1、形状检测
#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
using namespace std;
using namespace cv;
/*
contourArea() 计算整个或部分轮廓的面积
*/
Mat imgGray, imgBlur, imgCanny, imgDil, imgErode;
void getContours(Mat imgDil, Mat img)
{
//里面是一些向量 点
//{ {},
// {},
// {}}
vector<vector<Point>> contours;
//四个整数值 Vec4i是Vec<int,4>的别名,定义了一个“向量内每一个元素包含了4个int型变量”的向量。
vector<Vec4i>hierarchy;
//findContours :https://blog.csdn.net/dcrmg/article/details/51987348
findContours(imgDil, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
//画轮廓 -1 绘制所有 2---厚度
//drawContours(img, contours, -1, Scalar(255, 241, 29), 3);
//过滤
vector<vector<Point>> conPoly(contours.size());
vector<Rect>boundRect(contours.size());
string objectType;
//首先遍历所有轮廓
for (int i = 0; i < contours.size(); i++)
{
//计算整个或部分轮廓的面积
int area = contourArea(contours[i]);
cout << area << endl;
if (area > 1000)
{
/**
* @brief 计算轮廓的周长.
*
* \param contours 表示图像的轮廓
* \param true 封闭的
*/
float peri = arcLength(contours[i], true);
//找到角点 一个连续光滑曲线折线化,对图像轮廓点进行多边形拟合
approxPolyDP(contours[i], conPoly[i], 0.02 * peri, true);
drawContours(img, conPoly, i, Scalar(255, 21, 250), 2);
cout << conPoly[i].size() << endl;
//边界框
boundRect[i] = boundingRect(conPoly[i]);
//rectangle(img, boundRect[i].tl(), boundRect[i].br(), Scalar(241, 130, 200), 3);
int objCol = (int)conPoly[i].size();
if (objCol == 3) { objectType = "Triangle"; }
if (objCol == 4) {
float aspRatio = (float)boundRect[i].width / (float)boundRect[i].height;
if (aspRatio >= 0.95 && aspRatio <= 1.05)
objectType = "Square";
else
objectType = "Rect";
}
if (objCol > 4) { objectType = "Circle"; }
putText(img, objectType, { boundRect[i].x + 20,boundRect[i].y + 10 }, FONT_HERSHEY_DUPLEX, 0.75, Scalar(219, 219, 200));
}
}
}
/ Color Detection ///
void main()
{
string path = "Resources/shapes.png";
Mat img = imread(path);
if (img.empty())
{
cout << "找不到相关图像,检查路径" << endl;
return ;
}
//预处理
cvtColor(img, imgGray, COLOR_BGR2GRAY);
GaussianBlur(imgGray, imgBlur, Size(3, 3), 3, 0);
Canny(imgBlur, imgCanny, 25, 75);
Mat Kernel = getStructuringElement(MORPH_RECT, Size(5, 5));
dilate(imgCanny, imgDil, Kernel);
//获取轮廓
getContours(imgDil, img);
imshow("Image", img);
//imshow("Image Gray", imgGray);
//imshow("Image Blur", imgBlur);
//imshow("Image Canny", imgCanny);
//imshow("Image Dil", imgDil);
//imshow("Image Dil", imgDil);
waitKey(0);
}
效果图:
1、灰度匹配
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>
using namespace std;
using namespace cv;
/* 基于灰度匹配的程序实现——使用滑条选择 method */
int match_method2 = 1;
int max_Trackbar = 5;
const char* match_method = "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";
void MatchingMethod(int, void*);
class Histogram_Matching
{
public:
Histogram_Matching();
~Histogram_Matching();
void ImgMatch2();/*基于滑动条进行多种灰度方法匹配*/
void Histogram_Matching_Demo();/* 基于灰度匹配的程序实现 */
void Histogram_Matching_Template_coder();/* 基于灰度匹配的程序提炼模板 */
private:
};
Histogram_Matching::Histogram_Matching()
{
}
Histogram_Matching::~Histogram_Matching()
{
}
Mat resize_srcImg(cv::Mat inputImg, cv::Mat outputImg)
{
int width = inputImg.cols;//图像宽度
int height = inputImg.rows;//图像高度
if (width > 1920 || height > 1080)
{
float factor = min((float)1920 / width, (float)1080 / height);
resize(inputImg, outputImg, Size(factor * width, factor * height));
width *= factor;
height *= factor;
}
return outputImg;
}
void MatchingMethod(int, void*)
{
//Mat srcImg = imread("images/ipad_test04.jpg");
Mat srcImg = imread("images/temp2.bmp");
Mat tempImg = imread("images/tempImg.png");
int width = srcImg.cols - tempImg.cols + 1;
int height = srcImg.rows - tempImg.rows + 1;
int src_width = srcImg.cols;//图像宽度
int src_height = srcImg.rows;//图像高度
if (src_width > 1920 || src_height > 1080)
{
float factor = min((float)1920 / src_width, (float)1080 / src_height);
resize(srcImg, srcImg, Size(factor * src_width, factor * src_height));
src_width *= factor;
src_height *= factor;
}
Mat resultImg(Size(width, height), CV_32FC1);
//2.模版匹配
matchTemplate(srcImg, tempImg, resultImg, match_method2);
//3.正则化(归一化到0-1)
normalize(resultImg, resultImg, 0, 1, NORM_MINMAX, -1);
//4.找出resultImg中的最大值及其位置
double minValue = 0;
double maxValue = 0;
Point minPosition;
Point maxPosition;
minMaxLoc(resultImg, &minValue, &maxValue, &minPosition, &maxPosition);
/// 对于方法 SQDIFF 和 SQDIFF_NORMED, 越小的数值代表更高的匹配结果. 而对于其他方法, 数值越大匹配越好
if (match_method2 == TM_SQDIFF || match_method2 == TM_SQDIFF_NORMED)
{
maxPosition = minPosition;
}
else
{
maxPosition = maxPosition;
}
//4.遍历resultImg,给定筛选条件,筛选出前几个匹配位置
int tempX = 0;
int tempY = 0;
char prob[10] = { 0 };
//4.1遍历resultImg
for (int i = 0; i < resultImg.rows; i++)
{
for (int j = 0; j < resultImg.cols; j++)
{
//4.2获得resultImg中(j,x)位置的匹配值matchValue
double matchValue = resultImg.at<float>(i, j);
sprintf_s(prob, "%.4f", matchValue);
//4.3给定筛选条件
//条件1:概率值大于0.9
//条件2:任何选中的点在x方向和y方向上都要比上一个点大5
if (matchValue > 0.9001 && abs(i - tempY) > 5 && abs(j - tempX) > 5)
{
//5.给筛选出的点画出边框和文字
rectangle(srcImg, Point(j, i), Point(j + tempImg.cols, i + tempImg.rows), Scalar(0, 255, 0), 1, 8);
putText(srcImg, prob, Point(j, i + 100), FONT_HERSHEY_COMPLEX, 1, Scalar(0), 2);
tempX = j;
tempY = i;
}
}
}
//5.根据resultImg中的最大值位置在源图上画出矩形
rectangle(srcImg, maxPosition, Point(maxPosition.x + tempImg.cols, maxPosition.y + tempImg.rows), Scalar(0, 0, 255), 2, 8);
imshow("image_window", srcImg);
imshow("temp_window", tempImg);
}
/*基于滑动条进行多种灰度方法匹配*/
void Histogram_Matching::ImgMatch2()//24.图像匹配2
{
/// 创建窗口
namedWindow("image_window", WINDOW_AUTOSIZE);
namedWindow("temp_window", WINDOW_AUTOSIZE);
/// 创建滑动条
createTrackbar("match_method", "image_window", &match_method2, max_Trackbar, MatchingMethod);
MatchingMethod(0, 0);
waitKey(0);
}
/* 基于灰度匹配的程序实现 */
void Histogram_Matching::Histogram_Matching_Demo()//24.图像匹配3
{
Mat srcImg = imread("images/2D_srcImg/temp11.bmp");
//Mat srcImg = imread("images/ipad_test03.jpg");
Mat tempImg = imread("images/wxTemp.png");
//1.构建结果图像resultImg(注意大小和类型)
//如果原图(待搜索图像)尺寸为W x H, 而模版尺寸为 w x h, 则结果图像尺寸一定是(W-w+1)x(H-h+1)
//结果图像必须为单通道32位浮点型图像
int width = srcImg.cols - tempImg.cols + 1;
int height = srcImg.rows - tempImg.rows + 1;
int src_width = srcImg.cols;//图像宽度
int src_height = srcImg.rows;//图像高度
if (src_width > 1920 || src_height > 1080)
{
float factor = min((float)1920 / src_width, (float)1080 / src_height);
resize(srcImg, srcImg, Size(factor * src_width, factor * src_height));
src_width *= factor;
src_height *= factor;
}
//cout << srcImg.rows << "," << srcImg.cols << endl;
Mat resultImg(Size(width, height), CV_32FC1);
//2.模版匹配
matchTemplate(srcImg, tempImg, resultImg, TM_CCOEFF_NORMED);
imshow("result", resultImg);
//3.正则化(归一化到0-1)
normalize(resultImg, resultImg, 0, 1, NORM_MINMAX, -1);
//4.遍历resultImg,给定筛选条件,筛选出前几个匹配位置
int tempX = 0;
int tempY = 0;
char prob[10] = { 0 };
//4.1遍历resultImg
//4.找出resultImg中的最大值及其位置
double minValue = 0;
double maxValue = 0;
Point minPosition;
Point maxPosition;
minMaxLoc(resultImg, &minValue, &maxValue, &minPosition, &maxPosition);
//for (int i = 0; i < resultImg.rows; i++)
//{
// for (int j = 0; j < resultImg.cols; j++)
// {
// //4.2获得resultImg中(j,x)位置的匹配值matchValue
// double matchValue = resultImg.at<float>(i, j);
// /*sprintf_s(prob, "%.2f", matchValue);*/
// sprintf_s(prob, "%.4f", matchValue);
// //4.3给定筛选条件
// //条件1:概率值大于0.9
// //条件2:任何选中的点在x方向和y方向上都要比上一个点大5
// if (matchValue > 0.9 && abs(i - tempY) > 5 && abs(j - tempX) > 5)
// {
// //5.给筛选出的点画出边框和文字
// rectangle(srcImg, Point(j, i), Point(j + tempImg.cols, i + tempImg.rows), Scalar(0, 255, 0), 1, 8);
// putText(srcImg, prob, Point(j, i + 100), FONT_HERSHEY_COMPLEX, 1, Scalar(0), 2);
// tempX = j;
// tempY = i;
// }
// }
//}
rectangle(srcImg, maxPosition, Point(maxPosition.x + tempImg.cols, maxPosition.y + tempImg.rows), Scalar(0, 0, 255), 2, 8);
cout << "目标中心位置:" << maxPosition.x + tempImg.cols / 2 << "," << maxPosition.y + tempImg.rows / 2 << endl;
imshow("srcImg", srcImg);
imshow("template", tempImg);
waitKey(0);
}
/* 基于灰度匹配的程序提炼模板 */
//method:
// CV_TM_SQDIFF : 平方差匹配,最好时候为0;——不具备旋转
// CV_TM_SQDIFF_NORMED :归一化平方差匹配,最好时候为0;——不具备旋转
// CV_TM_CCORR :相关性匹配法,最差为0;
// CV_TM_CCORR_NORMED :归一化相关性匹配法,最差为0;
// CV_TM_CCOEFF :系数匹配法,最好匹配为1;
// CV_TM_CCOEFF_NORMED :化相关系数匹配法,最好匹配为1;——匹配度较好-可以抵抗轻度旋转
//images/ipad_test04.jpg images/temp2.bmp 匹配有误
void Histogram_Matching::Histogram_Matching_Template_coder()
{
//Mat srcImg = imread("images/temp2.bmp");
//Mat srcImg = imread("images/ipad_test04.jpg");
Mat srcImg = imread("images/2D_srcImg/temp11.bmp");
//Mat tempImg = imread("images/wxTemp1.png");
Mat tempImg = imread("images/qqTemp1.png");
int width = srcImg.cols - tempImg.cols + 1;
int height = srcImg.rows - tempImg.rows + 1;
//resize_srcImg(srcImg, srcImg);
//cout << srcImg.rows << "," << srcImg.cols << endl;
int src_width = srcImg.cols;//图像宽度
int src_height = srcImg.rows;//图像高度
if (src_width > 1920 || src_height > 1080)
{
float factor = min((float)1920 / src_width, (float)1080 / src_height);
resize(srcImg, srcImg, Size(factor * src_width, factor * src_height));
src_width *= factor;
src_height *= factor;
}
Mat resultImg(Size(srcImg.cols, srcImg.rows), CV_32FC1);
//2.模版匹配
matchTemplate(srcImg, tempImg, resultImg, TM_CCOEFF_NORMED);
//3.正则化(归一化到0-1)
normalize(resultImg, resultImg, 0, 1, NORM_MINMAX, -1);
imshow("result", resultImg);
//4.找出resultImg中的最大值及其位置
double minValue = 0;
double maxValue = 0;
Point minPosition;
Point maxPosition;
minMaxLoc(resultImg, &minValue, &maxValue, &minPosition, &maxPosition);
RNG rng(12345);
//4.1遍历resultImg
int tempX = 0;
int tempY = 0;
char prob[10] = { 0 };
for (int i = 0; i < resultImg.rows; i++)
{
for (int j = 0; j < resultImg.cols; j++)
{
//4.2获得resultImg中(i,j)位置的匹配值matchValue
double matchValue = resultImg.at<float>(i, j);
sprintf_s(prob, "%.4f", matchValue);
//4.3给定筛选条件
//条件1:概率值大于0.9
//条件2:任何选中的点在x方向和y方向上都要比上一个点大30——放置重复检测同一个目标
if (matchValue > 0.7 && abs(i - tempX) > 30 && abs(j - tempY) > 30)
{
//5.给筛选出的点画出边框和文字
rectangle(srcImg, Point(j, i), Point(j + tempImg.cols, i + tempImg.rows), Scalar(0, 255, 255), 1, 8);
putText(srcImg,prob,Point(j,i+100),FONT_HERSHEY_COMPLEX,1, Scalar(0), 2);
tempX = i;
tempY = j;
}
}
}
//5.画
rectangle(srcImg, maxPosition, Point(maxPosition.x + tempImg.cols, maxPosition.y + tempImg.rows), Scalar(0, 0, 255), 2, 8);
cout << "目标中心位置:" << maxPosition.x + tempImg.cols / 2 << "," << maxPosition.y + tempImg.rows / 2 << endl;
imshow("srcImg", srcImg);
waitKey(0);
}
int main()
{
Histogram_Matching hist_match;
hist_match.Histogram_Matching_Template_coder();
//hist_match.Histogram_Matching_Demo();
//hist_match.ImgMatch2();//不要
return 0;
}
问题:如果模板图和原图比列发生变化,会匹配错误
#include<iostream>
#include<string>
#include<vector>
#include<opencv2\opencv.hpp>
//#include"Tracker.h"
using namespace cv;
using namespace std;
namespace global {
bool paused = true; //单击鼠标右键,暂停标志
Mat displayImg; //绘制选择目标时鼠标的拖动痕迹
bool selectObject = false; //selectObject的初始值为false,
bool isRoiReady = false; //ROI区域是否已经选择好
Point origin; //ROI区域的左上角起始位置
Rect selectedRoi; //最终通过鼠标选择的ROI区域
static void onMouse(int event, int x, int y, int, void*) {
if (selectObject) //鼠标左键被按下后,该段语句开始执行
{
selectedRoi.x = MIN(x, origin.x);
selectedRoi.y = MIN(y, origin.y);
selectedRoi.width = std::abs(x - origin.x);
selectedRoi.height = std::abs(y - origin.y);
selectedRoi &= Rect(0, 0, displayImg.cols, displayImg.rows); //不能越界
rectangle(displayImg, selectedRoi, Scalar(0, 0, 255), 1); //画出鼠标选择框
}
switch (event)
{
//当在第一帧按下鼠标左键后,selectObject被置位1,拖动鼠标,开始选择目标的矩形区域
case EVENT_LBUTTONDOWN:
origin = Point(x, y);
selectedRoi = Rect(x, y, 0, 0);
selectObject = true;
isRoiReady = false;
break;
//直到鼠标左键抬起,标志着鼠标区域选择完毕。selectObject被置为false
case EVENT_LBUTTONUP:
selectObject = false;
if (selectedRoi.width > 0 && selectedRoi.height > 0) {
isRoiReady = true;
}
cout << "目标区域已经选择完毕" << endl;
cout << "选中的矩形区域为: " << selectedRoi << endl;
break;
//单击右键,暂停/开始
case EVENT_RBUTTONDOWN:
paused = !paused;
break;
}
}
}
//**********下面用于自己定义的模板匹配方法做匹配*******//
float MatchTemplate(const Mat& src, const Mat& temp1, Point2i& match_location, int match_method)
{
CV_Assert((src.type() == CV_8UC1) && (temp1.type() == CV_8UC1)); //申明只能处理单通道的图像
//原图像和模板的尺寸
int src_width = src.cols;
int src_height = src.rows;
int temp1_cols = temp1.cols;
int temp1_rows = temp1.rows;
int y_end = src_height - temp1_rows + 1;
int x_end = src_width - temp1_cols + 1;
//在匹配过程中,记录最匹配的位置和匹配度
float match_degree = FLT_MAX; //给匹配度赋一个最大匹配度初始值
int y_match = -1, x_match = -1;
//从上到下扫描原图像
for (int y = 0; y < y_end; y++)
{
//从左到右扫描原图像
for (int x = 0; x < x_end; x++)
{
//src(y,x)位置上与模板的匹配度
float match_yx = 0.0f;
//将模板左上角temp1(0,0)对齐到src(y,x)位置,在模板内累加每个采样像素点上的差异
for (int r = 0; r < temp1_rows; r++) {
for (int c = 0; c < temp1_cols; c++) {
uchar src_val = src.ptr<uchar>(y + r)[x + c];
uchar temp1_val = temp1.ptr<uchar>(r)[c];
if (match_method == 0) //SQDIFF=0
match_yx += float(std::abs(src_val - temp1_val) * std::abs(src_val - temp1_val));
if (match_method == 1) //SADIFF=1
match_yx += float(std::abs(src_val - temp1_val));
}
}
//与历史最好的差异度进行比较,找出差异最小的点
if (match_degree > match_yx) {
match_degree = match_yx;
y_match = y;
x_match = x;
}
}
}
match_location = Point2i(x_match, y_match);
return match_degree;
}
//**********以上用自己定义的模板匹配方法做匹配*********//
int main06(int argc, char* argv[])
{
//******下面用于自己定义的模板匹配方法做匹配*******//
//const string image_file = "images/temp1.bmp";
const string image_file = "images/ipad_test01.jpg";
Mat srcImg = imread(image_file, IMREAD_GRAYSCALE);
//用来显示结果
Mat displayImg;
srcImg.copyTo(displayImg);
//设置全局变量
global::isRoiReady = false;
global::selectObject = false;
global::displayImg = displayImg;
const string winname = "Result Image";
namedWindow(winname, WINDOW_AUTOSIZE);
setMouseCallback(winname, global::onMouse, 0);
//循环显示图像,等待鼠标选择ROI区域
for (;;)
{
imshow(winname, displayImg);
//一旦选择好ROI区域,就进入处理
if (global::isRoiReady) {
//设置为false,处理完此次就接着等待鼠标选择
global::displayImg = false;
//提取鼠标选中的图像块
Rect roiRect = global::selectedRoi;
Mat roiImg = srcImg(roiRect).clone();
imshow("ROI Image", roiImg);//显示ROI图像块
//为原始图像增加高斯噪声
Mat noiseImg(srcImg.size(), srcImg.type());
cv::randn(noiseImg, Scalar(0), Scalar(30));
Mat workImg = noiseImg + srcImg;
//显示噪声污染的图像和选择的ROI区域
workImg.copyTo(displayImg);
rectangle(displayImg, global::selectedRoi, Scalar::all(0), 4);
imshow(winname, displayImg);
waitKey(15);
//选中的模板在噪声污染的图像上匹配
Point2i match_location;
int match_method = 0;
MatchTemplate(workImg, roiImg, match_location, match_method);
Rect matchedRoi(match_location.x, match_location.y, roiImg.cols, roiImg.rows);
//显示匹配结果
rectangle(displayImg, matchedRoi, Scalar::all(255), 2);
imshow(winname, displayImg);
waitKey(15);
}
waitKey(15);
}
}
自己求阈值
#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
using namespace std;
using namespace cv;
//全局变量
Mat srcImage, templateImage, dstImage;
const int trackbar_method_maxValue = 5;
int trackbar_method;
std::vector<cv::Point> aim_pos(2);
void getRGBvector(const Mat& src, vector<unsigned int>& count)//得到64维向量
{
int nRows = src.rows, nCols = src.cols * src.channels();
const uchar* p;
for (int i = 0; i < nRows; ++i)
{
p = src.ptr<uchar>(i);
for (int j = 0; j < nCols; j += 3)
{
int r = int(p[j]) / 64;
int g = int(p[j + 1]) / 64;
int b = int(p[j + 2]) / 64;
count[r * 16 + g * 4 + b]++;
}
}
}
double getVectorLength(vector<unsigned int>& vec)
{
long long res = 0;
for (int i = 0; i < vec.size(); i++)
res += vec[i] * vec[i];
return sqrt(res);
}
double getcos(vector<unsigned int>& count1, vector<unsigned int>& count2)
{
double len1 = getVectorLength(count1);
double len2 = getVectorLength(count2);
assert(len1 != 0 && len2 != 0);
long long sum = 0;
for (int i = 0; i < count1.size(); i++)
sum += count1[i] * count2[i];
return (double)sum / len1 / len2 > 0 ? (double)sum / len1 / len2 : 0;
}
double getsimilarity(const Mat& src1, const Mat& src2)
{
vector<unsigned int> count1(64), count2(64);
getRGBvector(src1, count1);
getRGBvector(src2, count2);
double res = getcos(count1, count2);
return res;
}
//定义回调函数
void method(int, void*)
{
Mat display;
srcImage.copyTo(display);
//创建输出矩阵
int dstImage_rows = srcImage.rows - templateImage.rows + 1;
int dstImage_cols = srcImage.cols - templateImage.cols + 1;
/**
* @brief 创建一个新的图像矩阵
* @param type 新矩阵类型.
*
*/
dstImage.create(dstImage_rows, dstImage_cols, srcImage.type());
/*
void cv::matchTemplate(
cv::InputArray image, // 用于搜索的输入图像, 8U 或 32F, 大小 W-H
cv::InputArray templ, // 用于匹配的模板,和image类型相同, 大小 w-h
cv::OutputArray result, // 匹配结果图像, 类型 32F, 大小 (W-w+1)-(H-h+1)
int method // 用于比较的方法
);
*/
matchTemplate(srcImage, templateImage, dstImage, trackbar_method); //模板匹配
normalize(dstImage, dstImage, 0, 1, NORM_MINMAX); //归一化处理
//通过minMaxLoc定位最佳匹配位置
double minValue, maxValue;
Point minLocation, maxLocation;
Point matchLocation;
/*
* minMaxLoc 函数的作用是在数组中找到全局最小和最大值。
src ,输入的数组,若是图像,需为单通道图像。
minVal,返回最小值的指针。若无需返回,此值设为 NULL。
maxVal,返回最大值的指针。若无需返回,此值设为 NULL。
minLoc,返回最小值位置的指针(二维情况下)。若无需返回,此值设为 NULL。
maxVal,返回最大值位置的指针(二维情况下)。若无需返回,此值设为 NULL。
mask,可选的掩膜操作,非零掩码元素用于标记待统计元素,需要与输入图像集有相同尺寸。
*/
minMaxLoc(dstImage, &minValue, &maxValue, &minLocation, &maxLocation, Mat());
//对于方法SQDIFF和SQDIFF_NORMED两种方法来讲,越小的值就有着更高的匹配结果
// 平方差匹配和标准平方差匹配
//而其余的方法则是数值越大匹配效果越好
if (trackbar_method == TM_SQDIFF || trackbar_method == TM_SQDIFF_NORMED)
{
matchLocation = minLocation;
}
else
{
matchLocation = maxLocation;
}
imshow("匹配图像", display);
double res = getsimilarity(srcImage, templateImage);
//这里是对角线画矩形
//参数:图片, 左上角, 右下角, 颜色, 线条粗细, 线条类型,点类型
rectangle(display, Point(matchLocation.x, matchLocation.y), Point(matchLocation.x + templateImage.cols, matchLocation.y + templateImage.rows), Scalar(255, 0, 0), 3);
cout << "目标位置:" << matchLocation.x + templateImage.cols / 2 << " " << matchLocation.y + templateImage.rows / 2 << std::endl;
//resize(display,display, Size(), 0.25, 0.25);//缩小4倍
//imshow("匹配图像", display);
cout << "res:" << 1.0 / (res + 1) << endl;
}
/**
* namedWindow():新建一个显示窗口
*
* \return
*/
int main()
{
srcImage = imread("images/ipad_test02.jpg");
//templateImage = imread("images/icon64_wx_logo.png");
templateImage = imread("images/wxTemp.png");
//判断文件是否加载成功
if (srcImage.empty() || templateImage.empty())
{
cout << "图像加载失败!" << endl;
return -1;
}
else
cout << "图像加载成功..." << endl << endl;
/**
* @brief 新建一个显示窗口
* @param 窗口名字
* @param 窗口标识 默认为WINDOW_AUTOSIZE 自动适应图片大小,并且不可手动更改
* WINDOW_NORMAL 用户可以改变这个窗口大小.
*
* \return
*/
namedWindow("原图像", WINDOW_AUTOSIZE);
namedWindow("模板图像", WINDOW_AUTOSIZE);
resize(srcImage, srcImage, Size(), 0.25, 0.25);//缩小4倍
imshow("原图像", srcImage);
imshow("模板图像", templateImage);
//定义轨迹条参数
trackbar_method = 1;
//char mathodName[50];
std::string methodName = "method";
namedWindow("匹配图像", WINDOW_AUTOSIZE);
//std::cout << "匹配方式:\n 0:SQDIFF\n 1:SQDIFF_NORMED\n 2:TM_CCORR\n 3:TM_CCORR_NORMEND\n 4:TM_COEFF\n 5:TM_COEFF_NORMED" << trackbar_method_maxValue << std::endl;
//sprintf(methodName, "匹配方式%d\n 0:SQDIFF\n 1:SQDIFF_NORMED\n 2:TM_CCORR\n 3:TM_CCORR_NORMEND\n 4:TM_COEFF\n 5:TM_COEFF_NORMED", trackbar_method_maxValue);
/**
* @brief 创建滚动条
* @param trackbarname:用来给这个滚动条取一个名字
* @param winname:用来指定你要把这个滚动条用到那个窗口上
* @param value:用来设置滑块初始值位置,同时记录滑块以后的位置
* @param count:用来指定滚动条可以滚动的最大值
* @param onChange:用来接收回调函数函数名的,默认值为0;
*
* \return
*/
createTrackbar(methodName, "匹配图像", &trackbar_method, trackbar_method_maxValue, method);
//double res = getsimilarity(srcImage, templateImage);
//cout << "res:" << 1.0 / (res + 1) << endl;
method(trackbar_method, 0);
waitKey(0);
return 0;
}