IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 人工智能 -> OpenCV C++案例实战二十四《多目标匹配》 -> 正文阅读

[人工智能]OpenCV C++案例实战二十四《多目标匹配》


前言

本案例要实现的功能是使用OpenCV中的matchTemplate实现多目标匹配。熟悉matchTemplate这个API的小伙伴都知道,仅仅单一使用matchTemplate的话只能实现单一目标匹配,而不能实现多目标匹配。那么接下来我们就一起看看如何使用matchTemplate实现多目标匹配吧。

一、图像预处理

首先加载测试图像与模板图像,如下图所示:
测试图像:
请添加图片描述
模板图像:
请添加图片描述
我们的最终目的是在测试图像中找到所有模板图像的物体,并把它框出来。

首先将图像灰度化、去噪

	Mat src_gray, src_gaussian;
	cvtColor(src, src_gray, COLOR_BGR2GRAY);
	GaussianBlur(src_gray, src_gaussian, Size(3, 3), 0);

	Mat temp_gray, temp_gaussian;
	cvtColor(temp, temp_gray, COLOR_BGR2GRAY);
	GaussianBlur(temp_gray, temp_gaussian, Size(3, 3), 0);

然后调用matchTemplate进行模板匹配,matchTemplate提供六种计算图像相似度的方法。
1、差值平方和匹配 CV_TM_SQDIFF —匹配结果越好,值越小(0)
2、标准化差值平方和匹配 CV_TM_SQDIFF_NORMED
3、相关匹配 CV_TM_CCORR —匹配结果越好,值越大;0表示匹配结果最差
4、标准相关匹配 CV_TM_CCORR_NORMED
5、相关匹配 CV_TM_CCOEFF —1:表示完全相同;0:表示完全不相同
6、标准相关匹配 CV_TM_CCOEFF_NORMED

在这里我使用的是标准相关匹配,结果如下面所示。

	Mat result;
	matchTemplate(src_gaussian, temp_gaussian, result, TM_CCOEFF_NORMED);
	normalize(result, result, 0, 1, NORM_MINMAX);

如下图所示:即为我们使用matchTemplate及归一化得到的结果
在这里插入图片描述
使用minMaxLoc找到最大最小值,以及它们所在坐标。

	double minVal, maxVal;
	Point minLoc, maxLoc;
	minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc);

二、单目标匹配

	//单目标匹配
	rectangle(src, Rect(maxLoc.x, maxLoc.y, temp.cols, temp.rows), Scalar(0, 0, 255), 5);

请添加图片描述
如图为单目标匹配结果,接下来看看多目标匹配是如何实现的。

三、多目标匹配

我们之前使用matchTemplate得到归一化之后的结果,我们需要的是使用3*3邻域非极大值抑制找到result中所有邻域最大值。

	//多目标匹配
	double quality = 0.88;  //匹配质量(0~1),越接近1,匹配程度越高
	if (quality <= 0.0)quality = 0.0;
	if (quality >= 1.0)quality = 1.0;
	double thresh = maxVal * quality;//像素阈值
	for (int i = 0; i < result.rows; i++)
	{
		for (int j = 0; j < result.cols; j++)
		{
			double val = result.at<float>(i, j);//灰度值

			//3*3邻域非极大值抑制
			if (val > thresh)
			{
				//当前像素的灰度值大于阈值且该像素是其3*3邻域最大值时,判定其为目标
				if (result.at<float>(i - 1, j - 1) < val &&
					result.at<float>(i - 1, j) < val &&
					result.at<float>(i - 1, j + 1) < val &&
					result.at<float>(i, j - 1) < val &&
					result.at<float>(i, j + 1) < val &&
					result.at<float>(i + 1, j - 1) < val &&
					result.at<float>(i + 1, j) < val &&
					result.at<float>(i + 1, j + 1) < val)
				{
					//结果绘制
					rectangle(src, Rect(j, i, temp.cols, temp.rows), Scalar(0, 255, 0), 2);

					char text[10];
					float score = result.at<float>(i, j);
					sprintf_s(text, "%.2f",score);
					putText(src, text, Point(j, i), FONT_HERSHEY_SIMPLEX, 0.8, Scalar(0, 0, 255), 2);
				}
			}
		}
	}

1、 效果显示

请添加图片描述
如图,我们可以看到大部分的目标都找到了。我们可以通过控制quality 匹配质量来控制我们最终的匹配精度,quality 越大,匹配程度越高。

四、结果显示

在这里我做了点骚操作,将模板图像与测试图像放在一张新图像上。直接上代码

	//效果绘制--可忽略
	//设置新画布,可容纳原图跟模板图像
	Mat canvas(Size(src.cols + temp.cols + 200, src.rows), CV_8UC3, Scalar::all(255));
	src.copyTo(canvas(Rect(0, 0, src.cols, src.rows)));
	//将模板图像放置在画布上
	//tempname.substr(0, tempname.find("."))--为文件名
	rectangle(canvas, Rect(src.cols +40 , 50, 200, 80), Scalar(0,255,0), -1);
	putText(canvas, tempname.substr(0, tempname.find(".")), Point(src.cols + 100 , 100), FONT_HERSHEY_SIMPLEX, 1.3, Scalar(0,0,255), 3);
	temp.copyTo(canvas(Rect(src.cols + 100, 150, temp.cols, temp.rows)));
	namedWindow("Demo", WINDOW_NORMAL);
	imshow("Demo", canvas);

1、 效果显示

请添加图片描述
请添加图片描述

五、源码

#include<iostream>
#include<opencv2/opencv.hpp>
using namespace std;
using namespace cv;


int main()
{
	Mat src = imread("test.jpg");
	string tempname = "fox.jpg";
	Mat temp = imread(tempname);
	if (src.empty() || temp.empty())
	{
		cout << "No Image..." << endl;
		system("pause");
		return -1;
	}

	Mat src_gray, src_gaussian;
	cvtColor(src, src_gray, COLOR_BGR2GRAY);
	GaussianBlur(src_gray, src_gaussian, Size(3, 3), 0);

	Mat temp_gray, temp_gaussian;
	cvtColor(temp, temp_gray, COLOR_BGR2GRAY);
	GaussianBlur(temp_gray, temp_gaussian, Size(3, 3), 0);

	Mat result;
	matchTemplate(src_gaussian, temp_gaussian, result, TM_CCOEFF_NORMED);
	normalize(result, result, 0, 1, NORM_MINMAX);


	double minVal, maxVal;
	Point minLoc, maxLoc;
	minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc);
	
	//单目标匹配
	//rectangle(src, Rect(maxLoc.x, maxLoc.y, temp.cols, temp.rows), Scalar(0, 0, 255), 5);


	//多目标匹配
	double quality = 0.88;  //匹配质量(0~1),越接近1,匹配程度越高
	if (quality <= 0.0)quality = 0.0;
	if (quality >= 1.0)quality = 1.0;
	double thresh = maxVal * quality;//像素阈值
	for (int i = 0; i < result.rows; i++)
	{
		for (int j = 0; j < result.cols; j++)
		{
			double val = result.at<float>(i, j);//灰度值

			//3*3邻域非极大值抑制
			if (val > thresh)
			{
				//当前像素的灰度值大于阈值且该像素是其3*3邻域最大值时,判定其为目标
				if (result.at<float>(i - 1, j - 1) < val &&
					result.at<float>(i - 1, j) < val &&
					result.at<float>(i - 1, j + 1) < val &&
					result.at<float>(i, j - 1) < val &&
					result.at<float>(i, j + 1) < val &&
					result.at<float>(i + 1, j - 1) < val &&
					result.at<float>(i + 1, j) < val &&
					result.at<float>(i + 1, j + 1) < val)
				{
					//结果绘制
					rectangle(src, Rect(j, i, temp.cols, temp.rows), Scalar(0, 255, 0), 2);

					char text[10];
					float score = result.at<float>(i, j);
					sprintf_s(text, "%.2f",score);
					putText(src, text, Point(j, i), FONT_HERSHEY_SIMPLEX, 0.8, Scalar(0, 0, 255), 2);
				}
			}
		}
	}

	//效果绘制--可忽略
	//设置新画布,可容纳原图跟模板图像
	Mat canvas(Size(src.cols + temp.cols + 200, src.rows), CV_8UC3, Scalar::all(255));
	src.copyTo(canvas(Rect(0, 0, src.cols, src.rows)));
	//将模板图像放置在画布上
	//tempname.substr(0, tempname.find("."))--为文件名
	rectangle(canvas, Rect(src.cols +40 , 50, 200, 80), Scalar(0,255,0), -1);
	putText(canvas, tempname.substr(0, tempname.find(".")), Point(src.cols + 100 , 100), FONT_HERSHEY_SIMPLEX, 1.3, Scalar(0,0,255), 3);
	temp.copyTo(canvas(Rect(src.cols + 100, 150, temp.cols, temp.rows)));
	namedWindow("Demo", WINDOW_NORMAL);
	imshow("Demo", canvas);
	waitKey(0);
	system("pause");
	return false;
}

总结

本文使用OpenCV C++多目标匹配,主要操作有以下几点。
1、图像预处理
2、matchTemplate模板匹配以及图像归一化
3、minMaxLoc计算图像最大最小值
4、3*3非极大值抑制寻找邻域最大值,极为目标

  人工智能 最新文章
2022吴恩达机器学习课程——第二课(神经网
第十五章 规则学习
FixMatch: Simplifying Semi-Supervised Le
数据挖掘Java——Kmeans算法的实现
大脑皮层的分割方法
【翻译】GPT-3是如何工作的
论文笔记:TEACHTEXT: CrossModal Generaliz
python从零学(六)
详解Python 3.x 导入(import)
【答读者问27】backtrader不支持最新版本的
上一篇文章      下一篇文章      查看所有文章
加:2022-06-08 19:03:35  更:2022-06-08 19:04:22 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 2:51:00-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码