基于C++与OpenCV的多模板多目标形状匹配探索
c++ opencv开发的基于形状(轮廓)多模板多目标的模板匹配源码,可实现定位,计数,分类等等,定位精度可达亚像素级别,运行速度采用并行加速。开发工具:qt(msvc2015) + opencv6在计算机视觉领域,基于形状(轮廓)的多模板多目标模板匹配是一项十分实用的技术,它不仅能实现目标的定位、计数,还能进行分类,今天就跟大家分享下这方面的开发实战,开发工具选用了qt(msvc2015) 以及
c++ opencv开发的基于形状(轮廓)多模板多目标的模板匹配源码,可实现定位,计数,分类等等,定位精度可达亚像素级别,运行速度采用并行加速。 开发工具:qt(msvc2015) + opencv6

在计算机视觉领域,基于形状(轮廓)的多模板多目标模板匹配是一项十分实用的技术,它不仅能实现目标的定位、计数,还能进行分类,今天就跟大家分享下这方面的开发实战,开发工具选用了qt(msvc2015) 以及opencv6。
环境搭建
首先,确保你已经安装好Qt并配置了MSVC2015编译器,同时OpenCV6也正确安装并配置好了环境变量。在Qt项目的.pro文件中,添加如下代码引入OpenCV库:
INCLUDEPATH += C:/opencv6/build/include
LIBS += -LC:/opencv6/build/x64/vc14/lib \
-lopencv_world600d
这里假设你的OpenCV安装路径是C:/opencv6,实际情况请根据自己的安装路径调整。
定位、计数与分类的实现
轮廓检测
我们先从图像中提取目标的轮廓,以下是关键代码:
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main(int argc, char** argv) {
Mat src = imread("your_image.jpg");
if (src.empty()) {
cout << "Could not open or find the image" << endl;
return -1;
}
Mat gray;
cvtColor(src, gray, COLOR_BGR2GRAY);
Mat blurred;
GaussianBlur(gray, blurred, Size(5, 5), 0);
Mat edges;
Canny(blurred, edges, 50, 150);
vector<vector<Point>> contours;
findContours(edges, contours, RETR_TREE, CHAIN_APPROX_SIMPLE);
这段代码中,首先读取图像,将其转为灰度图,然后进行高斯模糊平滑处理,接着使用Canny边缘检测算法获取图像边缘,最后通过findContours函数找到所有轮廓。
模板匹配
接下来,实现基于轮廓的模板匹配,以实现定位功能。我们采用matchShapes函数来比较模板轮廓与图像中的轮廓相似度:
Mat templateImage = imread("template.jpg", IMREAD_GRAYSCALE);
if (templateImage.empty()) {
cout << "Could not open or find the template image" << endl;
return -1;
}
Mat templateEdges;
Canny(templateImage, templateEdges, 50, 150);
vector<vector<Point>> templateContours;
findContours(templateEdges, templateContours, RETR_TREE, CHAIN_APPROX_SIMPLE);
vector<vector<Point>> foundContours;
for (size_t i = 0; i < contours.size(); i++) {
double matchValue = matchShapes(templateContours[0], contours[i], CONTOURS_MATCH_I1, 0.0);
if (matchValue < 0.1) {
foundContours.push_back(contours[i]);
}
}
这里先读取模板图像并处理,然后遍历所有找到的轮廓,通过matchShapes函数计算相似度,当相似度小于某个阈值(这里设为0.1)时,认为找到了匹配的目标。
计数与分类
对于计数,我们可以简单统计找到的匹配轮廓数量:
cout << "Number of found objects: " << foundContours.size() << endl;
而分类则需要更多的模板以及更复杂的匹配逻辑,例如我们可以为不同类别的目标准备不同的模板,在匹配时分别计算相似度,根据相似度最高的模板来确定类别:
// 假设我们有多个模板
Mat template1 = imread("template1.jpg", IMREAD_GRAYSCALE);
Mat template2 = imread("template2.jpg", IMREAD_GRAYSCALE);
// 处理模板
//...
// 遍历轮廓进行分类
for (size_t i = 0; i < contours.size(); i++) {
double matchValue1 = matchShapes(templateContours1[0], contours[i], CONTOURS_MATCH_I1, 0.0);
double matchValue2 = matchShapes(templateContours2[0], contours[i], CONTOURS_MATCH_I1, 0.0);
if (matchValue1 < matchValue2 && matchValue1 < 0.1) {
cout << "Object at index " << i << " belongs to class 1" << endl;
} else if (matchValue2 < matchValue1 && matchValue2 < 0.1) {
cout << "Object at index " << i << " belongs to class 2" << endl;
}
}
亚像素级定位精度提升
为了达到亚像素级定位精度,可以在轮廓检测后使用approxPolyDP函数对轮廓进行多边形逼近,然后利用轮廓的矩来计算更精确的位置:
vector<Point2f> center(foundContours.size());
vector<float> radius(foundContours.size());
for (size_t i = 0; i < foundContours.size(); i++) {
Mat contourMat = Mat(foundContours[i]);
Point2f c;
float r;
minEnclosingCircle(contourMat, c, r);
center[i] = c;
radius[i] = r;
}
这里通过minEnclosingCircle函数获取轮廓的最小外接圆,圆心位置就是目标的更精确位置。
并行加速提升运行速度
OpenCV提供了并行处理的能力,可以加快计算速度。例如在轮廓检测部分,可以这样并行化:
parallel_for_(Range(0, contours.size()), [&](const Range& range) {
for (int i = range.start; i < range.end; i++) {
double matchValue = matchShapes(templateContours[0], contours[i], CONTOURS_MATCH_I1, 0.0);
if (matchValue < 0.1) {
foundContours.push_back(contours[i]);
}
}
});
这里使用parallelfor函数并行遍历轮廓,对每个轮廓进行模板匹配,大大提升了匹配速度。

c++ opencv开发的基于形状(轮廓)多模板多目标的模板匹配源码,可实现定位,计数,分类等等,定位精度可达亚像素级别,运行速度采用并行加速。 开发工具:qt(msvc2015) + opencv6

通过以上步骤,我们就实现了基于C++与OpenCV的形状多模板多目标的模板匹配,能够高效地进行定位、计数与分类,并且达到亚像素级精度以及快速的运行速度。希望这篇博文对大家在计算机视觉开发上有所帮助。

更多推荐
所有评论(0)