C++ 图片相似度比对(opencv库)

写在前面

opencv ,它的神秘,让我欣喜,它的奥妙,让我这个学弱望而却步,学习文档还大多是英文的,对于我这种学弱来说,实在是挑战。
也只能偶尔看看资料,发现有趣的demo代码,拿来学习一下,来解决自己内心饥渴。
偶然间发现一段有趣的代码,来与大家分享。

内容简介

操作系统:win7

开发IDE: VS2013

使用的开发库:opencv 2.4.10

使用的语言:C/C++


学习源码

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include 
#include 

using namespace std;
using namespace cv;

/// Global Variables
Mat img; Mat templ; Mat result;
char* image_window = "Source Image";
char* result_window = "Result window";

int match_method;
int max_Trackbar = 5;

/// Function Headers
void MatchingMethod(int, void*);

/** @function main */
int main(int argc, char** argv)
{
	/// Load image and template
	templ = imread("E:/hobby/mhxy/图片识别/图片/1.bmp", 1);
	img = imread("E:/hobby/mhxy/图片识别/测试图片/0001.bmp", 1);

	/// 
	namedWindow(image_window, CV_WINDOW_AUTOSIZE);
	namedWindow(result_window, CV_WINDOW_AUTOSIZE);

	/// Create Trackbar
	char* trackbar_label = "Method: \n 0: SQDIFF \n 1: SQDIFF NORMED \n 2: TM CCORR \n 3: TM CCORR NORMED \n 4: TM COEFF \n 5: TM COEFF NORMED";
	createTrackbar(trackbar_label, image_window, &match_method, max_Trackbar, MatchingMethod);

	MatchingMethod(0, 0);

	waitKey(0);
	return 0;
}

/**
* @function MatchingMethod
* @brief Trackbar callback
*/
void MatchingMethod(int, void*)
{
	/// 源图像显示
	Mat img_display;
	img.copyTo(img_display);

	/// 创建结果矩阵
	int result_cols = img.cols - templ.cols + 1;
	int result_rows = img.rows - templ.rows + 1;

	result.create(result_rows, result_cols, CV_32FC1);

	/// 匹配正常化
	matchTemplate(img, templ, result, match_method);
	normalize(result, result, 0, 1, NORM_MINMAX, -1, Mat());

	/// 本地化minMaxLoc的最佳匹配
	double minVal; double maxVal; Point minLoc; Point maxLoc;
	Point matchLoc;

	minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc, Mat());

	/// For SQDIFF and SQDIFF_NORMED, the best matches are lower values. For all the other methods, the higher the better
	if (match_method == CV_TM_SQDIFF || match_method == CV_TM_SQDIFF_NORMED)
	{
		matchLoc = minLoc;
	}
	else
	{
		matchLoc = maxLoc;
	}

	/// 告诉我你得到了什么
	rectangle(img_display, matchLoc, Point(matchLoc.x + templ.cols, matchLoc.y + templ.rows), Scalar::all(0), 2, 8, 0);
	rectangle(result, matchLoc, Point(matchLoc.x + templ.cols, matchLoc.y + templ.rows), Scalar::all(0), 2, 8, 0);

	imshow(image_window, img_display);
	imshow(result_window, result);

	return;
}


源码分析

Note: 我们假设读者已经了解图像读取函数imread ,并能使用 imshow 将图像显示到窗口,资料源于opencv官网及其它网络


namedWindow

原型:void namedWindow(const string&winname, intflags)

用途:创建窗口,配合imshow函数
参数:@param1 - 窗口名字   @param2 - 预留项

createTrackbar

原型:int createTrackbar(const string& trackbarname, const string&winname, int*value, intcount, TrackbarCallbackonChange=0, void*userdata=0)

用途:创建一个滑动条控件到一个窗口中

参数:@param1 - 滑动条控件区段标签名    @param2 - 父窗口的名称    @param3[output] - 它会实时反馈当前控件所指条下标    @param4 - 最大跟踪条目个数    @param5[callback] - 回调的第一个参数是搜索栏的位置,第二个参数是用户数据.


waitKey

原型:intwaitKey(intdelay=0)

用途:等待按键输入

参数:@param1 - 等待时间,0则为永久等待。


Mat::copyTo

原型:void Mat::copyTo(OutputArraym) const

用途:将一个Mat源的数据拷贝到指定参数源当中
参数:@param1 - 待拷入的数据源容器


Mat::create

原型:void Mat::create(introws, intcols, inttype)

用途:创建一个矩阵

参数:@param1 - 长或译行数    @param2 - 宽或译列数    @param3 - 矩阵的类型


cv::matchTemplate

原型:void matchTemplate(InputArrayimage, InputArraytemp, OutputArrayresult, intmethod)

用途:以method算法在image图片中搜索temp获得结果result 进行匹配和标准化

参数:@param1 - 搜索的源图片(它必须是8位或32位)    @param2 - 待搜索的目标图片(它的尺寸必须不大于@param1,并且是相同的数据类型)    @param3 - 比较后的结果    @param4 - 指定的比较算法(规则)


cv::normalize

原型:void normalize(const InputArraysrc, OutputArraydst, doublealpha=1, doublebeta=0, intnormType=NORM_L2, intrtype=-1, InputArraymask=noArray())

用途:使对应Mat参数标准化规范化归一化

参数:@param1 - 待规范的Mat源    @param2[output] - 输出规范后的结果源    @param3 -normalization模式的最小值    @param4 -normalization模式的最大值    @param5 -归一化的类型(常规选择NORM_MINMAX)    @param6 - 默认-1    @param7 默认数据类型


cv::minMaxloc

原型:void minMaxLoc(InputArraysrc, double*minVal, double*maxVal=0, Point*minLoc=0, Point*maxLoc=0, InputArraymask=noArray())

用途:与matchTemplate联合使用,测定查找图片的位置, SQDIFF 和 SQDIFF_NORMED,越小的数值代表更精确的匹配结果,而对于其它算法,数值越大匹配度越好

参数:


cv::rectangle

原型:void rectangle(CV_IN_OUT Mat& img, Point pt1, Point pt2, const Scalar& color, int thickness=1, int lineType=8, int shift=0);
用途:画矩形
参数:


个人心得

如何验证匹配结果

这函数可以匹配到某个相似的点,并返回匹配点的起点x,y值。
但是如果没有相似的点,他也会匹配到。这就让我纠结了。
在测试的过程中,我利用 matchTemplate的两个算法(SQDIFF、TM COEFF NORMED),或者三个算法进行重复测试,
发现如果匹配程度低的时候,这两个算法得出的结果大多会出现不一致的POS点,但匹配程度高的时候,两个算法得出的pos点大部分情况下都是一致的。


可供下载

源码demo

http://download.csdn.net/detail/csnd_ayo/9685551

开发IDE

http://pan.baidu.com/s/1qY5yYra

opencv: http://opencv.org



你可能感兴趣的:(C++,图片,opencv,识别,图片比对,C/C++,《C++,必知必会》)