圖像和輪廓的匹配(hu矩) (轉自:http://blog.csdn.net/lu597203933 )
(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;
- }