天天看點

opencv學習_10 (圖像和輪廓的比對(hu矩))

圖像和輪廓的比對(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, 歡迎交流!)