Opencv模板匹配

使用OpenCV和C++来识别彩色图片中的特定物体,如黑桃♠,通常涉及几个步骤:预处理图像、特征提取、对象检测等。下面是一个基本的示例代码,演示如何使用OpenCV的模板匹配方法来识别图片中的黑桃♠。

函数原型

cpp 复制代码
void matchTemplate(InputArray image, InputArray temp, OutputArray result, int method);

void matchTemplate(
    InputArray image,     // 输入的大图像
    InputArray templ,     // 输入的模板图像
    OutputArray result,   // 输出的匹配结果矩阵
    int method            // 匹配方法
);

参数说明:
image: 输入的大图像,它可以是灰度图像或者是彩色图像。
templ: 模板图像,它通常是较小的图像,我们希望在大图像中寻找这个模板的位置。
result: 匹配结果矩阵,输出的是一个二维矩阵,它的大小取决于输入图像和模板的大小,以及所选择的匹配方法。每个元素代表了相应位置的匹配程度。
method: 匹配的方法,有多种可选的方法,包括但不限于:
CV_TM_SQDIFF: 平方差匹配法
CV_TM_SQDIFF_NORMED: 归一化的平方差匹配法
CV_TM_CCORR: 互相关匹配法
CV_TM_CCORR_NORMED: 归一化的互相关匹配法
CV_TM_CCOEFF: 交叉系数匹配法
CV_TM_CCOEFF_NORMED: 归一化的交叉系数匹配法

函数作用:
这个函数通过遍历输入图像中的每一个可能的位置,将模板图像与该位置上的图像区域进行比较,计算出一个相似度值。最终,所有的相似度值会被存储在一个矩阵中,这个矩阵就是 result 参数。在不同的匹配方法下,这个矩阵的值有不同的意义。
例如,对于归一化的交叉系数匹配法 (CV_TM_CCOEFF_NORMED),匹配得分接近于 1 表示非常好的匹配;而对于平方差匹配法 (CV_TM_SQDIFF),得分接近于 0 表示很好的匹配。

使用示例: 如果你想找到一个模板图像在另一张大图像中的位置,你可以使用 matchTemplate 函数并随后分析 result 矩阵来确定最佳匹配位置。对于某些匹配方法,你需要找到矩阵中的最大值;而对于其他方法,则需要找到最小值。
cpp 复制代码
void minMaxLoc(InputArray src, double* minVal, double* maxVal=0, Point* minLoc=0, Point* maxLoc=0, InputArray mask=noArray());
void minMaxLoc(const SparseMat& src, double* minVal, double* maxVal, int* minIdx=0, int* maxIdx=0);
minMaxLoc 是 OpenCV 库中的一个函数,用于查找数组中的全局最小值和最大值,同时也可以找出这些值的位置。此函数适用于多种类型的数组,包括稠密数组和稀疏数组。

对于稠密数组(如 Mat 或 Umat):
void minMaxLoc(
    InputArray src,       // 输入数组
    double* minVal,       // 输出指针,指向最小值
    double* maxVal = 0,   // 输出指针,指向最大值(可选)
    Point* minLoc = 0,    // 输出指针,指向最小值的位置(可选)
    Point* maxLoc = 0,    // 输出指针,指向最大值的位置(可选)
    InputArray mask = noArray() // 可选的掩码数组,用于指定要处理的像素子集
);


对于稀疏数组(如 SparseMat):
void minMaxLoc(
    const SparseMat& src, // 输入稀疏数组
    double* minVal,       // 输出指针,指向最小值
    double* maxVal,       // 输出指针,指向最大值
    int* minIdx = 0,      // 输出指针,指向最小值的索引(可选)
    int* maxIdx = 0       // 输出指针,指向最大值的索引(可选)
);


参数说明:
src: 输入的数组,可以是多通道的数组。如果是多通道的数组,函数会分别在每个通道上查找最小值和最大值。
minVal: 输出指针,指向最小值。如果不需要这个值,可以传入 nullptr。
maxVal: 输出指针,指向最大值。如果不需要这个值,可以传入 nullptr。
minLoc: 输出指针,指向最小值的位置。对于多通道数组,返回的是通道索引和像素坐标。如果不需要这个位置信息,可以传入 nullptr。
maxLoc: 输出指针,指向最大值的位置。对于多通道数组,返回的是通道索引和像素坐标。如果不需要这个位置信息,可以传入 nullptr。
mask: 可选的掩码数组,用于指定要处理的像素子集。掩码数组应该是单通道的 8 位无符号整型数组。非零值表示对应的像素应该被处理,零值则表示对应的像素被忽略。
cpp 复制代码
rectangle 函数是 OpenCV 库中的一个函数,用于在图像上绘制矩形。这个函数有两种重载形式,一种接受两个顶点来定义矩形的对角线,另一种接受一个 Rect 对象来定义矩形。下面是这两个函数的中文含义及参数说明:

void rectangle(Mat& img, Point pt1, Point pt2, const Scalar& color, int thickness=1, int lineType=8, int shift=0);
void rectangle(Mat& img, Rect r, const Scalar& color, int thickness=1, int lineType=8, int shift=0);


对于使用两个顶点定义矩形的情况:
void rectangle(
    Mat& img,       // 要绘制矩形的图像
    Point pt1,      // 矩形左上角的点
    Point pt2,      // 矩形右下角的点
    const Scalar& color, // 矩形的颜色
    int thickness = 1,   // 线条的厚度,如果为负值,则填充矩形
    int lineType = 8,    // 线条类型,通常为 8 表示 8 连续性
    int shift = 0        // 坐标轴的位移量
);
对于使用 Rect 定义矩形的情况:
void rectangle(
    Mat& img,       // 要绘制矩形的图像
    Rect r,         // 矩形区域
    const Scalar& color, // 矩形的颜色
    int thickness = 1,   // 线条的厚度,如果为负值,则填充矩形
    int lineType = 8,    // 线条类型,通常为 8 表示 8 连续性
    int shift = 0        // 坐标轴的位移量
);

参数说明:
img: 输入/输出图像,矩形将在其上绘制。
pt1: 矩形左上角的坐标。
pt2: 矩形右下角的坐标。
r: 代表矩形的 Rect 对象。
color: 矩形的颜色,由 Scalar 类型定义。例如 Scalar(0, 0, 255) 表示红色。
thickness: 线条的厚度,单位为像素。默认值为 1。如果设置为负数,例如 -1,则矩形会被填充。
lineType: 线条类型,默认为 8,意味着使用 8 邻域的抗锯齿线条。其他可能的值有 LINE_4, LINE_8, LINE_AA。
shift: 坐标轴的位移量。通常情况下,设置为 0 即可。
cpp 复制代码
//minMaxLoc 函数举例

#include <opencv2/opencv.hpp>
#include <iostream>

int main()
{
	cv::Mat image = cv::imread("10.jpg", cv::IMREAD_GRAYSCALE);

	if (image.empty())
	{
		std::cout << "Could not open or find the image" << std::endl;
		return -1;
	}

	double minVal, maxVal;
	cv::Point minLoc, maxLoc;

	cv::minMaxLoc(image, &minVal, &maxVal, &minLoc, &maxLoc);

	std::cout << "Minimum value: " << minVal << " at (" << minLoc.x << ", " << minLoc.y << ")" << std::endl;
	std::cout << "Maximum value: " << maxVal << " at (" << maxLoc.x << ", " << maxLoc.y << ")" << std::endl;

	system("pause");
	
	return 0;
}

原图

截取模板

代码

cpp 复制代码
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>

using namespace std;
using namespace cv;

int main()
{
	Mat srcImage = imread("10.jpg", IMREAD_COLOR);//读取源图像
	Mat templateImage = imread("10_0.jpg", IMREAD_COLOR);//读模板图像

	if (srcImage.empty() || templateImage.empty())
	{
		cout << "读入的图片有空资源!" << endl;
	}
	//转化为灰度图、以减少计算复杂度
	Mat graySrc, grayTemplate;
	cvtColor(srcImage, graySrc, COLOR_BGR2GRAY);
	cvtColor(templateImage, grayTemplate, COLOR_BGR2GRAY);

	//执行模板匹配
	Mat result;
	matchTemplate(graySrc, grayTemplate, result, TM_CCOEFF_NORMED);

	//设定阈值,找到匹配位置
	double minVal, maxVal;
	Point minLoc, maxLoc;
	minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc);

	//如果匹配得分足够高,则在原图上标出匹配区域
	int width = templateImage.cols;
	int height = templateImage.rows;
	if (maxVal > 0.8)//设置一个阈值,根据实际情况调整
	{
		rectangle(srcImage, maxLoc, Point(maxLoc.x + width, maxLoc.y + height), Scalar(0, 0, 255), 2);
	}
	//显示结果
	
	imshow("源图像", srcImage);
	imshow("模板图像", templateImage);

	waitKey(0);

	return 0;
}

运行结果

相关推荐
只怕自己不够好2 分钟前
OpenCV 图像运算全解析:加法、位运算(与、异或)在图像处理中的奇妙应用
图像处理·人工智能·opencv
华清远见IT开放实验室2 小时前
【每天学点AI】实战图像增强技术在人工智能图像处理中的应用
图像处理·人工智能·python·opencv·计算机视觉
只怕自己不够好2 小时前
《OpenCV 图像缩放、翻转与变换全攻略:从基础操作到高级应用实战》
人工智能·opencv·计算机视觉
安静读书8 小时前
Python解析视频FPS(帧率)、分辨率信息
python·opencv·音视频
小陈phd8 小时前
OpenCV从入门到精通实战(九)——基于dlib的疲劳监测 ear计算
人工智能·opencv·计算机视觉
如若12313 小时前
主要用于图像的颜色提取、替换以及区域修改
人工智能·opencv·计算机视觉
lsjweiyi16 小时前
极简AI工具箱网站开源啦!
opencv·开源·微信支付·支付宝支付·百度ai·极简ai工具箱·ai图像处理
Jack黄从零学c++19 小时前
opencv(c++)---自带的卷积运算filter2D以及应用
c++·人工智能·opencv
饭碗、碗碗香1 天前
OpenCV笔记:图像去噪对比
人工智能·笔记·opencv·计算机视觉
是Dream呀2 天前
Python从0到100(七十三):Python OpenCV-OpenCV实现手势虚拟拖拽
开发语言·python·opencv