OpenCV对图像的性能测试
2018-06-17 23:58:42来源:未知 阅读 ()
最近在做图像算法,对图像性能指标进行测试。主要包括PSNR(峰值信噪比)、NC(归一化相关系数)、SSIM(结构相似性)等,下面对这三个指标做简单介绍。
PSNR:峰值信噪比,一种评价图像的客观标准,用来评估图像的保真性。峰值信噪比经常用作图像压缩等领域中信号重建质量的测量方法,它常简单地通过均方差(MSE)进行定义,使用两个m×n单色图像I和K。PSNR的单位为分贝dB。计算公式如下:
其中,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自带的“郁金香”图片,先生成数字指纹图像,比较图像的失真结果。
原图 数字指纹加密后
测试结果:
测试二:用原图和经过噪声攻击的图像进行测试。
测试结果:
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- OpenCV开发笔记(五十九):红胖子8分钟带你深入了解分水岭 2020-05-24
- opencv-12-高斯滤波-双边滤波(附C++代码实现) 2020-05-10
- opencv-11-中值滤波及自适应中值滤波 2020-05-03
- opencv调用nu-book/zxing-cpp识别二维码 2020-03-26
- 二值图像连通域标记算法优化 2020-03-11
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash