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向量问题
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);
- 当frontRange = 1,backRange = 1,并使用sort()函数时,该类退化成原始Hausforff distance定义的匹配方法
- 当frontRange ,backRange 取值为0~1之间,并使用sort函数时,该类为改进型hausdorff distance:部分hausdorff distance.
- 当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,未经允许请勿用于商业用途