图像和轮廓的匹配(hu矩)
(1)hu矩的概念,我也总结了但是我不过多的阐述,因为我也不是太理解,只知道它具有平移,旋转,尺度不变性,详细见别人的这篇blog:http://blog.csdn.net/wrj19860202/article/details/6327094
(2)opencv 的实现——计算hu矩
<1>普通矩和中心矩的计算
Void cvMoments(const CvArr*arr,CvMoments*moments, int binary = 0)
arr:图像(1-通道或3通道,有COI设置)或者多边形(点的CvSeq或一族点的向量)
moments:返回矩阵态度接口的指针
binary(仅对图像)如果标识为非0,则所有零像素点被当成零,其它的被看成1.
Double cvGetSpatialMoment(&moment, p, q); //得到普通矩
Double cvGetCentralMoment(&moment, p, q); // 得到中心矩
<2>计算hu矩
Void cvGetHuMoment(CvMoments *moment,CvHuMoments *humoment)
代码:
IplImage *src = cvCreateImage(cvSize(10,10), 8, 1); cvZero(src); for(int yy = 0; yy < 5; yy++) { for(int xx = 0; xx < 5; xx++) { cvSetReal2D(src, yy, xx, 255); } } double m00, m10, m01; CvMoments moment; cvMoments(src, &moment, 2); //第三个像素点非0,则所有的0像素点被当做0,非0像素点被当做1 m00 = cvGetSpatialMoment(&moment, 0, 0); // 得到普通矩 m10 = cvGetSpatialMoment(&moment, 1, 0); m01 = cvGetSpatialMoment(&moment, 0, 1); double u20; u20 = cvGetCentralMoment(&moment, 2, 0); //得到中心矩 CvHuMoments humoment; cvGetHuMoments(&moment, &humoment); double hu1 = humoment.hu1; // 得到hu矩 cout << hu1 << endl;
<3>OPENCV还提供了输入图像直接进行hu矩匹配的函数,返回的是两个图像或轮廓之间hu矩的相似度:
double cvMatchShapes(const void*object1,const void*object2,int method,doubleparameter=0);
计算两个轮廓之间hu矩相似程度:
#include <iostream> #include "cv.h" #include "cxcore.h" #include "highgui.h" using namespace std; CvSeq *getImageContours(CvArr *src) { cvThreshold(src, src, 100, 255, CV_THRESH_BINARY); CvMemStorage * storage = cvCreateMemStorage(0); CvSeq * contours; cvFindContours(src, storage, &contours); return contours; } int main() { IplImage *src1 = cvLoadImage("", 0); CvSeq *contours1 = getImageContours(src1); // 得到src1的轮廓 IplImage *src2 = cvLoadImage("", 0); CvSeq *contours2 = getImageContours(src2); double result = cvMatchShapes(contours1, contours2, 1); // 根据输入的图像或轮廓来计算它们的hu矩的相似度 cout << result << endl; cvReleaseMemStorage(&contours1->storage); cvReleaseMemStorage(&contours1->storage); cvReleaseImage(&src1); cvReleaseImage(&src2); return 0; }
(3)案例:给出了10副图片,其中2.jpg和11.jpg非常相似,我们代码是要实现的在3~11.jgp找到与2.jpg最相似的图片。
代码:
#include <iostream> #include <string> #include <sstream> #include "cv.h" #include "cxcore.h" #include "highgui.h" using namespace std; int main() { IplImage *srcColor = cvLoadImage("E:\\study_opencv_video\\lesson15_3\\2.jpg", 1); IplImage *src = cvCreateImage(cvGetSize(srcColor), 8, 1); cvCvtColor(srcColor, src, CV_BGR2GRAY); if(!src) { cout << "No Image Load" << endl; } int i; stringstream ss; string path; string str; IplImage *dst = NULL, *dstColor; char c[256]; double result, maxResult= 1000 * 256 *256; IplImage *resultMap = NULL; for (i = 3; i < 12; i ++) { path = "E:\\study_opencv_video\\lesson15_3\\"; ss.clear(); ss << i; ss >> str; str += ".jpg"; path += str; ss.clear(); ss << path; ss >> c; dstColor = cvLoadImage(c,1); dst = cvCreateImage(cvGetSize(dstColor), 8, 1); cvCvtColor(dstColor, dst, CV_BGR2GRAY); result = cvMatchShapes(src, dst, 1); if(maxResult > result) { resultMap = cvCreateImage(cvGetSize(dstColor), 8, 3); maxResult = result; cvCopy(dstColor, resultMap); } } cvNamedWindow("srcColor", 0); cvNamedWindow("resultMap",0); cvShowImage("resultMap", resultMap); cvShowImage("srcColor", srcColor); cvWaitKey(0); cvReleaseImage(&src); cvReleaseImage(&srcColor); cvReleaseImage(&dst); cvReleaseImage(&dstColor); cvReleaseImage(&resultMap); cvDestroyWindow("srcColor"); cvDestroyWindow("resultMap"); return 0; }
作者:小村长 出处:http://blog.csdn.net/lu597203933 欢迎转载或分享,但请务必声明文章出处。 (新浪微博:小村长zack, 欢迎交流!)