基于形状的模板匹配之十字识别:C++与C#实现
·
基于形状的模板匹配,十字识别,C++/C#

在计算机视觉领域,基于形状的模板匹配是一项非常实用的技术,它可以帮助我们在复杂图像中精准定位特定形状的目标。今天咱们就来聊聊如何实现十字形状的识别,并且分别用C++和C#来实现。
C++ 实现
首先来看C++,OpenCV库为我们提供了强大的图像处理功能,在模板匹配这块也是相当给力。
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main(int argc, char** argv) {
// 读取模板图像(十字形状)
Mat templateImage = imread("cross_template.png", IMREAD_GRAYSCALE);
if (templateImage.empty()) {
cout << "Could not open or find the template image" << endl;
return -1;
}
// 读取待匹配的图像
Mat inputImage = imread("input_image.png", IMREAD_GRAYSCALE);
if (inputImage.empty()) {
cout << "Could not open or find the input image" << endl;
return -1;
}
// 定义结果矩阵
Mat result;
int result_cols = inputImage.cols - templateImage.cols + 1;
int result_rows = inputImage.rows - templateImage.rows + 1;
result.create(result_rows, result_cols, CV_32FC1);
// 进行模板匹配,这里使用平方差匹配方法
matchTemplate(inputImage, templateImage, result, TM_SQDIFF_NORMED);
// 归一化结果便于显示
normalize(result, result, 0, 1, NORM_MINMAX, -1, Mat());
// 寻找最佳匹配位置
double minVal; double maxVal; Point minLoc; Point maxLoc;
minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc, Mat());
// 对于平方差匹配方法,最小值对应的位置就是最佳匹配位置
Point matchLoc = minLoc;
// 在原图上绘制矩形标记出匹配位置
rectangle(inputImage, matchLoc, Point(matchLoc.x + templateImage.cols, matchLoc.y + templateImage.rows), Scalar(0, 255, 0), 2, 8, 0);
// 显示结果
imshow("Result", inputImage);
waitKey(0);
return 0;
}
C++ 代码分析
- 图像读取:
-imread函数分别读取模板图像(十字形状)和待匹配的图像。这里设置读取为灰度图像,因为在模板匹配中,灰度图像往往能满足需求且计算量更小。如果图像读取失败,程序会输出错误信息并退出。 - 结果矩阵创建:
- 根据模板图像和输入图像的大小计算结果矩阵的大小。结果矩阵的每个元素表示模板在对应位置的匹配程度。 - 模板匹配:
- 使用matchTemplate函数进行匹配,这里选用TMSQDIFFNORMED方法,它通过计算模板与图像块之间的平方差归一化来衡量匹配程度,值越小表示匹配越好。 - 寻找最佳匹配位置:
-minMaxLoc函数用于找到结果矩阵中的最小值和最大值及其位置。对于平方差匹配方法,最小值对应的位置就是最佳匹配位置。 - 标记与显示:
- 使用rectangle函数在输入图像上标记出匹配的位置,最后通过imshow显示结果。
C# 实现
接下来看看C#,Emgu CV库可以让我们在C#中轻松实现图像处理功能。
using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
using Emgu.CV.Util;
using System;
using System.Drawing;
class CrossTemplateMatching
{
static void Main()
{
// 读取模板图像(十字形状)
Image<Gray, byte> templateImage = new Image<Gray, byte>("cross_template.png");
if (templateImage == null)
{
Console.WriteLine("Could not open or find the template image");
return;
}
// 读取待匹配的图像
Image<Gray, byte> inputImage = new Image<Gray, byte>("input_image.png");
if (inputImage == null)
{
Console.WriteLine("Could not open or find the input image");
return;
}
// 进行模板匹配,这里使用平方差匹配方法
Image<Gray, float> result = inputImage.MatchTemplate(templateImage, TemplateMatchingType.CcoeffNormed);
// 寻找最佳匹配位置
double[] minValues;
double[] maxValues;
Point[] minLocations;
Point[] maxLocations;
result.MinMax(out minValues, out maxValues, out minLocations, out maxLocations);
// 对于平方差匹配方法,最小值对应的位置就是最佳匹配位置
Point matchLoc = maxLocations[0];
// 在原图上绘制矩形标记出匹配位置
inputImage.Draw(new Rectangle(matchLoc, templateImage.Size), new Gray(255), 2);
// 显示结果
CvInvoke.Imshow("Result", inputImage);
CvInvoke.WaitKey(0);
}
}
C# 代码分析
- 图像读取:
- 使用Emgu CV的Image类型读取模板图像和输入图像。同样,如果图像读取失败,程序会输出错误信息并退出。 - 模板匹配:
-MatchTemplate函数进行模板匹配,这里选用TemplateMatchingType.CcoeffNormed方法,它基于归一化互相关系数来衡量匹配程度,值越大表示匹配越好(注意与C++中平方差匹配方法的区别)。 - 寻找最佳匹配位置:
-MinMax函数找到结果图像中的最小值和最大值及其位置。由于使用的匹配方法不同,这里取最大值对应的位置作为最佳匹配位置。 - 标记与显示:
- 使用Draw函数在输入图像上绘制矩形标记匹配位置,最后通过CvInvoke.Imshow显示结果。
通过上面两种语言的实现,我们可以看到虽然语法和使用的库有所不同,但基于形状的模板匹配实现十字识别的核心思路是相似的。希望这篇文章能帮助你在计算机视觉的形状匹配领域有所收获!






更多推荐

所有评论(0)