Add SSIM function based on work code from JM
This commit is contained in:
1 parent
074091340c
commit
7cb42e65aa
1 file changed
+97
-24
@@ -390,30 +390,30 @@ Void PlaYUVerFrame::FrameToBuffer( Pel *output_buffer )
|
||||
memcpy( output_buffer + frame_bytes_input * 5 / 4, &m_pppcInputPel[CHROMA_V][0][0], frame_bytes_input / 4 * sizeof(Pel) );
|
||||
break;
|
||||
case YUV444p:
|
||||
memcpy( output_buffer + frame_bytes_input * 0, &m_pppcInputPel[LUMA][0][0], frame_bytes_input * sizeof(Pel) );
|
||||
memcpy( output_buffer + frame_bytes_input * 1, &m_pppcInputPel[CHROMA_U][0][0], frame_bytes_input * sizeof(Pel) );
|
||||
memcpy( output_buffer + frame_bytes_input * 2, &m_pppcInputPel[CHROMA_V][0][0],frame_bytes_input * sizeof(Pel) );
|
||||
memcpy( output_buffer + frame_bytes_input * 0, &m_pppcInputPel[LUMA][0][0], frame_bytes_input * sizeof(Pel) );
|
||||
memcpy( output_buffer + frame_bytes_input * 1, &m_pppcInputPel[CHROMA_U][0][0], frame_bytes_input * sizeof(Pel) );
|
||||
memcpy( output_buffer + frame_bytes_input * 2, &m_pppcInputPel[CHROMA_V][0][0], frame_bytes_input * sizeof(Pel) );
|
||||
break;
|
||||
case YUV422p:
|
||||
memcpy( output_buffer + frame_bytes_input * 0,&m_pppcInputPel[LUMA][0][0], frame_bytes_input * sizeof(Pel) );
|
||||
memcpy( output_buffer + frame_bytes_input * 1,&m_pppcInputPel[CHROMA_U][0][0], frame_bytes_input / 2 * sizeof(Pel) );
|
||||
memcpy( output_buffer + frame_bytes_input * 3 / 2,&m_pppcInputPel[CHROMA_V][0][0], frame_bytes_input / 2 * sizeof(Pel) );
|
||||
memcpy( output_buffer + frame_bytes_input * 0, &m_pppcInputPel[LUMA][0][0], frame_bytes_input * sizeof(Pel) );
|
||||
memcpy( output_buffer + frame_bytes_input * 1, &m_pppcInputPel[CHROMA_U][0][0], frame_bytes_input / 2 * sizeof(Pel) );
|
||||
memcpy( output_buffer + frame_bytes_input * 3 / 2, &m_pppcInputPel[CHROMA_V][0][0], frame_bytes_input / 2 * sizeof(Pel) );
|
||||
break;
|
||||
case YUYV422:
|
||||
for( UInt i = 0; i < m_uiHeight * m_uiWidth / 2; i++ )
|
||||
{
|
||||
*output_buffer++ = *pInputPelY++ ;
|
||||
*output_buffer++ = *pInputPelU++ ;
|
||||
*output_buffer++ = *pInputPelY++ ;
|
||||
*output_buffer++ = *pInputPelV++ ;
|
||||
*output_buffer++ = *pInputPelY++;
|
||||
*output_buffer++ = *pInputPelU++;
|
||||
*output_buffer++ = *pInputPelY++;
|
||||
*output_buffer++ = *pInputPelV++;
|
||||
}
|
||||
break;
|
||||
case GRAY:
|
||||
memcpy( output_buffer + frame_bytes_input * 0, &m_pppcInputPel[LUMA][0][0], frame_bytes_input * sizeof(Pel) );
|
||||
memcpy( output_buffer + frame_bytes_input * 0, &m_pppcInputPel[LUMA][0][0], frame_bytes_input * sizeof(Pel) );
|
||||
break;
|
||||
case RGB8:
|
||||
FrametoRGB8();
|
||||
memcpy( output_buffer, pcRGBPelInterlaced, frame_bytes_input * sizeof(Pel) * 3 );
|
||||
memcpy( output_buffer, pcRGBPelInterlaced, frame_bytes_input * sizeof(Pel) * 3 );
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -658,19 +658,19 @@ cv::Mat PlaYUVerFrame::getCvMat()
|
||||
Int cvType = CV_8UC3;
|
||||
switch( m_iPixelFormat )
|
||||
{
|
||||
case YUV420p:
|
||||
case YUV444p:
|
||||
case YUV422p:
|
||||
case YUYV422:
|
||||
case YUV420p:
|
||||
case YUV444p:
|
||||
case YUV422p:
|
||||
case YUYV422:
|
||||
cvType = CV_8UC3;
|
||||
break;
|
||||
case GRAY:
|
||||
case GRAY:
|
||||
cvType = CV_8UC1;
|
||||
break;
|
||||
case RGB8:
|
||||
case RGB8:
|
||||
cvType = CV_8UC3;
|
||||
break;
|
||||
default:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
cv::Mat opencvFrame( m_uiHeight, m_uiWidth, cvType );
|
||||
@@ -687,7 +687,6 @@ cv::Mat PlaYUVerFrame::getCvMat()
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef USE_OPENCV
|
||||
Void PlaYUVerFrame::copyFrom( cv::Mat* opencvFrame )
|
||||
{
|
||||
@@ -695,13 +694,13 @@ Void PlaYUVerFrame::copyFrom( cv::Mat* opencvFrame )
|
||||
{
|
||||
switch( opencvFrame->channels() )
|
||||
{
|
||||
case 1:
|
||||
case 1:
|
||||
m_iPixelFormat = GRAY;
|
||||
break;
|
||||
case 3:
|
||||
case 3:
|
||||
m_iPixelFormat = RGB8;
|
||||
break;
|
||||
default:
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -800,10 +799,84 @@ Double PlaYUVerFrame::getPSNR( PlaYUVerFrame* Org, Int component )
|
||||
return dPSNR;
|
||||
}
|
||||
|
||||
float compute_ssim( Pel **refImg, Pel **encImg, Int width, Int height, Int win_width, Int win_height, Int max_pel_value_comp, Int overlapSize )
|
||||
{
|
||||
static const float K1 = 0.01f, K2 = 0.03f;
|
||||
float max_pix_value_sqd;
|
||||
float C1, C2;
|
||||
float win_pixels = ( float )( win_width * win_height );
|
||||
#ifdef UNBIASED_VARIANCE
|
||||
float win_pixels_bias = win_pixels - 1;
|
||||
#else
|
||||
float win_pixels_bias = win_pixels;
|
||||
#endif
|
||||
float mb_ssim, meanOrg, meanEnc;
|
||||
float varOrg, varEnc, covOrgEnc;
|
||||
int imeanOrg, imeanEnc, ivarOrg, ivarEnc, icovOrgEnc;
|
||||
float cur_distortion = 0.0;
|
||||
int i, j, n, m, win_cnt = 0;
|
||||
|
||||
max_pix_value_sqd = ( float )( max_pel_value_comp * max_pel_value_comp );
|
||||
C1 = K1 * K1 * max_pix_value_sqd;
|
||||
C2 = K2 * K2 * max_pix_value_sqd;
|
||||
|
||||
for( j = 0; j <= height - win_height; j += overlapSize )
|
||||
{
|
||||
for( i = 0; i <= width - win_width; i += overlapSize )
|
||||
{
|
||||
imeanOrg = 0;
|
||||
imeanEnc = 0;
|
||||
ivarOrg = 0;
|
||||
ivarEnc = 0;
|
||||
icovOrgEnc = 0;
|
||||
|
||||
for( n = j; n < j + win_height; n++ )
|
||||
{
|
||||
for( m = i; m < i + win_width; m++ )
|
||||
{
|
||||
imeanOrg += refImg[n][m];
|
||||
imeanEnc += encImg[n][m];
|
||||
ivarOrg += refImg[n][m] * refImg[n][m];
|
||||
ivarEnc += encImg[n][m] * encImg[n][m];
|
||||
icovOrgEnc += refImg[n][m] * encImg[n][m];
|
||||
}
|
||||
}
|
||||
|
||||
meanOrg = ( float )imeanOrg / win_pixels;
|
||||
meanEnc = ( float )imeanEnc / win_pixels;
|
||||
|
||||
varOrg = ( ( float )ivarOrg - ( ( float )imeanOrg ) * meanOrg ) / win_pixels_bias;
|
||||
varEnc = ( ( float )ivarEnc - ( ( float )imeanEnc ) * meanEnc ) / win_pixels_bias;
|
||||
covOrgEnc = ( ( float )icovOrgEnc - ( ( float )imeanOrg ) * meanEnc ) / win_pixels_bias;
|
||||
|
||||
mb_ssim = ( float )( ( 2.0 * meanOrg * meanEnc + C1 ) * ( 2.0 * covOrgEnc + C2 ) );
|
||||
mb_ssim /= ( float )( meanOrg * meanOrg + meanEnc * meanEnc + C1 ) * ( varOrg + varEnc + C2 );
|
||||
|
||||
cur_distortion += mb_ssim;
|
||||
win_cnt++;
|
||||
}
|
||||
}
|
||||
|
||||
cur_distortion /= ( float )win_cnt;
|
||||
|
||||
if( cur_distortion >= 1.0 && cur_distortion < 1.01 ) // avoid float accuracy problem at very low QP(e.g.2)
|
||||
cur_distortion = 1.0;
|
||||
|
||||
return cur_distortion;
|
||||
}
|
||||
|
||||
Double PlaYUVerFrame::getSSIM( PlaYUVerFrame* Org, Int component )
|
||||
{
|
||||
Double dSSIM = 1;
|
||||
if( component == LUMA )
|
||||
{
|
||||
dSSIM = compute_ssim( m_pppcInputPel[component], Org->getPelBufferYUV()[component], m_uiWidth, m_uiHeight, 8, 8, 255, 8 );
|
||||
}
|
||||
else
|
||||
{
|
||||
dSSIM = compute_ssim( m_pppcInputPel[component], Org->getPelBufferYUV()[component], getChromaWidth(), getChromaHeight(), 4, 4, 255, 8 );
|
||||
}
|
||||
return dSSIM;
|
||||
}
|
||||
|
||||
} // NAMESPACE
|
||||
} // NAMESPACE
|
||||
Reference in new issue
Block a user