图像像素缩放误差 - 计算CCD透镜的SNR

时间:2013-04-18 13:29:50

标签: c opencv image-processing type-conversion

我正在尝试计算从同一台数码相机拍摄的两张加载图像的信噪比。我们的想法是计算多个光线水平的信噪比,以获得显示CCD镜头信噪比的图表。

我现在面临的问题是;当我将第二图像(图像B)缩放为具有与第一图像(图像A)相同的平均像素强度时,所获得的值不是与第一图像相同的精确值。我认为问题是图像转换产生舍入误差的结果。

我用来计算SNR的方法是:

  1. 将图像转换为灰度
  2. 将图片转换为16位签名
  3. 从A
  4. 中减去图像B.
  5. 获取减法的平均像素强度
  6. 从A和B中减去该平均值(以消除一些噪音)
  7. 转换回8位无符号
  8. 获取两个图像的平均像素值
  9. 获取这些平均值的比率
  10. 按比例缩放图像B(16位无符号)以获得图像A的平均像素值 - 问题区域
  11. 转换回8位并计算平均像素强度
  12. 再次相互减去图像以消除最后的随机噪音
  13. 计算此减法的标准差
  14. 将标准差转换为差异
  15. 我是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左右)。

0 个答案:

没有答案