程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> OpenCV對圖像的性能測試,opencv性能測試

OpenCV對圖像的性能測試,opencv性能測試

編輯:C++入門知識

OpenCV對圖像的性能測試,opencv性能測試


最近在做圖像算法,對圖像性能指標進行測試。主要包括PSNR(峰值信噪比)、NC(歸一化相關系數)、SSIM(結構相似性)等,下面對這三個指標做簡單介紹。

 

PSNR:峰值信噪比,一種評價圖像的客觀標准,用來評估圖像的保真性。峰值信噪比經常用作圖像壓縮等領域中信號重建質量的測量方法,它常簡單地通過均方差(MSE)進行定義,使用兩個m×n單色圖像IK。PSNR的單位為分貝dB。計算公式如下:

                                                              \mathit{MSE} = \frac{1}{mn}\sum_{i=0}^{m-1}\sum_{j=0}^{n-1} ||I(i,j) - K(i,j)||^2

                                                              \mathit{PSNR} = 10 \cdot \log_{10} \left( \frac{\mathit{MAX}_I^2}{\mathit{MSE}} \right) = 20 \cdot \log_{10} \left( \frac{\mathit{MAX}_I}{\sqrt{\mathit{MSE}}} \right)

其中,MAXI是表示圖像點顏色的最大數值,如果每個采樣點用 8 位表示,那麼就是 255。PSNR值越大,就代表失真越少,圖像壓縮中典型的峰值信噪比值在 30 到 40dB 之間,小於30dB時考慮圖像無法忍受。

 

NC:對兩幅圖像進行相似度的衡量,除了用眼睛觀察的方法外,我們可以更加精確地用數據來客觀的評估歸一化,歸一化的相關系數(NC)提供了度量工具,它可以用來評估圖像的魯棒性

                                                                       

其中,w(x,y)和w'(x,y)代表兩張圖像(水印和提取水印),M、N為圖像分標率,歸一化相關系數用來表示原始水印與提取水印的相似度,取值在0到1之間,越接近1表示魯棒性越好。

 

SSIM:(structural similarity index),結構相似性,是一種衡量兩幅圖像相似度的指標,也是一種全參考的圖像質量評價指標,它分別從亮度對比度結構三方面度量圖像相似性。Wiki中的計算公式:

 

                                                                               

 

 

 

 

其中  是 的平均值, 是  的平均值,  是  的方差,  是  的方差,  是  和 的標准差。  是用來維持穩定的常數。 是像素值的動態范圍。  ,  。結構相似性的范圍為  到  。當兩張圖像一模一樣時,SSIM的值等於1。

 

另一篇博文中的計算公式如下,也可以使用。http://blog.csdn.net/xiaxiazls/article/details/47952611

 

                                                           

 

其中ux、uy分別表示圖像X和Y的均值,σX、σY分別表示圖像X和Y的方差,σXY表示圖像X和Y的協方差,即

 

                                                                  

 

C1、C2、C3為常數,為了避免分母為0的情況,通常取C1=(K1*L)^2, C2=(K2*L)^2, C3=C2/2, 一般地K1=0.01, K2=0.03, L=255. 則

 

                                                                                       

 

在實際應用中,可以利用滑動窗將圖像分塊,令分塊總數為N,考慮到窗口形狀對分塊的影響,采用高斯加權計算每一窗口的均值、方差以及協方差,然後計算對應塊的結構相似度SSIM,最後將平均值作為兩圖像的結構相似性度量,即平均結構相似性MSSIM:

 

                                                                                         

 

 

 

另外可以參考SSIM的另一篇博文:  http://blog.csdn.net/xiaxiazls/article/details/47952611

 

 

 

程序如下:

環境:win7   VC++6.0   OpenCV1.0

其中 src 是原圖像,key是指經過簡單的數字指紋加密的圖像或失真的圖像。(這裡用到的數字指紋加密是指將圖像隨機數量像素點進行小范圍的改變,肉眼無法辨別)。

 

  1 #include <cstdio>
  2 #include <cmath>
  3 #include <ctime>
  4 #include <cstdlib>
  5 
  6 #include "cv.h"  
  7 #include "highgui.h"  
  8 
  9 
 10 //計算兩幅圖像的保真性
 11 //參數: src 原圖像
 12 //      key 指紋加密的圖像
 13 
 14 double Psnr( IplImage* src, IplImage* key ) {
 15     int width = src->width;       //圖像寬
 16     int height = src->height;     //圖像高
 17     
 18     double mse = 0.0;             //MSE為均方差
 19 
 20     CvScalar s_src;               //原圖像的像素通道結構體
 21     CvScalar s_key;               //加密後的像素通道結構體
 22 
 23                                   //計算MSE——均方差
 24     for( int row = 0; row < height; row++ ) {
 25         for( int col = 0; col < width; col++ ) {
 26             s_src = cvGet2D( src, row, col );   
 27             s_key = cvGet2D( key, row, col );
 28             double src_r = s_src.val[0];        //取出G通道的像素值
 29             double key_r = s_key.val[0];
 30             //if( src_r != key_r ) {
 31             //printf( "%.lf %.lf\n", src_r, key_r );
 32             //char ch = getchar();
 33             //}
 34             mse += ( src_r - key_r ) * ( src_r - key_r );   //計算方差
 35         }
 36     }
 37 
 38     const double MAX = 255.0;               //最大峰值為255
 39     
 40     //方法一
 41     double temp = MAX * MAX * ( double )width * ( double )height;
 42     double r = temp / mse;
 43     r = 10.0 * log10( r );
 44     
 45     //方法二,計算結果是一樣的
 46     //mse = mse / ( width * height );
 47     //printf( "均方誤差: %lf\n", mse );
 48     //mse = sqrt( mse );
 49     //double temp = MAX;
 50     //double r = temp / mse;
 51     //r = 20.0 * log10( r );
 52 
 53     //打印的中間結果信息
 54     //printf( "temp: %lf\n", temp );
 55     //printf( "sum: %lf\n", sum );
 56      //printf( "%lf\n", r );
 57     
 58     return r;
 59 }
 60 
 61 
 62 
 63 //計算兩幅圖像的魯棒性
 64 //參數: src 原圖像
 65 //      key 指紋加密的圖像
 66 
 67 double Nc( IplImage* src, IplImage* key ) {
 68     int width = src->width;       //圖像寬
 69     int height = src->height;     //圖像高
 70 
 71     CvScalar s_src;               //原圖像的像素通道結構體
 72     CvScalar s_key;               //加密後的像素通道結構體
 73 
 74     double d = 0.0;
 75     double d_src = 0.0;
 76     double d_key = 0.0;
 77 
 78     for( int row = 0; row < height; row++ ) {
 79         for( int col = 0; col < width; col++ ) {
 80             s_src = cvGet2D( src, row, col );   
 81             s_key = cvGet2D( key, row, col );
 82             double src_r = s_src.val[0];        //取出G通道的像素值
 83             double key_r = s_key.val[0];
 84             d += src_r * key_r;
 85             d_src += src_r * src_r;
 86             d_key += key_r * key_r;
 87         }
 88     }
 89     
 90     //nc是魯棒性指標
 91     double nc = 0.0;
 92     nc = d / ( sqrt( d_src ) * sqrt( d_key ) );
 93 
 94     return nc;
 95 }
 96 
 97 
 98 
 99 //計算兩幅圖像的結構相似性
100 //參數: src 原圖像
101 //      key 指紋加密的圖像
102 
103 double Ssim( IplImage* src, IplImage* key ) {
104     int width = src->width;       //圖像寬
105     int height = src->height;     //圖像高
106 
107     CvScalar s_src;               //原圖像的像素通道結構體
108     CvScalar s_key;               //加密後的像素通道結構體
109 
110     double mu_src = 0.0;          //原圖像均值
111     double mu_key = 0.0;          //加密後的圖像均值
112 
113     int row, col;
114     for( row = 0; row < height; row++ ) {
115         for( col = 0; col < width; col++ ) {
116             s_src = cvGet2D( src, row, col );   
117             s_key = cvGet2D( key, row, col );
118             double src_r = s_src.val[0];        //取出G通道的像素值
119             double key_r = s_key.val[0];
120             mu_src += src_r;
121             mu_key += key_r;
122         }
123     }
124 
125     mu_src = mu_src / ( width * height );       //原圖像均值
126     mu_key = mu_key / ( width * height );       //加密圖像均值
127 
128     //打印的中間結果信息
129     //printf( "src的均值: %lf\n", mu_src );
130     //printf( "key的均值: %lf\n", mu_key );
131 
132     double sigma_src2 = 0.0;                    //原圖像方差,即sigma_src^2
133     double sigma_key2 = 0.0;                    //加密圖像方差,即sigma_key^2
134     double sigma_s_k2 = 0.0;                    //原圖和加密圖像的方差,即sigma_s_k^2
135 
136     double sigma_src = 0.0;                     //原圖像標准差
137     double sigma_key = 0.0;                     //加密圖像標准差
138     double sigma_s_k = 0.0;                     //原圖像和加密圖像的標准差
139 
140     for( row = 0; row < height; row++ ) {
141         for( col = 0; col < width; col++ ) {
142             s_src = cvGet2D( src, row, col );   
143             s_key = cvGet2D( key, row, col );
144             double src_r = s_src.val[0];        //取出G通道的像素值
145             double key_r = s_key.val[0];
146             sigma_src2 += ( src_r - mu_src ) * ( src_r - mu_src );
147             sigma_key2 += ( key_r - mu_key ) * ( key_r - mu_key );
148             sigma_s_k2 += ( src_r - mu_src ) * ( key_r - mu_key ); 
149         }
150     }
151 
152     sigma_src2 = sigma_src2 / ( width * height - 1 );
153     sigma_key2 = sigma_key2 / ( width * height - 1 );
154     sigma_s_k2 = sigma_s_k2 / ( width * height - 1 );
155 
156     sigma_src = sqrt( sigma_src2 );
157     sigma_key = sqrt( sigma_key2 );
158     sigma_s_k = sqrt( sigma_s_k2 );
159 
160     //打印的中間結果信息
161     //printf( "sigma_src: %lf\n", sigma_src );
162     //printf( "sigma_key: %lf\n", sigma_key );
163     //printf( "sigma_s_k: %lf\n", sigma_s_k );
164 
165     //固定參數,為常量
166     //c1,c2,c3是用來維持穩定的常數
167     //MAX是像素值的動態范圍
168     const double k1 = 0.01;
169     const double k2 = 0.03;
170     const int MAX = 255;
171     
172     double c1 = ( k1 * MAX ) * ( k1 * MAX );
173     double c2 = ( k2 * MAX ) * ( k2 * MAX );
174     double c3 = c2 / 2;
175 
176     //亮度、對比度、結構三方面度量圖像相似性
177     double light = ( 2 * mu_src * mu_key + c1 ) / ( mu_src * mu_src + mu_key * mu_key + c1 );
178     double contrast = ( 2 * sigma_src * sigma_key + c2 ) / ( sigma_src2 + sigma_key2 +c2 );
179     double structure = ( sigma_s_k2 + c3 ) / ( sigma_src * sigma_key + c3 );
180 
181     //打印的中間結果信息
182     //printf( "light: %lf\n", light );
183     //printf( "contrast: %lf\n", contrast );
184     //printf( "structure: %lf\n", structure );
185 
186     //方法一
187     //亮度 * 對比度 * 結構相似度
188     double ssim = light * contrast * structure;
189 
190     //方法二,計算結果是一樣的
191     //double ssim = light * ( ( 2 * sigma_s_k2 + c2 ) / (sigma_src2 + sigma_key2 + c2 ) );
192 
193     return ssim;
194 }
195 
196 void KeyImg( IplImage* src ) {
197     int n = 0;
198     int width = src->width;       //圖像寬
199     int height = src->height;     //圖像高
200 
201     printf( "圖像寬: %d, 高: %d\n", width, height );
202     printf( "輸入嵌入的像素點位數: " );
203     scanf( "%d", &n );
204     int count = 0;
205     
206     srand( (unsigned)time(NULL) );
207 
208     CvScalar s;
209 
210     IplImage* keyImg;
211     keyImg = cvCreateImage( cvGetSize( src ), IPL_DEPTH_8U, 1 );
212     keyImg = cvCloneImage( src );
213 
214     while( count < n ) {
215         int x = rand() % width;
216         int y = rand() % height;
217         s = cvGet2D( keyImg, y, x );
218         double b = s.val[0];
219         double g = s.val[1];
220         double r = s.val[2];
221         //printf( "修改前: %0.lf, %0.lf, %0.lf\n  ", s.val[0], s.val[1], s.val[2] );
222         int temp = rand() % 2;
223         if( temp == 0 ) {
224             s.val[0] -= 10.0;
225         }
226         else if( temp == 1 ) {
227             s.val[0] += 10.0;
228         }
229         cvSet2D( keyImg, y, x, s );
230         //s = cvGet2D( keyImg, y, x );
231         //printf( "修改後: %0.lf\n", s.val[0] );
232         count++;
233     }
234     
235     cvSaveImage( "Test.bmp", keyImg );
236     //cvNamedWindow("image", CV_WINDOW_AUTOSIZE); //創建窗口
237     //cvShowImage("image", keyImg); //顯示圖像
238     cvWaitKey(0);
239     printf( "圖像生成成功!\n" );
240 }
241 
242 
243 int main() {
244     IplImage* src = NULL;
245     IplImage* key = NULL;
246     
247     
248     src = cvLoadImage( "Flower.bmp", CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR );
249 
250     //生成一張加密的指紋圖片
251     //KeyImg( src );
252     key = cvLoadImage( "水印Flower.bmp", CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR );
253 
254     double psnr = 0.0;
255     double nc = 0.0;
256     double ssim = 0.0;
257     psnr = Psnr( src, key );
258     nc = Nc( src, key );
259     ssim = Ssim( src, key );
260     printf( "保真性: %lf\n", psnr );
261     printf( "魯棒性: %lf\n", nc );
262     printf( "結構相似性: %lf\n", ssim );
263     return 0;
264 }

 

測試一:使用Windows自帶的“郁金香”圖片,先生成數字指紋圖像,比較圖像的失真結果。

         

                                原圖                                                                              數字指紋加密後

 

測試結果:

 

測試二:用原圖和經過噪聲攻擊的圖像進行測試。

  

 

測試結果:

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved