OpenCvSharp是OpenCV库的C#封装,提供了丰富的图像处理功能。模板匹配是一种在大图像中查找小模板图像位置的技术。在这篇文章中,我们将介绍如何使用OpenCvSharp进行模板匹配,并考虑目标尺寸大小的匹配。
以下是实现模板匹配的详细步骤:
你可以通过NuGet包管理器来安装OpenCvSharp。运行以下命令:
BashInstall-Package OpenCvSharp4 Install-Package OpenCvSharp4.runtime.win
目标图
模板
首先,我们需要加载包含目标图像和模板图像的文件。
C#using OpenCvSharp;
namespace App1
{
internal class Program
{
static void Main(string[] args)
{
// 读取待搜索的大图和模板小图
Mat targetImage = Cv2.ImRead("pcb_layout.png", ImreadModes.Color);
Mat templateImage = Cv2.ImRead("template.png", ImreadModes.Color);
// 确保图片正确加载
if (targetImage.Empty() || templateImage.Empty())
{
Console.WriteLine("图像加载失败!");
return;
}
// 运行模板匹配
Mat result = new Mat();
Cv2.MatchTemplate(targetImage, templateImage, result, TemplateMatchModes.CCoeffNormed);
// 设定匹配结果的阈值
double threshold = 0.8;
// 找到所有匹配度高于阈值的匹配结果
List<Rect> matches = new List<Rect>();
for (int y = 0; y < result.Rows; y++)
{
for (int x = 0; x < result.Cols; x++)
{
if (result.At<float>(y, x) >= threshold)
{
Rect matchRect = new Rect(new Point(x, y), new Size(templateImage.Width, templateImage.Height));
matches.Add(matchRect);
}
}
}
// 计算匹配结果的尺寸并筛选有效匹配
List<Rect> validMatches = new List<Rect>();
foreach (var matchRect in matches)
{
double matchWidth = matchRect.Width;
double matchHeight = matchRect.Height;
double templateWidth = templateImage.Width;
double templateHeight = templateImage.Height;
double widthRatio = matchWidth / templateWidth;
double heightRatio = matchHeight / templateHeight;
bool isAcceptableMatch = widthRatio <= 1.2 && widthRatio >= 0.8 && heightRatio <= 1.2 && heightRatio >= 0.8;
if (isAcceptableMatch)
{
validMatches.Add(matchRect);
}
}
// 去除相互重叠的匹配结果
List<Rect> nonOverlappingMatches = FilterOverlappingMatches(validMatches);
// 在目标图像上绘制矩形框以标注匹配区域
foreach (var match in nonOverlappingMatches)
{
Cv2.Rectangle(targetImage, match, Scalar.Red, 2);
}
Console.WriteLine($"{nonOverlappingMatches.Count} 个匹配找到!");
Cv2.ImShow("Matched Image", targetImage);
Cv2.WaitKey(0);
}
// 函数用于去除重叠的匹配结果
static List<Rect> FilterOverlappingMatches(List<Rect> matches, double minOverlapRatio = 0.5)
{
List<Rect> filteredMatches = new List<Rect>();
foreach (var match in matches)
{
bool overlap = false;
foreach (var filteredMatch in filteredMatches)
{
Rect intersection = match & filteredMatch;
double intersectionArea = intersection.Width * intersection.Height;
double matchArea = match.Width * match.Height;
double filteredMatchArea = filteredMatch.Width * filteredMatch.Height;
double overlapRatio = intersectionArea / Math.Min(matchArea, filteredMatchArea);
if (overlapRatio > minOverlapRatio)
{
overlap = true;
break;
}
}
if (!overlap)
{
filteredMatches.Add(match);
}
}
return filteredMatches;
}
}
}
计算匹配结果尺寸并筛选有效的匹配。这里比较的是匹配区域与模板区域的宽高比,确保在接受的范围内(0.8到1.2之间)。
本文作者:技术老小子
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!