图像的七个不变矩 可用于图像的匹配

http://blog.csdn.net/qq_18343569/article/details/46913501

图像的几何不变矩

矩特征主要表征了图像区域的几何特征,又称为几何矩, 由于其具有旋转、平移、尺度等特性的不变特征,所以又称其为不变矩。在图像处理中,几何不变矩可以作为一个重要的特征来表示物体,可以据此特征来对图像进行分类等操作。

1.     HU矩

几何矩是由Hu(Visual pattern recognition by moment invariants)在1962年提出的,图像f(x,y)的(p+q)阶几何矩定义为

Mpq =∫∫(x^p)*(y^q)f(x,y)dxdy(p,q = 0,1,……∞)

矩在统计学中被用来反映随机变量的分布情况,推广到力学中,它被用作刻画空间物体的质量分布。同样的道理,如果我们将图像的灰度值看作是一个二维或三维的密度分布函数,那么矩方法即可用于图像分析领域并用作图像特征的提取。最常用的,物体的零阶矩表示了图像的“质量”:

Moo= ∫∫f(x,y )dxdy

一阶矩(M01,M10)用于确定图像质心( Xc,Yc):

Xc = M10/M00;Yc = M01/M00;

若将坐标原点移至 Xc和 Yc处,就得到了对于图像位移不变的中心矩。如

Upq =∫∫[(x-Xc)^p]*[(y-Yc)^q]f(x,y)dxdy。

Hu在文中提出了7个几何矩的不变量,这些不变量满足于图像平移、伸缩和旋转不变。如果定义

Zpq=Upq/(U20 + U02)^(p+q+2),

Hu 的7种矩为:

H1=Z20+Z02;H1=(Z20+Z02)^2+4Z11^2;......

矩是描述图像特征的算子,它在模式识别与图像分析领域中有重要的应用.迄今为止,常见的矩描述子可以分为以下几种:几何矩、正交矩、复数矩和旋转矩.其中几何矩提出的时间最早且形式简单,对它的研究最为充分。几何矩对简单图像有一定的描述能力,他虽然在区分度上不如其他三种矩,但与其他几种算子比较起来,他极其的简单,一般只需用一个数字就可表达。所以,一般我们是用来做大粒度的区分,用来过滤显然不相关的文档。

比如在图形库中,可能有100万幅图,也许只有200幅图是我们想要的。使用一维的几何矩的话,就可以对几何矩进行排序,建立索引,然后选出与目标图的几何矩最近的2000幅图作比较就好了。而对于其他的矩来说,由于一般是多维的关系,一般不好排序,只能顺序查找,自然速度有巨大的差别.所以。虽然几何矩不太能选出最像的,但可以快速排除不像的,提高搜索效率。

MATLAB代码:

img=

[html] view plain copy

  1. invariable_moment(imread(‘lena.jpg‘));

[html] view plain copy

  1. function inv_m7 = invariable_moment(in_image)
  2. % 功能:计算图像的Hu的七个不变矩
  3. % 输入:in_image-RGB图像
  4. % 输出:inv_m7-七个不变矩
  5. % 将输入的RGB图像转换为灰度图像
  6. image=rgb2gray(in_image);
  7. %将图像矩阵的数据类型转换成双精度型
  8. image=double(image);
  9. %%%=================计算 、 、 =========================
  10. %计算灰度图像的零阶几何矩
  11. m00=sum(sum(image));
  12. m10=0;
  13. m01=0;
  14. [row,col]=size(image);
  15. for i=1:row
  16. for j=1:col
  17. m10=m10+i*image(i,j);
  18. m01=m01+j*image(i,j);
  19. end
  20. end
  21. %%%=================计算 、 ================================
  22. u10=m10/m00;
  23. u01=m01/m00;
  24. %%%=================计算图像的二阶几何矩、三阶几何矩============
  25. m20 = 0;m02 = 0;m11 = 0;m30 = 0;m12 = 0;m21 = 0;m03 = 0;
  26. for i=1:row
  27. for j=1:col
  28. m20=m20+i^2*image(i,j);
  29. m02=m02+j^2*image(i,j);
  30. m11=m11+i*j*image(i,j);
  31. m30=m30+i^3*image(i,j);
  32. m03=m03+j^3*image(i,j);
  33. m12=m12+i*j^2*image(i,j);
  34. m21=m21+i^2*j*image(i,j);
  35. end
  36. end
  37. %%%=================计算图像的二阶中心矩、三阶中心矩============
  38. y00=m00;
  39. y10=0;
  40. y01=0;
  41. y11=m11-u01*m10;
  42. y20=m20-u10*m10;
  43. y02=m02-u01*m01;
  44. y30=m30-3*u10*m20+2*u10^2*m10;
  45. y12=m12-2*u01*m11-u10*m02+2*u01^2*m10;
  46. y21=m21-2*u10*m11-u01*m20+2*u10^2*m01;
  47. y03=m03-3*u01*m02+2*u01^2*m01;
  48. %%%=================计算图像的归格化中心矩====================
  49. n20=y20/m00^2;
  50. n02=y02/m00^2;
  51. n11=y11/m00^2;
  52. n30=y30/m00^2.5;
  53. n03=y03/m00^2.5;
  54. n12=y12/m00^2.5;
  55. n21=y21/m00^2.5;
  56. %%%=================计算图像的七个不变矩======================
  57. h1 = n20 + n02;
  58. h2 = (n20-n02)^2 + 4*(n11)^2;
  59. h3 = (n30-3*n12)^2 + (3*n21-n03)^2;
  60. h4 = (n30+n12)^2 + (n21+n03)^2;
  61. h5 = (n30-3*n12)*(n30+n12)*((n30+n12)^2-3*(n21+n03)^2)+(3*n21-n03)*(n21+n03)*(3*(n30+n12)^2-(n21+n03)^2);
  62. h6 = (n20-n02)*((n30+n12)^2-(n21+n03)^2)+4*n11*(n30+n12)*(n21+n03);
  63. h7 = (3*n21-n03)*(n30+n12)*((n30+n12)^2-3*(n21+n03)^2)+(3*n12-n30)*(n21+n03)*(3*(n30+n12)^2-(n21+n03)^2);
  64. inv_m7= [h1 h2 h3 h4 h5 h6 h7];

c++代码:

[html] view plain copy

  1. /*===============================================//
  2. 功能:不变矩匹配
  3. 时间:3/28/2011 SkySeraph HQU
  4. 参考:
  5. //===============================================*/
  6. #include "iostream"
  7. usingnamespace std;
  8. #include "cv.h"
  9. #include "highgui.h"
  10. #include "math.h"
  11. #pragma comment(lib,"highgui.lib")
  12. #pragma comment(lib,"cv.lib")
  13. #pragma comment(lib,"cvaux.lib")
  14. #pragma comment(lib,"cxcore.lib")
  15. constchar* filename ="D:\\My Documents\\My Pictures\\Images\\1.bmp";
  16. constchar* filename2 ="D:\\My Documents\\My Pictures\\Images\\2.bmp";
  17. /*=============================================*/
  18. double M[7] = {0}; //HU不变矩
  19. bool HuMoment(IplImage* img)
  20. {
  21. int bmpWidth = img->width;
  22. int bmpHeight = img->height;
  23. int bmpStep = img->widthStep;
  24. int bmpChannels = img->nChannels;
  25. uchar*pBmpBuf = (uchar*)img->imageData;
  26. double m00=0,m11=0,m20=0,m02=0,m30=0,m03=0,m12=0,m21=0; //中心矩
  27. double x0=0,y0=0; //计算中心距时所使用的临时变量(x-x‘)
  28. double u20=0,u02=0,u11=0,u30=0,u03=0,u12=0,u21=0;//规范化后的中心矩
  29. //double M[7]; //HU不变矩
  30. double t1=0,t2=0,t3=0,t4=0,t5=0;//临时变量,
  31. //double Center_x=0,Center_y=0;//重心
  32. int Center_x=0,Center_y=0;//重心
  33. int i,j; //循环变量
  34. // 获得图像的区域重心
  35. double s10=0,s01=0,s00=0; //0阶矩和1阶矩 //注:二值图像的0阶矩表示面积
  36. for(j=0;j<bmpHeight;j++)//y
  37. {
  38. for(i=0;i<bmpWidth;i++)//x
  39. {
  40. s10+=i*pBmpBuf[j*bmpStep+i];
  41. s01+=j*pBmpBuf[j*bmpStep+i];
  42. s00+=pBmpBuf[j*bmpStep+i];
  43. }
  44. }
  45. Center_x=(int)(s10/s00+0.5);
  46. Center_y=(int)(s01/s00+0.5);
  47. // 计算二阶、三阶矩
  48. m00=s00;
  49. for(j=0;j<bmpHeight;j++)
  50. {
  51. for(i=0;i<bmpWidth;i++)//x
  52. {
  53. x0=(i-Center_x);
  54. y0=(j-Center_y);
  55. m11+=x0*y0*pBmpBuf[j*bmpStep+i];
  56. m20+=x0*x0*pBmpBuf[j*bmpStep+i];
  57. m02+=y0*y0*pBmpBuf[j*bmpStep+i];
  58. m03+=y0*y0*y0*pBmpBuf[j*bmpStep+i];
  59. m30+=x0*x0*x0*pBmpBuf[j*bmpStep+i];
  60. m12+=x0*y0*y0*pBmpBuf[j*bmpStep+i];
  61. m21+=x0*x0*y0*pBmpBuf[j*bmpStep+i];
  62. }
  63. }
  64. // 计算规范化后的中心矩
  65. u20=m20/pow(m00,2);
  66. u02=m02/pow(m00,2);
  67. u11=m11/pow(m00,2);
  68. u30=m30/pow(m00,2.5);
  69. u03=m03/pow(m00,2.5);
  70. u12=m12/pow(m00,2.5);
  71. u21=m21/pow(m00,2.5);
  72. // 计算中间变量。
  73. t1=(u20-u02);
  74. t2=(u30-3*u12);
  75. t3=(3*u21-u03);
  76. t4=(u30+u12);
  77. t5=(u21+u03);
  78. // 计算不变矩
  79. M[0]=u20+u02;
  80. M[1]=t1*t1+4*u11*u11;
  81. M[2]=t2*t2+t3*t3;
  82. M[3]=t4*t4+t5*t5;
  83. M[4]=t2*t4*(t4*t4-3*t5*t5)+t3*t5*(3*t4*t4-t5*t5);
  84. M[5]=t1*(t4*t4-t5*t5)+4*u11*t4*t5;
  85. M[6]=t3*t4*(t4*t4-3*t5*t5)-t2*t5*(3*t4*t4-t5*t5);
  86. /*cout<<M[0]<<endl;//<<二"<<M[0]<<"三"<<M[0]<<"四"<<M[0]<<"五"<<M[0]<<"六"<<M[0]<<"七"<<M[0]<<endl;
  87. cout<<M[1]<<endl;
  88. cout<<M[2]<<endl;
  89. cout<<M[3]<<endl;
  90. cout<<M[4]<<endl;
  91. cout<<M[5]<<endl;
  92. cout<<M[6]<<endl;
  93. cout<<endl;*/
  94. returntrue;
  95. }
  96. int main(char argc,char** argv)
  97. {
  98. int i;
  99. double Sa[7] = {0},Ta[7] ={0};
  100. ///*源图像
  101. IplImage*img = cvLoadImage(filename,0);//灰度
  102. HuMoment(img);
  103. for(i=0;i<7;i++)
  104. {
  105. Sa[i] = M[i];
  106. M[i] =0;
  107. }
  108. cout<<Sa[0]<<endl;
  109. cout<<Sa[1]<<endl;
  110. cout<<Sa[2]<<endl;
  111. cout<<Sa[3]<<endl;
  112. cout<<Sa[4]<<endl;
  113. cout<<Sa[5]<<endl;
  114. cout<<Sa[6]<<endl;
  115. cout<<endl;
  116. //*/
  117. ///*模板图
  118. IplImage*tpl = cvLoadImage(filename2,0);//灰度
  119. HuMoment(tpl);
  120. for(i=0;i<7;i++)
  121. {
  122. Ta[i] = M[i];
  123. M[i] =0;
  124. }
  125. cout<<Ta[0]<<endl;
  126. cout<<Ta[1]<<endl;
  127. cout<<Ta[2]<<endl;
  128. cout<<Ta[3]<<endl;
  129. cout<<Ta[4]<<endl;
  130. cout<<Ta[5]<<endl;
  131. cout<<Ta[6]<<endl;
  132. cout<<endl;
  133. // 计算相似度
  134. double dbR =0; //相似度
  135. double dSigmaST =0;
  136. double dSigmaS =0;
  137. double dSigmaT =0;
  138. double temp =0;
  139. for(i=0;i<7;i++)
  140. {
  141. temp = Sa[i]*Ta[i];
  142. dSigmaST+=temp;
  143. dSigmaS+=pow(Sa[i],2);
  144. dSigmaT+=pow(Ta[i],2);
  145. }
  146. dbR = dSigmaST/(sqrt(dSigmaS)*sqrt(dSigmaT));
  147. printf("%lf\n",dbR);
  148. //cout<<dbR<<endl;
  149. cvReleaseImage(&img);
  150. cvReleaseImage(&tpl);
  151. return0;
  152. }

其他几种矩的比较可以参考这篇文章:

点击打开链接

时间: 2024-12-14 00:41:48

图像的七个不变矩 可用于图像的匹配的相关文章

用于图像去雾的优化对比度增强算法

图像去雾哪家强?之前我们已经讨论过了著名的基于暗通道先验的图像去雾(Kaiming He, 2009)算法,如果你用兴趣可以参考: 暗通道优先的图像去雾算法(上) 暗通道优先的图像去雾算法(下) 此外,网上也有很多同道推荐了一篇由韩国学者所发表的研究论文<Optimized contrast enhancement for real-time image and video dehazing>(你也可以从文末参考文献[1]给出的链接中下载到这篇经典论文),其中原作者就提出了一个效果相当不错的图

第七章 实现炫酷效果—图像和动画(1)

第七章实现炫酷效果-图像和动画 学完上一章,相信读者对Android画图核心部分有了一定的了解.为了实现更加炫酷的效果,我们可能会在我们的应用中使用大量的图像和动画效果. 本章我们将详细介绍Android中的各种图像对象的使用,以及动画的使用.学习完本章,相信读者可以独立开发出有着绚丽的视觉效果的Android应用了. 7.1 Android的几种常用图像类型 Android中的图像对象,主要有android.graphics.Bitmap(位图).android.graphics.drawab

捕获海康威视IPCamera图像,转成OpenCV可以处理的图像(一)

海康威视IPCamera图像捕获 捕获海康威视IPCamera图像,转成OpenCV可以处理的IplImage图像(一) 捕获海康威视IPCamera图像,转成OpenCV可以处理的IplImage图像(二) 所使用海康威视摄像头型号:DS-2CD4026FWD-(A)(P) 海康威视IPCamera图像捕获方法有两种: (1)利用SDK里面的NET_DVR_CaptureJPEGPicture_NEW进行视频抓图 (2)捕获实时流,将实时流解码成YV12,然后转换成RGB 在这篇博文里,我先介

[ jquery 文档处理 empty() remove([expr]) detach([expr]) ] 此方法用于把所有匹配的元素移除

此方法用于把所有匹配的元素移除: remove([expr]) 概述 从DOM中删除所有匹配的元素 这个方法不会把匹配的元素从jQuery对象中删除,因而可以在将来再使用这些匹配的元素.但除了这个元素本身得以保留之外,其他的比如绑定的事件,附加的数据等都会被移除 empty() 概述 删除匹配的元素集合中所有的子节点 detach([expr]) 概述 从DOM中删除所有匹配的元素. 这个方法不会把匹配的元素从jQuery对象中删除,因而可以在将来再使用这些匹配的元素.与remove()不同的是

[ jquery 文档处理 replaceWith(content|fn) replaceAll(content) ] 此方法用于把所有匹配的元素替换成指定的HTML或DOM元素

此方法用于把所有匹配的元素替换成指定的HTML或DOM元素 content(String, Element, jQuery, Function) 用于将匹配元素替换掉的内容.如果这里传递一个函数进来的话,函数返回值必须是HTML字符串. fn 返回THML字符串,用来替换的内容. 实例: <html lang='zh-cn'> <head> <title>Insert you title</title> <meta http-equiv='descri

[ jquery 文档处理 wrapInner(htm|element|fnl) ] 此方法用于把所有匹配的元素的子元素(包括文本节点)使用指定的 HTML 元素来包裹

此方法用于把所有匹配的元素的子元素(包括文本节点)使用指定的 HTML 元素来包裹 将每一个匹配的元素的子内容(包括文本节点)用一个HTML结构包裹起来 这个函数的原理是检查提供的第一个元素(它是由所提供的HTML标记代码动态生成的),并在它的代码结构中找到最上层的祖先元素--这个祖先元素就是包装元素 html HTML标记代码字符串,用于动态生成元素并包装目标元素 element 用于包装目标元素的DOM元素 fn 生成包裹结构的一个函数 实例: <html lang='zh-cn'> &l

[ jquery 文档处理 wrap(html|element|fn) ] 此方法用于把所有匹配的元素用其他元素的结构化标记包裹起来

此方法用于把所有匹配的元素用其他元素的结构化标记包裹起来 实例: <html lang='zh-cn'> <head> <title>Insert you title</title> <meta http-equiv='description' content='this is my page'> <meta http-equiv='keywords' content='keyword1,keyword2,keyword3'> <

捕获海康威视IPCamera图像,转成OpenCV可以处理的图像(二)

海康威视IPCamera图像捕获 捕获海康威视IPCamera图像,转成OpenCV可以处理的IplImage图像(一) 捕获海康威视IPCamera图像,转成OpenCV可以处理的IplImage图像(二) 所使用海康威视摄像头型号:DS-2CD4026FWD-(A)(P) 海康威视IPCamera图像捕获方法有两种: (1)利用SDK里面的NET_DVR_CaptureJPEGPicture_NEW进行视频抓图 (2)捕获实时流,将实时流解码成YV12,然后转换成RGB 在这篇博文里,我将介

off() 方法 与 unbind() 方法移除绑定事件的处理程序。one()函数用于为每个匹配元素的一个或多个事件绑定一次性事件处理函数

off() 方法移除用.on()绑定的事件处理程序. unbind() 方法移除用.bind()绑定的事件处理程序. 从 jQuery 1.7开始, .on() 和 .off()方法是最好的元素上附加和移除事件处理程序的方法. 常用原型区别: .unbind( eventType [, handler ] ) .off( events [, selector ] [, handler ] ) off: http://www.365mini.com/page/jquery-off.htm unbi