0

同じデジタル カメラから取得した 2 つの読み込み済み画像の信号対雑音比を計算しようとしています。アイデアは、CCD レンズの信号対雑音比を示すグラフを実現するために、多数の光レベルで信号対雑音を計算することです。

私が現在直面している問題は次のとおりです。最初の画像 (画像 A) と同じ平均ピクセル強度を持つように 2 番目の画像 (画像 B) をスケーリングすると、得られる値は最初の画像と正確な値ではありません。問題は、画像変換による丸め誤差の結果だと思います。

SNR の計算に使用する方法は次のとおりです。

  1. 画像をグレースケールに変換
  2. 画像を 16 ビット符号付きに変換する
  3. A から画像 B を減算
  4. 減算の平均ピクセル強度を取得します
  5. その平均値を A と B から引きます (ノイズを除去するため)。
  6. 符号なし 8 ビットに戻す
  7. 両方の画像の平均ピクセル値を取得する
  8. それらの平均値の比率を取得します
  9. 画像 A の平均ピクセル値を取得する比率で画像 B (符号なし 16 ビット) をスケーリングします - 問題領域
  10. 8 ビットに戻して平均ピクセル強度を計算する
  11. 最後のランダム ノイズを除去するために、互いに画像を再度減算します。
  12. この減算の標準偏差を計算します
  13. 標準偏差を分散に変換する

私は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;
}

このプログラムの結果は次のとおりです。

画像 A のピクセル強度 = 138.292328

画像 B のピクセル強度 = 253.836456

比率 = 0.544809

スケーリング後の画像 B 強度 = 138.351196

CCD ノイズの分散 = 8.016509

ここでのプレゼンテーションでは、何が起こるのかを強調するためにさまざまな画像を使用しました。テストでは、画像はより近くなります (比率は約 0.992 になります)。

4

0 に答える 0