图像的七个不变矩 可用于图像的匹配
2015-07-16 16:10
393 查看
图像的几何不变矩
矩特征主要表征了图像区域的几何特征,又称为几何矩, 由于其具有旋转、平移、尺度等特性的不变特征,所以又称其为不变矩。在图像处理中,几何不变矩可以作为一个重要的特征来表示物体,可以据此特征来对图像进行分类等操作。
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=
其他几种矩的比较可以参考这篇文章:
点击打开链接
矩特征主要表征了图像区域的几何特征,又称为几何矩, 由于其具有旋转、平移、尺度等特性的不变特征,所以又称其为不变矩。在图像处理中,几何不变矩可以作为一个重要的特征来表示物体,可以据此特征来对图像进行分类等操作。
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=
invariable_moment(imread('lena.jpg'));
function inv_m7 = invariable_moment(in_image) % 功能:计算图像的Hu的七个不变矩 % 输入:in_image-RGB图像 % 输出:inv_m7-七个不变矩 % 将输入的RGB图像转换为灰度图像 image=rgb2gray(in_image); %将图像矩阵的数据类型转换成双精度型 image=double(image); %%%=================计算 、 、 ========================= %计算灰度图像的零阶几何矩 m00=sum(sum(image)); m10=0; m01=0; [row,col]=size(image); for i=1:row for j=1:col m10=m10+i*image(i,j); m01=m01+j*image(i,j); end end %%%=================计算 、 ================================ u10=m10/m00; u01=m01/m00; %%%=================计算图像的二阶几何矩、三阶几何矩============ m20 = 0;m02 = 0;m11 = 0;m30 = 0;m12 = 0;m21 = 0;m03 = 0; for i=1:row for j=1:col m20=m20+i^2*image(i,j); m02=m02+j^2*image(i,j); m11=m11+i*j*image(i,j); m30=m30+i^3*image(i,j); m03=m03+j^3*image(i,j); m12=m12+i*j^2*image(i,j); m21=m21+i^2*j*image(i,j); end end %%%=================计算图像的二阶中心矩、三阶中心矩============ y00=m00; y10=0; y01=0; y11=m11-u01*m10; y20=m20-u10*m10; y02=m02-u01*m01; y30=m30-3*u10*m20+2*u10^2*m10; y12=m12-2*u01*m11-u10*m02+2*u01^2*m10; y21=m21-2*u10*m11-u01*m20+2*u10^2*m01; y03=m03-3*u01*m02+2*u01^2*m01; %%%=================计算图像的归格化中心矩==================== n20=y20/m00^2; n02=y02/m00^2; n11=y11/m00^2; n30=y30/m00^2.5; n03=y03/m00^2.5; n12=y12/m00^2.5; n21=y21/m00^2.5; %%%=================计算图像的七个不变矩====================== h1 = n20 + n02; h2 = (n20-n02)^2 + 4*(n11)^2; h3 = (n30-3*n12)^2 + (3*n21-n03)^2; h4 = (n30+n12)^2 + (n21+n03)^2; 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); h6 = (n20-n02)*((n30+n12)^2-(n21+n03)^2)+4*n11*(n30+n12)*(n21+n03); 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); inv_m7= [h1 h2 h3 h4 h5 h6 h7];c++代码:
/*===============================================// 功能:不变矩匹配 时间:3/28/2011 SkySeraph HQU 参考: //===============================================*/ #include "iostream" usingnamespace std; #include "cv.h" #include "highgui.h" #include "math.h" #pragma comment(lib,"highgui.lib") #pragma comment(lib,"cv.lib") #pragma comment(lib,"cvaux.lib") #pragma comment(lib,"cxcore.lib") constchar* filename ="D:\\My Documents\\My Pictures\\Images\\1.bmp"; constchar* filename2 ="D:\\My Documents\\My Pictures\\Images\\2.bmp"; /*=============================================*/ double M[7] = {0}; //HU不变矩 bool HuMoment(IplImage* img) { int bmpWidth = img->width; int bmpHeight = img->height; int bmpStep = img->widthStep; int bmpChannels = img->nChannels; uchar*pBmpBuf = (uchar*)img->imageData; double m00=0,m11=0,m20=0,m02=0,m30=0,m03=0,m12=0,m21=0; //中心矩 double x0=0,y0=0; //计算中心距时所使用的临时变量(x-x') double u20=0,u02=0,u11=0,u30=0,u03=0,u12=0,u21=0;//规范化后的中心矩 //double M[7]; //HU不变矩 double t1=0,t2=0,t3=0,t4=0,t5=0;//临时变量, //double Center_x=0,Center_y=0;//重心 int Center_x=0,Center_y=0;//重心 int i,j; //循环变量 // 获得图像的区域重心 double s10=0,s01=0,s00=0; //0阶矩和1阶矩 //注:二值图像的0阶矩表示面积 for(j=0;j<bmpHeight;j++)//y { for(i=0;i<bmpWidth;i++)//x { s10+=i*pBmpBuf[j*bmpStep+i]; s01+=j*pBmpBuf[j*bmpStep+i]; s00+=pBmpBuf[j*bmpStep+i]; } } Center_x=(int)(s10/s00+0.5); Center_y=(int)(s01/s00+0.5); // 计算二阶、三阶矩 m00=s00; for(j=0;j<bmpHeight;j++) { for(i=0;i<bmpWidth;i++)//x { x0=(i-Center_x); y0=(j-Center_y); m11+=x0*y0*pBmpBuf[j*bmpStep+i]; m20+=x0*x0*pBmpBuf[j*bmpStep+i]; m02+=y0*y0*pBmpBuf[j*bmpStep+i]; m03+=y0*y0*y0*pBmpBuf[j*bmpStep+i]; m30+=x0*x0*x0*pBmpBuf[j*bmpStep+i]; m12+=x0*y0*y0*pBmpBuf[j*bmpStep+i]; m21+=x0*x0*y0*pBmpBuf[j*bmpStep+i]; } } // 计算规范化后的中心矩 u20=m20/pow(m00,2); u02=m02/pow(m00,2); u11=m11/pow(m00,2); u30=m30/pow(m00,2.5); u03=m03/pow(m00,2.5); u12=m12/pow(m00,2.5); u21=m21/pow(m00,2.5); // 计算中间变量。 t1=(u20-u02); t2=(u30-3*u12); t3=(3*u21-u03); t4=(u30+u12); t5=(u21+u03); // 计算不变矩 M[0]=u20+u02; M[1]=t1*t1+4*u11*u11; M[2]=t2*t2+t3*t3; M[3]=t4*t4+t5*t5; M[4]=t2*t4*(t4*t4-3*t5*t5)+t3*t5*(3*t4*t4-t5*t5); M[5]=t1*(t4*t4-t5*t5)+4*u11*t4*t5; M[6]=t3*t4*(t4*t4-3*t5*t5)-t2*t5*(3*t4*t4-t5*t5); /*cout<<M[0]<<endl;//<<二"<<M[0]<<"三"<<M[0]<<"四"<<M[0]<<"五"<<M[0]<<"六"<<M[0]<<"七"<<M[0]<<endl; cout<<M[1]<<endl; cout<<M[2]<<endl; cout<<M[3]<<endl; cout<<M[4]<<endl; cout<<M[5]<<endl; cout<<M[6]<<endl; cout<<endl;*/ returntrue; } int main(char argc,char** argv) { int i; double Sa[7] = {0},Ta[7] ={0}; ///*源图像 IplImage*img = cvLoadImage(filename,0);//灰度 HuMoment(img); for(i=0;i<7;i++) { Sa[i] = M[i]; M[i] =0; } cout<<Sa[0]<<endl; cout<<Sa[1]<<endl; cout<<Sa[2]<<endl; cout<<Sa[3]<<endl; cout<<Sa[4]<<endl; cout<<Sa[5]<<endl; cout<<Sa[6]<<endl; cout<<endl; //*/ ///*模板图 IplImage*tpl = cvLoadImage(filename2,0);//灰度 HuMoment(tpl); for(i=0;i<7;i++) { Ta[i] = M[i]; M[i] =0; } cout<<Ta[0]<<endl; cout<<Ta[1]<<endl; cout<<Ta[2]<<endl; cout<<Ta[3]<<endl; cout<<Ta[4]<<endl; cout<<Ta[5]<<endl; cout<<Ta[6]<<endl; cout<<endl; // 计算相似度 double dbR =0; //相似度 double dSigmaST =0; double dSigmaS =0; double dSigmaT =0; double temp =0; for(i=0;i<7;i++) { temp = Sa[i]*Ta[i]; dSigmaST+=temp; dSigmaS+=pow(Sa[i],2); dSigmaT+=pow(Ta[i],2); } dbR = dSigmaST/(sqrt(dSigmaS)*sqrt(dSigmaT)); printf("%lf\n",dbR); //cout<<dbR<<endl; cvReleaseImage(&img); cvReleaseImage(&tpl); return0; }
其他几种矩的比较可以参考这篇文章:
点击打开链接
相关文章推荐
- 指数型母函数&&hdu 2065 "红色病毒"问题
- Android---利用Google的云消息
- SSH搭建
- 基于API的MFC串口通信程序编写
- ubuntu备份与恢复
- asp.net 生成验证码
- LCA 最近公共祖先 小结
- idea中配置使用mybatis出现问题BuilderException
- 建立TFTP下载调试
- git中reset与revert的使用
- 常用base.css
- MyBatis返回主键
- WPF中的ControlTemplate(控件模板)(转)
- c++对象模型-the sematics of function
- Hadoop YARN ERROR 1/1 local-dirs are bad *, 1/1 log-dirs are bad *
- Android-studio第一次开始跳过SDK下载
- WCF问题集锦:ReadResponse failed: The server did not return a complete response for this request.
- 【LintCode】 Best Time to Buy and Sell Stock II 买卖股票的最佳时机 II
- Android触控基础:MotionEvent
- python 获取内存的状态