Hausdorff距离匹配算法及代码

5 篇文章 0 订阅
3 篇文章 0 订阅

2016年11月29日更新:

该代码已托管到GitHub,最新代码请从GitHub 下载
1. 修复了match()函数内一个导致内存泄漏的bug.

2015年9月16日更新:

添加CFeatures类,用于获取特征点,实现了CANNY、HARRIS、SIFT、SURF特征点的获取,添加了实时匹配例程。

已知BUG:
1.使用HARRIS、SIFT、SURF提取特征点时,Debug版本耗时非常长,release版本正常
2.使用HARRIS、SIFT、SURF提取特征点时,CFeatures类不能正确析构,初步判断是dll和EXE堆释放错误,
而且出错点很可能是 m_vecPoints向量问题

如有知道原因,还望不吝赐教。

/************************************************************************************************************************************/

2015年9月10上传

以下是我实现的Hausdorff  distance距离匹配 C++ 类,构造函数如下:

	CHausdorff(IplImage *srcImg, IplImage *modelImge, 
			int xInterval = 1, int yInterval = 1, 
			double frontRange = 0.8, double backRange = 0.7);
  1. 当frontRange = 1,backRange = 1,并使用sort()函数时,该类退化成原始Hausforff distance定义的匹配方法
  2. 当frontRange ,backRange 取值为0~1之间,并使用sort函数时,该类为改进型hausdorff distance:部分hausdorff distance.
  3. 当frontRange ,backRange 取值任意,并使用meanDistance()函数时,该类为改进型hausdorff distance:平均hausdorff distance.

以下C++代码在VS2010 + OpenCV2.4.8下调试通过,

附上代码:

CHausdorff类定义如下:

CHausdorff.h 文件:

/******************************************
* Copyright (C) 2015 HolaMirai(HolaMirai@163.com)
* All rights reserved.
* 
* 文件名:hausdorff.h
* 摘要:寻找Hausdorff Distance度量的最匹配位置和最匹配位置的距离
* 当前版本:<V1.0>,<完成日期:2015年9月7日>,<HolaMirai>,<创建该文件>
* 历史记录:...
******************************************/


/*
* 类定义说明
*/
/********************************************
* CHausforff类
* CHausdorff类接受带匹配图、模板图的二值化图像或包含特征点二值化图像,参数都带有默认值
* 使用match函数可以直接获取匹配结果
* hausdorff distance 采用部分距离法,对遮挡、噪声效果良好,也可以采用平均距离法
* 匹配过程分为粗匹配和精匹配个过程
* 各函数已经解耦,可以单独调用某个函数以观察hausdorff distance 方法的各部分
********************************************/

#ifndef CHAUSDORFF_H
#define CHAUSDORFF_H

/*
* 宏定义
*/
// 最大距离
#define MAX_DISTANCE INT_MAX

#include "cv.h"

/*
*  类定义
*/
class CHausdorff
{
public:
	CHausdorff( IplImage *modelImge, IplImage *srcImg = NULL,
				int xInterval = 1, int yInterval = 1, 
				double frontRange = 0.8, double backRange = 0.7);
	~CHausdorff();

public:
	void setSourceImage(IplImage *srcImg);
	//void setModelImage(IplImage *modelImg);

	void setScanInterval_X(int xInterval);
	 void setScanInterval_Y(int yInterval);

	 void setFrontRange(double Range);
	 void setBackRange(double Range);

	 double computeDirDistance(CvPoint Apoints[], CvPoint Bpoints[], int numA, int numB, double Range) const;
	 double distance(CvPoint Apoints[], CvPoint Bpoints[], int numA, int numB) const;
	 
	 void match();
	 void drawMatch(const char *name, IplImage *img = NULL);

private:
	int searchPoints(IplImage *img, CvPoint pPoints[]) const;

	void sort(double a[],int n) const;
	double meanDistance(double a[], int n) const;

	void createTable();
	void freeTable();

public:
	//记录匹配结果
	CvPoint m_matchPoint;
	double  m_matchDistance;

private:
	int m_xInterval;
	int m_yInterval;
	double m_frontRange;
	double m_backRange;

	//距离变换表指针
	double **m_disTable;

public:
	IplImage *m_srcImg;
	IplImage *m_modelImg;
};

#endif

CHausdorff.cpp文件:

/******************************************
* Copyright (C) 2015 HolaMirai(HolaMirai@163.com)
* All rights reserved.
* 
* 文件名:hausdorff.cpp
* 摘要:寻找Hausdorff Distance度量的最匹配位置和最匹配位置的距离
* 当前版本:V2.1, 2015年9月11日,HolaMirai, 添加 createTable()、freeTable()函数,添加平均hausdorff距离方法,添加注释
* 历史记录:V2.0, 2015年9月10日,HolaMirai, 调试完成该文件&添加meanDistance()函数
*		  :V1.0, 2015年9月7日, HolaMirai, 创建该文件
******************************************/

/*
* TBD:	1.改用Voronoi图进行Hausdorff距离计算
*/

#include "CHausdorff.h"
#include "highgui.h"

/*
* 函数名称:CHausdorff
* 函数功能:类构造函数
* 函数入口: 
* 输入参数: 待匹配图、模板二值化图像,粗匹配横、纵坐标扫描间隔 xInterval,yInterval 
*            前向距离因子 frontRange,后向距离因子 backRange
* 输出参数:无
* 返 回 值:
* 其它说明: 
*/
CHausdorff::CHausdorff(IplImage *modelImg, IplImage *srcImg, int xInterval, int yInterval, double frontRange, double backRange)
{
	m_modelImg = cvCloneImage(modelImg);
	m_srcImg = cvCloneImage(srcImg);

	m_frontRange = frontRange;
	m_backRange = backRange;
	m_xInterval = xInterval;
	m_yInterval = yInterval;

	createTable();
}

CHausdorff::~CHausdorff()
{
	freeTable();

	m_srcImg = NULL;
	cvReleaseImage(&m_modelImg);
	
}

/*
* 函数名称:setSourceImage
* 函数功能:设置待匹配图像
* 函数入口: 
* 输入参数: 待匹配图像指针
* 输出参数:
* 返 回 值:void
* 其它说明: 
*/
void CHausdorff::setSourceImage(IplImage *srcImg)
{
	assert(srcImg->nChannels == 1);
	m_srcImg = srcImg;
}

/*
* 函数名称:setModelImage
* 函数功能:设置待模板图像
* 函数入口: 
* 输入参数: 模板图像指针
* 输出参数:
* 返 回 值:void
* 其它说明: 若是用查表法计算距离,请不要改变模板图,即不要调用该函数
*/
/*
void CHausdorff::setModelImage(IplImage *modelImg)
{
	assert(modelImg->nChannels == 1);
	m_modelImg = modelImg;
}
*/
/*
* 函数名称:setScanInterval_X
* 函数功能:设置粗匹配X坐标扫描间隔
* 函数入口: 
* 输入参数: 粗匹配横坐标扫描间隔 xInterval
* 输出参数:无
* 返 回 值:void
* 其它说明: 
*/
void CHausdorff::setScanInterval_X(int xInterval)
{
	m_xInterval = xInterval;
}

/*
* 函数名称:setScanInterval_Y
* 函数功能:设置粗匹配Y坐标扫描间隔
* 函数入口: 
* 输入参数: 粗匹配横坐标扫描间隔 yInterval
* 输出参数:无
* 返 回 值:void
* 其它说明: 
*/
void CHausdorff::setScanInterval_Y(int yInterval)
{
	m_yInterval = yInterval;
}

/*
* 函数名称:setFrontRange
* 函数功能:设置前向匹配距离因子
* 函数入口: 
* 输入参数: 前向匹配距离因子 Range
* 输出参数:无
* 返 回 值:void
* 其它说明: 
*/
void CHausdorff::setFrontRange(double Range)
{
	m_frontRange = Range;
}

/*
* 函数名称:setFrontRange
* 函数功能:设置后向匹配距离因子
* 函数入口: 
* 输入参数: 前向匹配距离因子 Range
* 输出参数:无
* 返 回 值:void
* 其它说明: 
*/
void CHausdorff::setBackRange(double Range)
{
	m_backRange = Range;
}

/*
* 函数名称:searchPoints
* 函数功能:获得特征点坐标和特征点的个数
* 函数入口: 
* 输入参数: 灰度图 img, 接受特征点的数组指针
* 输出参数:无
* 返 回 值: 特征点个数
* 其它说明: 支持图片 ROI
*/
int CHausdorff::searchPoints(IplImage *img, CvPoint pPoints[]) const
{
	CvRect rect;
	if ( !img->roi)
	{
		rect.x = 0;
		rect.y = 0;
		rect.width = img->width;
		rect.height = img->height;
	}
	else
	{
		rect.x = img->roi->xOffset;
		rect.y = img->roi->yOffset;
		rect.width = img->roi->width;
		rect.height = img->roi->height;
	}

	//统计特征点
	uchar *ptr;
	int num = 0;
	for (int i = rect.y; i < rect.y + rect.height; i++)
	{
		ptr = (uchar *) (img->imageData + i * img->widthStep);
		for (int j = rect.x; j < rect.x + rect.width; j++)
		{
			if (ptr[j] != 0)
			{
				num++;
			}
		}
	}

	if (num == 0)
	{
		return 0;
	}

	num = 0;
	for (int i = rect.y; i < rect.y + rect.height; i++)
	{
		ptr = (uchar *) (img->imageData + i * img->widthStep);
		for (int j = rect.x; j < rect.x + rect.width; j++)
		{
			if (ptr[j] != 0)
			{
				pPoints[num].x = j - rect.x;
				pPoints[num].y = i - rect.y;
				num++;
			}
		}
	}

	//结果返回
	return num;
}/*searchPoints()*/


/*
* 函数名称:match
* 函数功能:利用 Hausdorff distance 值来匹配图片
* 函数入口: 
* 输入参数:无
* 输出参数:最佳匹配位置 和最佳匹配距离
* 返 回 值: void
* 其它说明: 
*/
void CHausdorff::match()
{
	int ws, hs, wm, hm, numModel, numSrc;
	CvRect rect;
	double *matchDis = new double[100];  //假定最大会有100个最佳位置,这里并未实现,留着以后改进
	CvPoint *matchPoints = new CvPoint[100];
	double temp = MAX_DISTANCE;
	double dis = MAX_DISTANCE;
	int n = 0;  //只有一个最佳位置,本文的假设前提


	ws = m_srcImg->width;
	hs = m_srcImg->height;
	wm = m_modelImg->width;
	hm = m_modelImg->height;

	// 存储模板特征点和原图像特征点
	CvPoint *pMPoints = new CvPoint[wm * hm];
	CvPoint *pSPoints = new CvPoint[wm * hm];

	//获得模板特征点
	numModel = searchPoints(m_modelImg,pMPoints);

	if (numModel == 0)
	{
		printf_s("find no points in model");
		return;
	}

	//搜索最佳匹配
	rect.width = wm;
	rect.height = hm;
	
	// 粗匹配
	//#pragma omp parallel for firstprivate(m_srcImg)     //并行运算
	for (int i = 0; i < ws; i += m_xInterval)
	{
		rect.x = i;
		//#pragma omp parallel for 
		for (int j = 0; j < hs; j += m_yInterval)
		{
			rect.y = j;
			cvSetImageROI(m_srcImg,rect);
			numSrc = searchPoints(m_srcImg,pSPoints);
			if (numSrc == 0)
			{
				continue;
			}
			// 特征点数据量相差太大则忽略该位置,可以依具体情况调整参数
			if (double(numSrc)/numModel < 0.8 || (double)numSrc/numModel > 1.25)
			{
				continue;
			}

			temp = distance(pMPoints, pSPoints, numModel, numSrc);
			// min
			if (temp < dis)
			{
				dis = temp;
				matchDis[n] = temp;
				matchPoints[n].x = i;
				matchPoints[n].y = j;
			} 	
		}
	}

	//精匹配
	for (int i = matchPoints[n].x - m_xInterval; i < matchPoints[n].x + m_xInterval; i++)
	{
		rect.x = i;
		for (int j = matchPoints[n].y - m_yInterval; j < matchPoints[n].y + m_yInterval; j++)
		{
			rect.y = j;
			cvSetImageROI(m_srcImg,rect);
			numSrc = searchPoints(m_srcImg,pSPoints);
			if (numSrc == 0)
			{
				continue;
			}

			temp = distance(pMPoints, pSPoints, numModel, numSrc);
			// min
			if (temp < dis)
			{
				dis = temp;
				matchDis[n] = temp;
				matchPoints[n].x = i;
				matchPoints[n].y = j;
			} 	
		}
	}


	m_matchPoint = matchPoints[0];
	m_matchDistance = matchDis[0];

	cvResetImageROI(m_srcImg);

	delete []pMPoints;
	delete []pSPoints;
	delete []matchDis;
	delete []matchPoints;
}/* match() */


/*
* 函数名称:distance
* 函数功能:获取某位置的Hausdorff distance值
* 函数入口: 
* 输入参数:两组特征点数组指针,特征点个数 numA, numB
* 输出参数:
* 返 回 值: 该位置的Hausdorff distance值
* 其它说明: 支持图片ROI
*/
double CHausdorff::distance(CvPoint Apoints[], CvPoint Bpoints[], int numA, int numB) const
{
	double hAB;
	double hBA;
	hAB = computeDirDistance(Apoints, Bpoints, numA, numB, m_frontRange);
	hBA = computeDirDistance(Bpoints, Apoints, numB, numA, m_backRange);

	// H(A, B) = max(h(A, B), h(B,A))
	return std::max(hAB, hBA);	
}/*distance()*/

/*
* 函数名称:computeDirDistance
* 函数功能:计算单向 Hausdorff distance 值
* 函数入口: 
* 输入参数:两组特征点数组指针 Apoints, Bpoints, 特征点个数numA, int numB, 单向距离因子 Range
* 输出参数:
* 返 回 值: 单向 Hausdorff distance 值
* 其它说明:
*/
double CHausdorff::computeDirDistance(CvPoint Apoints[], CvPoint Bpoints[], int numA, int numB, double Range) const
{
	double *disA = new double[numA];

	double temp;
	double aB = MAX_DISTANCE;
	for (int i = 0; i < numA; i++)
	{
		for (int j = 0; j < numB; j++)
		{
			temp = (Apoints[i].x - Bpoints[j].x) * (Apoints[i].x - Bpoints[j].x)
					+ (Apoints[i].y - Bpoints[j].y) * (Apoints[i].y - Bpoints[j].y);
			//或者使用查表法
			//temp = m_disTable[abs(Apoints[i].x - Bpoints[j].x)][abs(Apoints[i].y - Bpoints[j].y)];

			// while b in B, get min|| a - b ||
			aB = std::min(temp,aB);
		}
		disA[i] = aB;
		// 注意下面这条语句
		aB = MAX_DISTANCE;
	}

	sort(disA, numA);
	double dis;
	// hausdorff 距离改进版:部分hausdorff距离
	dis = disA[(int)(numA * Range) - 1];
	// 也可以尝试平均距离:meanDistance(),使用meanDistance()则不需要对距离数组排序
	// dis = meanDistance(disA, numA);

	delete []disA;
	return dis;
}/*computeDirDistance()*/

/*
* 函数名称:drawMatch()
* 函数功能:在待匹配图中画出匹配结果区域
* 函数入口: 
* 输入参数: img指针默认指向m_srcImg,可以将待匹配图像的jpeg格式图像指针传入,以使结果更加直观
* 输出参数:
* 返 回 值: void
* 其它说明: 
*/
void CHausdorff::drawMatch(const char *name, IplImage *img)
{
	CvPoint pt;
	pt.x = m_matchPoint.x + m_modelImg->width;
	pt.y = m_matchPoint.y + m_modelImg->height;

	if (!img)
	{
		img = m_srcImg;
	}

	cvRectangle(img, m_matchPoint, pt, cvScalar(0,0,255));
	cvShowImage(name, img);
}

/*
* 函数名称:sort
* 函数功能:对数组进行升序排序
* 函数入口: 
* 输入参数:待排序数组指针及数组个数
* 输出参数:
* 返 回 值: void
* 其它说明: 
*/
void CHausdorff::sort(double a[],int n) const //升序
{ 
	double temp;
	for(int i=0;i<n;i++) 
		for(int j=i+1;j<n;j++) 
		{ 
			if(a[i]>a[j]) 
			{  
				temp=a[i]; 
				a[i]=a[j]; 
				a[j]=temp; 
			} 
		} 
}

/*
* 函数名称:meanDistance
* 函数功能:对距离数组求平均值
* 函数入口: 
* 输入参数:距离数组指针及数组个数
* 输出参数:
* 返 回 值: 距离数组的平均值
* 其它说明: 
*/
double CHausdorff::meanDistance(double a[], int n) const
{
	double sum = 0;

	for (int i = 0; i < n; i++)
	{
		sum += a[i];
	}
	sum /= n;
	return sum;
}

/*
* 函数名称:createTable
* 函数功能:创建距离变换表
* 函数入口: 
* 输入参数:NULL
* 输出参数:距离变换表的指针
* 返 回 值: void
* 其它说明: 
*/
void CHausdorff::createTable()
{
	int wm, hm, r;
	wm = m_modelImg->width;
	hm = m_modelImg->height;

	r = std::max(wm,hm);

	m_disTable = new double*[r];
	for (int i = 0; i < r; i++)
	{
		m_disTable[i] = new double[r];
	}

	for (int j = 0; j < r; j++)
	{
		for(int i = 0; i < r; i++)
		{
			m_disTable[j][i] = i*i + j*j;
			m_disTable[i][j] = m_disTable[j][i];
		}
	}
}

/*
* 函数名称:freeTable
* 函数功能:释放距离变换表内存
* 函数入口: 
* 输入参数:
* 输出参数:
* 返 回 值: void
* 其它说明: 
*/
void CHausdorff::freeTable()
{
	int wm, hm, r;
	wm = m_modelImg->width;
	hm = m_modelImg->height;

	r = std::max(wm,hm);

	for (int i = 0; i < r; i++)
	{
		delete []m_disTable[i];
	}
	delete []m_disTable;
}

CFeatures类定义

CFeatures.h文件

/******************************************
* Copyright (C) 2015 HolaMirai(HolaMirai@163.com)
* All rights reserved.
* 
* 文件名:CFeatures.h
* 摘要:图像前置处理,用于获取特征点
* 当前版本:V1.0,2015年9月13日,HolaMirai,创建该文件
* 历史记录:...
******************************************/


/*
* BUG:	1.使用HARRIS、SIFT、SURF提取特征点时,Debug版本耗时非常长,release版本正常
		2.使用HARRIS、SIFT、SURF提取特征点时,CFeatures类不能正确析构,初步判断是dll和EXE堆释放错误,
		而且出错点很可能是 m_vecPoints向量问题
*/




/*
* 类定义说明
*/
/********************************************
* CFeatures类
* CFeatures类接受一个int值,表示特征点类型
* 使用getFeatures()函数可以得到特征点的二值化图像
* 一个工程只需定义一个CFeatures类的实例


********************************************/

#ifndef CFEATURES_H
#define CFEATURES_H

/*
* 特征点类型
*/
enum feature_type
{
	FEATURE_CANNY,		//特征点为CANNY边缘点
	FEATURE_HARRIS,		//特征点为Harris特征点
	FEATURE_SIFT,		//特征点为SIFT特征点
	FEATURE_SURF,		//特征点为SURF特征点
};

#include "cv.h"
#include <vector>

/*
* 类定义
*/
class CFeatures
{
public:
	CFeatures(int feature_type);
	~CFeatures();

public:
	void getFeatures(IplImage *grayImg, IplImage *featuresImg);
	void drawFeatures(const char *name, IplImage *img);

private:
	void vecPointsToImage(IplImage *featuresImg);

public:
	IplImage *m_featuresImg;
	IplImage *m_imgShow;
	std::vector<cv::KeyPoint> m_vecPoints;

private:
	int m_type;
};

#endif
CFeatures.cpp文件

/******************************************
* Copyright (C) 2015 HolaMirai(HolaMirai@163.com)
* All rights reserved.
* 
* 文件名:CFeatures.cpp
* 摘要:图像前置处理,用于获取特征点
* 当前版本:V2.0,2015年9月14日,HolaMirai,完成四种特征点获取方法
* 历史记录:V1.0,2015年9月13日,HolaMirai,创建该文件
******************************************/

#include "CFeatures.h"
#include "highgui.h"
#include <opencv2/nonfree/nonfree.hpp>  
using namespace cv;

/***********************************************/

/*
* 函数名称:CFeatures
* 函数功能:CFeatures类构造函数
* 函数入口: 
* 输入参数: 需要获取的特征点的特征点类型,值为enum feature_type其中一个
* 输出参数:无
* 返 回 值:
* 其它说明: 
*/
CFeatures::CFeatures(int feature_type)
{
	m_type = feature_type;
	initModule_nonfree();//if use SIFT or SURF
}

/*
* 函数名称:~CFeatures
* 函数功能:CFeatures类析构函数
* 函数入口: 
* 输入参数: 
* 输出参数:
* 返 回 值:
* 其它说明: 
*/
CFeatures::~CFeatures()
{

}

/*
* 函数名称:getFeatures
* 函数功能:获取特征点
* 函数入口: 
* 输入参数: 待搜索图像的灰度图 grayImg 指针, 接受特征点的灰度图像指针 featuresImg, featuresImg与 grayImg尺寸相同
* 输出参数:特征点的灰度图像 featuresImg
* 返 回 值:
* 其它说明: 
*/
void CFeatures::getFeatures(IplImage *grayImg, IplImage *featuresImg)
{
	switch (m_type)
	{
	case FEATURE_CANNY:
		{
			assert(grayImg->width == featuresImg->width &&
				grayImg->height == featuresImg->height &&
				grayImg->nChannels == grayImg->nChannels);

			cvCanny(grayImg,featuresImg,50,150);
			break;
		}
	case FEATURE_HARRIS:
		{
			Ptr<FeatureDetector> detector = FeatureDetector::create( "HARRIS" );    //特征点寻找
			detector->detect(grayImg, m_vecPoints);
			vecPointsToImage(featuresImg);
			break;
		}

	case FEATURE_SIFT:
		{
			Ptr<FeatureDetector> detector = FeatureDetector::create( "SIFT" );    //特征点寻找
			detector->detect(grayImg, m_vecPoints);
			vecPointsToImage(featuresImg);
			break;
		}

	case FEATURE_SURF:
		{
			Ptr<FeatureDetector> detector = FeatureDetector::create( "SURF" );    //特征点寻找
			detector->detect(grayImg, m_vecPoints);
			vecPointsToImage(featuresImg);
			break;
		}
	default:
		break;
	}
} /*getFeatures()*/

/*
* 函数名称:vecPointsToImage
* 函数功能:将vector类型的特征点变换成 IplImage 图像类型
* 函数入口: 
* 输入参数: 特征点向量m_vecPoints, 接受特征点的灰度图像指针 featuresImg
* 输出参数:特征点的灰度图像 featuresImg
* 返 回 值:
* 其它说明: 
*/
void CFeatures::vecPointsToImage(IplImage *featuresImg)
{
	vector<KeyPoint>::iterator it;
	vector<KeyPoint>::iterator end_it = m_vecPoints.end();

	cvZero(featuresImg);

	int w,h;
	uchar *ptr;
	for (it = m_vecPoints.begin(); it != end_it; it++)
	{
		w= (int)it->pt.x;
		h = (int)it->pt.y;
		ptr = (uchar *)(featuresImg->imageData + h*featuresImg->widthStep + w);
		// 特征点置255,其他置0
		*ptr = 255;
	}
	ptr = NULL;
}/*vecPointsToImage()*/

/*
* 函数名称:drawFeatures
* 函数功能:画出特征点
* 函数入口: 
* 输入参数: 显示窗口 name, 在哪副图像上画出特征点的图像指针 img
* 输出参数:
* 返 回 值:void
* 其它说明:画出的是最近一次处理的图片的特征点
*/
void CFeatures::drawFeatures(const char *name, IplImage *img)
{
	IplImage *m_imgShow = cvCloneImage(img);

	vector<KeyPoint>::iterator it;
	vector<KeyPoint>::iterator end_it = m_vecPoints.end();

	CvPoint center;
	for (it = m_vecPoints.begin(); it != end_it; it++)
	{
		center.x = (int)it->pt.x;
		center.y  = (int)it->pt.y;

		cvCircle(m_imgShow,center,3,cvScalar(rand()%255,rand()%255,rand()%255));
	}
	cvShowImage(name,m_imgShow);
	cvReleaseImage(&m_imgShow);
}/*drawFeatures()*/


测试程序文件

huas.cpp代码

/******************************************
* Copyright (C) 2015 HolaMirai(HolaMirai@163.com)
* All rights reserved.
* 
* 文件名:haus.cpp
* 摘要:包含main函数的主文件,用于测试CHausdorff类, CFeatures类
* 当前版本:V2.0,2015年9月14日,添加CFeatures类,并使用CFeatures类来获取特征点
* 历史记录:V1.0,2015年9月7日,HolaMirai,创建该文件
******************************************/

#include "opencv2/opencv.hpp"
#include "iostream"
#include "CHausdorff.h"
#include "CFeatures.h"
#include "windows.h"

using namespace std;
using namespace cv;

//单张图片匹配
void main()
{
	char srcName[] = "sg.jpg";
	char modelName[] = "sgt.jpg";

	IplImage *srcColor = cvLoadImage(srcName,1);
	IplImage *modelColor = cvLoadImage(modelName,1);

	IplImage *srcGray = cvLoadImage(srcName,0);
	IplImage *modelGray = cvLoadImage(modelName,0);

	IplImage *srcFeat = cvCreateImage(cvGetSize(srcGray),IPL_DEPTH_8U,1);
	IplImage *modelFeat = cvCreateImage(cvGetSize(modelGray),IPL_DEPTH_8U,1);

	CFeatures features(FEATURE_HARRIS);


	features.getFeatures(srcGray,srcFeat);
	features.drawFeatures("src",srcColor);
	features.getFeatures(modelGray,modelFeat);
	features.drawFeatures("model",modelColor);
	

	CHausdorff haus(modelFeat,srcFeat,8,8);

	DWORD start_t = GetTickCount(); 
	haus.match();
	DWORD end_t = GetTickCount();

	cout<<"匹配耗时:"<<end_t - start_t<<"ms"<<endl;

	haus.drawMatch("resultMatch",srcColor);

	cvWaitKey(0);
	//system("pause");
	cvReleaseImage(&srcColor);
	cvReleaseImage(&modelColor);
	cvReleaseImage(&srcGray);
	cvReleaseImage(&modelGray);
	cvReleaseImage(&srcFeat);
	cvReleaseImage(&modelFeat);
	cvDestroyAllWindows();

}


//从相机中获取图像连续匹配
/*
void main()
{
	char modelName[] = "m1.jpg";

	CvCapture *capture = cvCreateCameraCapture(0);
	IplImage *srcColor = cvQueryFrame(capture);
	IplImage *modelColor = cvLoadImage(modelName,1);

	IplImage *srcGray = cvCreateImage(cvGetSize(srcColor),IPL_DEPTH_8U,1);
	IplImage *modelGray = cvLoadImage(modelName,0);

	IplImage *srcFeat = cvCreateImage(cvGetSize(srcColor),IPL_DEPTH_8U,1);
	IplImage *modelFeat = cvCreateImage(cvGetSize(modelColor),IPL_DEPTH_8U,1);

	CFeatures features(FEATURE_HARRIS);
	features.getFeatures(modelGray,modelFeat);

	char winSrc[] = "src";
	cvNamedWindow("src",1);

	CHausdorff haus(modelFeat,NULL,8,8);

	for (int i = 0; i < 30; i++)
	{
		srcColor = cvQueryFrame(capture);
		cvShowImage(winSrc,srcColor);
		cvWaitKey(30);
	}

	while (cvWaitKey(30) != 'q')
	{
		srcColor = cvQueryFrame(capture);

		cvCvtColor(srcColor,srcGray,CV_BGR2GRAY);
		features.getFeatures(srcGray,srcFeat);

		haus.setSourceImage(srcFeat);

		DWORD start_t = GetTickCount(); 
		haus.match();
		DWORD end_t = GetTickCount();

		cout<<"匹配耗时:"<<end_t - start_t<<"ms"<<endl;

		haus.drawMatch("resultMatch",srcColor);
	}

	cvWaitKey(0);
	//system("pause");
	cvReleaseImage(&srcColor);
	cvReleaseImage(&modelColor);
	cvReleaseImage(&srcGray);
	cvReleaseImage(&modelGray);
	cvReleaseImage(&srcFeat);
	cvReleaseImage(&modelFeat);
	cvDestroyAllWindows();

}
*/



结果:

使用Harris特征点进行匹配,release版本耗时为203ms,基本可以满足实时性要求

输入带匹配图和模板图,结果如下图所示:




 转载请注明作者和出处:http://blog.csdn.net/holamirai,未经允许请勿用于商业用途

  • 11
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 19
    评论
图像 Hausdorff 距离是一种常用于度量两个图像之间的相似度的指标,它可以评估两个图像中的最大差异程度。在图像匹配中,可以使用 Hausdorff 距离来计算图像之间的相似度,从而进行匹配。 在 Python 中,可以使用 OpenCV 库以及 NumPy 库来实现图像 Hausdorff 距离匹配。以下是一种简单的实现方法: 1. 导入所需的库: ```python import cv2 import numpy as np ``` 2. 加载两个图像(可以是灰度图或彩色图): ```python image1 = cv2.imread("image1.jpg") image2 = cv2.imread("image2.jpg") ``` 3. 将图像转换为灰度图(如果图像不是灰度图): ```python gray_image1 = cv2.cvtColor(image1, cv2.COLOR_BGR2GRAY) gray_image2 = cv2.cvtColor(image2, cv2.COLOR_BGR2GRAY) ``` 4. 使用 OpenCV 的 `distanceTransform` 函数计算图像的距离变换。这将返回一个浮点数数组,表示图像中每个像素到最近边缘的距离: ```python dist1 = cv2.distanceTransform(gray_image1, cv2.DIST_L2, 3) dist2 = cv2.distanceTransform(gray_image2, cv2.DIST_L2, 3) ``` 5. 计算 Hausdorff 距离: ```python hausdorff_distance = np.max(dist1 * cv2.compare(dist1, dist2, cv2.CMP_LE)) ``` 以上代码中,`np.max` 函数用于找到图像中的最大值,`cv2.compare` 函数用于比较两个距离变换后的图像,并生成一个比较结果图像。 最后,`hausdorff_distance` 变量将包含计算出的 Hausdorff 距离值,可以用于衡量两个图像的相似度。 需要注意的是,图像 Hausdorff 距离的计算复杂度较高,计算大图像或大数据集时可能较耗时。不过,这个简单的实现可以提供一个基本的框架,您可以根据具体需求进行调整和优化。
评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值