这道题是载入一幅带有有趣纹理的图像并用不同的模板(窗口,核)大小做高斯模糊(高斯平滑),然后比较用5*5大小的窗口平滑图像两次和用11*11大小的窗口平滑图像一次是否接近相同。
先说下我的做法,a部分我将每个不同的窗口大小模糊化后的图像生成后,还计算了每个模糊化后的图像与原始图像间的MSE值与PSNR值。(参见:http://zh.wikipedia.org/wiki/%E5%B3%B0%E5%80%BC%E4%BF%A1%E5%99%AA%E6%AF%94)
b部分我计算了两次5*5窗口大小的高斯模糊后的图像与一次11*11窗口大小的高斯模糊图像之间的MSE与PSNR。
代码:
1 #include <opencv/highgui.h> 2 #include <opencv/cv.h> 3 #include <opencv_libs.h> 4 #include <math.h> 5 6 /* 7 *《学习OpenCV》第五章第一题 8 * 完成时间:18:37 10/13 星期日 2013 9 * 作者:qdsclove@163.com 10 */ 11 12 /* 13 * function: calculate MSE & PSNR of two GrayScale(8-bit depth & one channel) images. 14 * param: img1 -- the first image. 15 * param: img2 -- the second image. 16 * param: dMSE -- the MSE of two images(output) 17 * param: dPSNR -- the PSNR of two images(output) 18 * return: 0 -- success; others -- failed. 19 */ 20 int calculateGrayImgsPSNR(IplImage* img1, IplImage* img2, double& dMSE, double& dPSNR) 21 { 22 if( !img1 || !img2 || 23 img1->nChannels != 1 || 24 img2->nChannels != 1 || 25 img1->depth != img2->depth || 26 img1->width != img2->width || 27 img1->height != img2->height ) 28 { 29 return -1; 30 } 31 int width = img1->width; 32 int height = img1->height; 33 34 // calculate MSE of the two images 35 double dSumOfSquares = 0; 36 for(int i = 0; i < height; i++) 37 { 38 char* pdata1 = img1->imageData + i * img1->widthStep; 39 char* pdata2 = img2->imageData + i *img2->widthStep; 40 for(int j = 0; j < width; j++ ) 41 { 42 uchar value1 = *(pdata1 + j); 43 uchar value2 = *(pdata2 + j); 44 45 double square = pow( (double)(value1 - value2), 2 ); 46 dSumOfSquares += square; 47 } 48 } 49 50 dMSE = dSumOfSquares / (width * height); 51 52 // this is means the two images are strictly same. 53 if(dMSE == 0) 54 { 55 dPSNR = -1; 56 return 0; 57 } 58 int iDepth = img1->depth; 59 int iMAX = pow( 2., iDepth) - 1; 60 61 dPSNR = 20 * log10(iMAX / (sqrt(dMSE))); 62 63 return 0; 64 } 65 66 int main() 67 { 68 const char * FILE_PATH = "Fig0333(a)(test_pattern_blurring_orig).tif"; 69 70 IplImage* src = cvLoadImage(FILE_PATH, CV_LOAD_IMAGE_UNCHANGED); 71 72 if(!src) 73 { 74 printf("Load image error. "); 75 return -1; 76 } 77 78 // Get the source image's size 79 CvSize srcSize = cvGetSize(src); 80 81 // 3 * 3 82 IplImage* dst_three_gaussian = cvCreateImage(srcSize, src->depth, src->nChannels); 83 // 5 * 5 84 IplImage* dst_five_gaussian = cvCreateImage(srcSize, src->depth, src->nChannels); 85 // 9 * 9 86 IplImage* dst_nine_gaussian = cvCreateImage(srcSize, src->depth, src->nChannels); 87 // 11 * 11 88 IplImage* dst_eleven_gaussian = cvCreateImage(srcSize, src->depth, src->nChannels); 89 // twice 5 * 5 90 IplImage* dst_twice_five_gaussian = cvCreateImage( srcSize, src->depth, src->nChannels ); 91 92 93 if( !dst_three_gaussian || !dst_five_gaussian || 94 !dst_nine_gaussian || !dst_eleven_gaussian || 95 !dst_twice_five_gaussian ) 96 { 97 printf("Create image error. "); 98 return -1; 99 } 100 101 cvSmooth(src, dst_three_gaussian, CV_GAUSSIAN, 3, 3); 102 cvSmooth(src, dst_five_gaussian, CV_GAUSSIAN, 5, 5); 103 cvSmooth(src, dst_nine_gaussian, CV_GAUSSIAN, 9, 9); 104 cvSmooth(src, dst_eleven_gaussian, CV_GAUSSIAN, 11, 11); 105 cvSmooth( dst_five_gaussian, dst_twice_five_gaussian, CV_GAUSSIAN, 5, 5 ); 106 107 cvShowImage("src", src); 108 cvShowImage("src - GAUSSIAN 3*3", dst_three_gaussian); 109 cvShowImage("src - GAUSSIAN 5*5", dst_five_gaussian); 110 cvShowImage("src - GAUSSIAN 9*9", dst_nine_gaussian); 111 cvShowImage("src - GAUSSIAN 11*11", dst_eleven_gaussian); 112 cvShowImage("src - GAUSSIAN 5*5 Twice", dst_twice_five_gaussian ); 113 114 // calculate the MSE and PSNR of the two images. 115 double dMSE, dPSNR; 116 // part a: 117 calculateGrayImgsPSNR(src, dst_three_gaussian, dMSE, dPSNR); 118 printf("source image & 3*3 GAUSSIAN: MSE: %f PSNR: %f ", dMSE, dPSNR); 119 calculateGrayImgsPSNR(src, dst_five_gaussian, dMSE, dPSNR); 120 printf("source image & 5*5 GAUSSIAN: MSE: %f PSNR: %f ", dMSE, dPSNR); 121 calculateGrayImgsPSNR(src, dst_nine_gaussian, dMSE, dPSNR); 122 printf("source image & 9*9 GAUSSIAN: MSE: %f PSNR: %f ", dMSE, dPSNR); 123 calculateGrayImgsPSNR(src, dst_eleven_gaussian, dMSE, dPSNR); 124 printf("source image & 11*11 GAUSSIAN: MSE: %f PSNR: %f ", dMSE, dPSNR); 125 126 // part b 127 puts("--------------------------- "); 128 calculateGrayImgsPSNR(src, dst_eleven_gaussian, dMSE, dPSNR); 129 printf("source image & eleven: MSE: %f PSNR: %f ", dMSE, dPSNR); 130 calculateGrayImgsPSNR(src, dst_twice_five_gaussian, dMSE, dPSNR); 131 printf("source image & twice five: MSE: %f PSNR: %f ", dMSE, dPSNR); 132 calculateGrayImgsPSNR(dst_eleven_gaussian, dst_twice_five_gaussian, dMSE, dPSNR); 133 printf("eleven & twice five: MSE: %f PSNR: %f ", dMSE, dPSNR); 134 135 cvWaitKey(0); 136 cvReleaseImage(&src); 137 cvReleaseImage(&dst_three_gaussian); 138 cvReleaseImage(&dst_five_gaussian); 139 cvReleaseImage(&dst_nine_gaussian); 140 cvReleaseImage(&dst_eleven_gaussian); 141 cvReleaseImage(&dst_twice_five_gaussian); 142 cvDestroyAllWindows(); 143 144 return 0; 145 }
运行结果:
a部分:
3*3:
5*5:
9*9:
11*11:
同时各个不同的窗口大小模糊化后的图像与原始图像之间的MSE与PSNR:
从图中可以看出,当窗口大小越大时,MSE增大,PSNR减小。
b部分:
两幅图像的PSNR与MSE:
众所周知的是在图像压缩中典型的PSNR比值在30-40dB之间,而我们这两幅平滑之后的图像PSNR为31.976534,所以这两幅图像是比较接近的。