我正在尝试计算从同一台数码相机拍摄的两张加载图像的信噪比。我们的想法是计算多个光线水平的信噪比,以获得显示CCD镜头信噪比的图表。
我现在面临的问题是;当我将第二图像(图像B)缩放为具有与第一图像(图像A)相同的平均像素强度时,所获得的值不是与第一图像相同的精确值。我认为问题是图像转换产生舍入误差的结果。
我用来计算SNR的方法是:
我是OpenCV的新手和一般的编程,所以我们将非常感谢任何更好的方法和对特定问题的帮助。
int _tmain(int argc, _TCHAR* argv[])
{
float mean_A;
float mean_B1;
float var,mean_B;
float grey_B_mul;
float grey_sub2;
float o, standard, r;
IplImage *img = cvLoadImage("J:\\backup\\fotos\\IMG_0168.JPG", 3);//Define images
IplImage *img2 = cvLoadImage("J:\\backup\\fotos\\IMG_0164.JPG", 3);
IplImage *grayA = cvCreateImage(cvGetSize(img),IPL_DEPTH_8U, 1);
IplImage *grayB = cvCreateImage(cvGetSize(img),IPL_DEPTH_8U, 1);
IplImage *gray1 = cvCreateImage(cvGetSize(img),IPL_DEPTH_16U, 1);
IplImage *gray1S = cvCreateImage(cvGetSize(img),IPL_DEPTH_16S, 1);
IplImage *gray2S = cvCreateImage(cvGetSize(img),IPL_DEPTH_16S, 1);
IplImage *gray2 = cvCreateImage(cvGetSize(img),IPL_DEPTH_16U, 1);
IplImage *sub1 = cvCreateImage(cvGetSize(img),IPL_DEPTH_16S, 1);
IplImage *imgA = cvCreateImage(cvGetSize(img),IPL_DEPTH_8U, 1);
IplImage *imgA1 = cvCreateImage(cvGetSize(img),IPL_DEPTH_16S, 1);
IplImage *imgA1U = cvCreateImage(cvGetSize(img),IPL_DEPTH_16U, 1);
IplImage *imgB1U = cvCreateImage(cvGetSize(img),IPL_DEPTH_16U, 1);
IplImage *imgB1 = cvCreateImage(cvGetSize(img),IPL_DEPTH_16S, 1);
IplImage *imgB = cvCreateImage(cvGetSize(img),IPL_DEPTH_8U, 1);
IplImage *imgB_mul = cvCreateImage(cvGetSize(img),IPL_DEPTH_16U, 1);
IplImage *imgB_mull = cvCreateImage(cvGetSize(img),IPL_DEPTH_16U, 1);
IplImage *imgB_scaled = cvCreateImage(cvGetSize(img),IPL_DEPTH_16S, 1);
IplImage *imgBsc = cvCreateImage(cvGetSize(img),IPL_DEPTH_8U, 1);
IplImage *sub2 = cvCreateImage(cvGetSize(img),IPL_DEPTH_16S, 1);
IplImage *sub2U = cvCreateImage(cvGetSize(img),IPL_DEPTH_16U, 1);
IplImage *sub2_final = cvCreateImage(cvGetSize(img),IPL_DEPTH_8U, 1);
if (img->nChannels ==3)
{
cvCvtColor(img, grayA, CV_BGR2GRAY); //convert to grayscale
cvCvtColor(img2, grayB, CV_BGR2GRAY);
}
else
{
cvCopyImage(img,grayA);
cvCopyImage(img2,grayB);
}
CvScalar m = cvAvg(grayA, 0); //Calculate average pixel intensity
double z = m.val[0];
CvScalar n = cvAvg(grayB, 0); //Calculate average pixel intensity
double y = n.val[0];
if (z > 128) //Convert to 16 bit signed
{
cvConvertScale(grayA, gray1, 256.0, -32768);
cvConvertScale(gray1, gray1S, 1.0);
}
else
cvConvertScale(grayA, gray1S, 256.0, -32768);
if (y> 128)
{
cvConvertScale(grayB, gray2, 256.0, -32768);
cvConvertScale(gray2, gray2S, 1.0);
}
else
cvConvertScale(grayB, gray2S, 256.0, -32768);
cvNamedWindow("CCD noise",1);
cvNamedWindow("Image A",1);
cvNamedWindow("Image B scaled",1);
cvSub(gray1S,gray2S, sub1); //Subtract images
cvSub(gray1S,sub1, imgA1);
cvSub(gray2S,sub1, imgB1);
cvConvertScale(imgA1, imgA1U, 1.0, +32768 );
cvConvertScale(imgB1, imgB1U, 1.0, +32768 );
cvConvertScale(imgA1U, imgA, 1.0/256);
cvConvertScale(imgB1U, imgB, 1.0/256);
CvScalar d = cvAvg(imgB, 0); //Calculate average pixel intensity
mean_B = d.val[0];
CvScalar e = cvAvg(imgA, 0); //Calculate average pixel intensity
mean_A = e.val[0];
printf("Image A pixel intensity = %f\n", mean_A);
printf("Image B pixel intensity = %f\n", mean_B);
r = mean_A/mean_B; // Ratio between average pixel intensities of image A and B
printf("r = %f\n", r);
for( int a = 0; a < imgB1U->height; a++ ) //Scale image B to achieve same average pixel intensity as image A
{
for( int b = 0; b < imgB1U->width; b++ )
{
CvScalar pixel = cvGet2D(imgB1U, a, b);
o = pixel.val[0]*r;
CvScalar p;
p.val[0] = o;
cvSet2D(imgB_mul, a, b, p);
}
}
cvConvertScale(imgB_mul, imgBsc, 1.0/256); //Convert back to 8 bit
CvScalar c = cvAvg(imgBsc, 0); //Calculate average pixel intensity
mean_B1 = c.val[0];
printf("Image B intensity after scaling = %f\n", mean_B1);
cvConvertScale(imgB_mul, imgB_scaled, 1.0, -32768);
cvSub(imgA1,imgB_scaled, sub2); //Final subtraction to calculte standard deviation
cvConvertScale(sub2, sub2U, 1.0, +32768 );
cvConvertScale(sub2U, sub2_final, 1.0/256);
CvScalar t,std;
cvAvgSdv(sub2_final, &t, &std); //Calculate std deviation
standard = std.val[0];
var = (standard*standard)/2; //Square std deviation and devide by 2 for variance
printf("Variance camera noise is = %f\n", var);
cvShowImage("Image A",imgA);
cvShowImage("Image B scaled",imgBsc);
cvShowImage("CCD noise",sub2);
cvWaitKey(0); //To terminate images
cvDestroyWindow("CCD gain");
cvDestroyWindow("Image A");
cvDestroyWindow("Image B scaled");
cvReleaseImage(&img);
cvReleaseImage(&img2);
cvReleaseImage(&gray1);
cvReleaseImage(&gray1S);
cvReleaseImage(&gray2S);
cvReleaseImage(&gray2);
cvReleaseImage(&sub1);
cvReleaseImage(&sub2);
cvReleaseImage(&imgA);
cvReleaseImage(&imgA1);
cvReleaseImage(&imgA1U);
cvReleaseImage(&imgB);
cvReleaseImage(&imgB1);
cvReleaseImage(&imgB1U);
cvReleaseImage(&imgB_mul);
cvReleaseImage(&imgB_mull);
cvReleaseImage(&imgBsc);
cvReleaseImage(&imgB_scaled);
cvReleaseImage(&sub2U);
cvReleaseImage(&sub2_final);
return 0;
}
该计划的结果如下:
图像像素强度= 138.292328
图像B像素强度= 253.836456
比率= 0.544809
缩放后的图像B强度= 138.351196
CCD噪声的变化= 8.016509
我在这里使用不同的图像来强调应该发生的事情。在测试中,图像将更加接近(比率将在0.992左右)。