C#+OpenCV基础(十八)_模版匹配
1.C#+OpenCV学习笔记(目录)-目录2.C#+OpenCV基础(一)_加载创建复制保存图片3.C#+OpenCV基础(二)_灰度化二值化4.C#+OpenCV基础(三)_修改高宽剪切拼接缩放5.C#+OpenCV基础(四)_旋转翻转透视6.C#+OpenCV基础(五)_添加边框7.C#+OpenCV基础(六)_均值中值高斯双边滤波8.C#+OpenCV基础(七)_图像金字塔9.C#+OpenCV基础(八)_获取修改图片亮度10.C#+OpenCV基础(九)_拆分合并图层11.C#+OpenCV基础(十)_灰度变化与直方图12.C#+OpenCV基础(十一)_图片基础计算13.C#+OpenCV基础(十二)_图片形态学计算14.C#+OpenCV基础(十三)_图片白平衡矫正15.C#+OpenCV基础(十四)_绘制像素、图形、文字16.C#+OpenCV基础(十五)_图像的基础分割方法17.C#+OpenCV基础(十六)_识别圆、直线、斑点、轮廓18.C#+OpenCV基础(十七)_计算图片相似度
19.C#+OpenCV基础(十八)_模版匹配
20.C#+OpenCV进阶(一)_人体识别21.C#+OpenCV进阶(二)_文字识别22.C#+OpenCV进阶(三)_操作摄像头与视频文件23.C#+OpenCV进阶(四)_录屏24.C#+OpenCV实战(一)_图片简易角度矫正25.C#+OpenCV实战(二)_春天转秋天26.C#+OpenCV实战(三)_玉米粒计数27.C#+OpenCV实战(四)_特定钢板缺陷检测- MatchTemplate匹配图片:用于匹配光照角度未变化的图片。
- SIFT特征点匹配图片:尺度不变特征变换(Scale-invariant feature transform,SIFT)。用于匹配光照角度未变化的图片,可在图像中检测出关键点,是一种局部特征描述子。
- SURF特征点匹配图片:SURF算法速度是SIFT的3倍,SURF善于处理具有模糊和旋转的图像,但是不善于处理视角变化和光照变化,是一种局部特征描述子。其对匹配旋转、尺度缩放、亮度变化保持不变性,对视角变化、仿射变换、噪声保持一定程度的匹配稳定性。
1、MatchTemplate匹配图片
/// <summary>
/// 匹配图片(Cv2.MatchTemplate)
/// </summary>
/// <param name="matSrc">图片</param>
/// <param name="matTo">特征图片</param>
/// <param name="outMat">结果图片</param>
/// <param name="threshold">相似度</param>
/// <returns></returns>
public static List<Rect> ImageDetector_MatchTemplate(Mat matSrc, Mat matTo, out Mat outMat, double threshold = 0.81)
{
List<Rect> rects = new List<Rect>();
outMat = new Mat();
matSrc.CopyTo(outMat);
Mat resultMat = new Mat();
// 模版匹配
Cv2.MatchTemplate(matSrc, matTo, resultMat, TemplateMatchModes.CCoeffNormed);
while (true)
{
Cv2.MinMaxLoc(resultMat, out double minVal, out double maxVal, out Point minLoc, out Point maxLoc);
if (maxVal < threshold) // 如果最大值小于阈值则退出
break;
// 绘制图像
Rect rect = new Rect(maxLoc.X, maxLoc.Y, matTo.Width, matTo.Height);
Cv2.Rectangle(outMat, rect, Scalar.Red, 1);
rects.Add(rect);
// 将匹配位置重置为0,以便匹配下一个最大值
Cv2.FloodFill(resultMat, maxLoc, Scalar.Black);
}
return rects;
}
2、SIFT特征点匹配图片
/// <summary>
/// 匹配图片(SIFT特征点)
/// </summary>
/// <param name="mat">源图片</param>
/// <param name="mat">目标图片</param>
/// <param name="resultMat">结果图片</param>
/// <returns>相似特征点集合</returns>
/// <exception cref="Exception"></exception>
public static List<DMatch> ImageDetector_SIFT(Mat matSrc, Mat matTo, out Mat outMat)
{
using (Mat matSrcRet = new Mat()) // 结果图片 -源图片
using (Mat matToRet = new Mat()) // 结果图片 -目标图片
{
KeyPoint[] keyPointsSrc, keyPointsTo; // 源图片与目标图片的‘特征点’
using (var sift = OpenCvSharp.Features2D.SIFT.Create())
{
sift.DetectAndCompute(matSrc, null, out keyPointsSrc, matSrcRet); // 检测和计算‘源图片的特征点’
sift.DetectAndCompute(matTo, null, out keyPointsTo, matToRet); // 检测和计算‘目标图片的特征点’
}
using (var bfMatcher = new BFMatcher())
{
var matches = bfMatcher.KnnMatch(matSrcRet, matToRet, k: 2); // 匹配相似点
// 获取相似特征点
var pointsSrc = new List<Point2f>(); // 源图片的相似特征点
var pointsDst = new List<Point2f>(); // 目标图片的相似特征点
var goodMatches = new List<DMatch>(); // 匹配到的相似特征点
var matches1 = matches.Where(x => x.Length > 1);
foreach (DMatch[] items in matches1)
{
if (items[0].Distance < 0.5 * items[1].Distance)
{
pointsSrc.Add(keyPointsSrc[items[0].QueryIdx].Pt);
pointsDst.Add(keyPointsTo[items[0].TrainIdx].Pt);
goodMatches.Add(items[0]);
Console.WriteLine($"源图片的特征点:{keyPointsSrc[items[0].QueryIdx].Pt.X}, {keyPointsSrc[items[0].QueryIdx].Pt.Y}");
}
}
outMat = new Mat();
// 过滤相似特征点(使用RANSAC算法过滤匹配结果)
var pSrc = pointsSrc.ConvertAll<Point2d>(Point2fToPoint2d);
var pDst = pointsDst.ConvertAll<Point2d>(Point2fToPoint2d);
var outMask = new Mat();
// 如果原始的匹配结果为空, 则跳过过滤步骤
if (pSrc.Count > 0 && pDst.Count > 0)
Cv2.FindHomography(pSrc, pDst, HomographyMethods.Ransac, mask: outMask);
// 如果通过RANSAC处理后的匹配点大于10个,才应用过滤. 否则使用原始的匹配点结果(因为匹配点过少的时候通过RANSAC处理后,可能会得到0个匹配点的结果).
if (outMask.Rows > 10)
{
byte[] maskBytes = new byte[outMask.Rows * outMask.Cols];
outMask.GetArray(out maskBytes);
Cv2.DrawMatches(matSrc, keyPointsSrc, matTo, keyPointsTo, goodMatches, outMat, matchesMask: maskBytes, flags: DrawMatchesFlags.NotDrawSinglePoints);
}
else
Cv2.DrawMatches(matSrc, keyPointsSrc, matTo, keyPointsTo, goodMatches, outMat, flags: DrawMatchesFlags.NotDrawSinglePoints);
return goodMatches;
}
}
}
3、SURF特征点匹配图片
/// <summary>
/// 匹配图片(SURF特征点)
/// </summary>
/// <param name="mat">图片</param>
/// <param name="resultMat">结果图片</param>
/// <returns>车牌号</returns>
/// <exception cref="Exception"></exception>
public static List<DMatch> ImageDetector_SURF(Mat matSrc, Mat matTo, out Mat outMat, double threshold = 400)
{
using (Mat matSrcRet = new Mat()) // 结果图片 -源图片
using (Mat matToRet = new Mat()) // 结果图片 -目标图片
{
KeyPoint[] keyPointsSrc, keyPointsTo; // 源图片与目标图片的‘特征点’
using (var surf = OpenCvSharp.XFeatures2D.SURF.Create(threshold, 4, 3, true, true))
{
surf.DetectAndCompute(matSrc, null, out keyPointsSrc, matSrcRet); // 检测和计算‘源图片的特征点’
surf.DetectAndCompute(matTo, null, out keyPointsTo, matToRet); // 检测和计算‘目标图片的特征点’
}
using (var flnMatcher = new OpenCvSharp.FlannBasedMatcher())
{
var matches = flnMatcher.Match(matSrcRet, matToRet); // 匹配相似点
// 求最小最大距离
double minDistance = 1000;//反向逼近
double maxDistance = 0;
for (int i = 0; i < matSrcRet.Rows; i++)
{
double distance = matches[i].Distance;
if (distance > maxDistance)
{
maxDistance = distance;
}
if (distance < minDistance)
{
minDistance = distance;
}
}
Console.WriteLine($"最大相似度: {maxDistance}");
Console.WriteLine($"最小相似度: {minDistance}");
// 获取相似特征点
var pointsSrc = new List<Point2f>(); // 源图片的相似特征点
var pointsDst = new List<Point2f>(); // 目标图片的相似特征点
var goodMatches = new List<DMatch>(); // 匹配到的相似特征点
for (int i = 0; i < matSrcRet.Rows; i++)
{
double distance = matches[i].Distance;
if (distance < Math.Max(minDistance * 2, 0.02))
{
pointsSrc.Add(keyPointsSrc[matches[i].QueryIdx].Pt);
pointsDst.Add(keyPointsTo[matches[i].TrainIdx].Pt);
//距离小于范围的压入新的DMatch
goodMatches.Add(matches[i]);
}
}
outMat = new Mat();
// 算法RANSAC对匹配的结果做过滤
var pSrc = pointsSrc.ConvertAll(Point2fToPoint2d);
var pDst = pointsDst.ConvertAll(Point2fToPoint2d);
var outMask = new Mat();
// 如果原始的匹配结果为空, 则跳过过滤步骤
if (pSrc.Count > 0 && pDst.Count > 0)
Cv2.FindHomography(pSrc, pDst, HomographyMethods.Ransac, mask: outMask);
// 如果通过RANSAC处理后的匹配点大于10个,才应用过滤. 否则使用原始的匹配点结果(匹配点过少的时候通过RANSAC处理后,可能会得到0个匹配点的结果).
if (outMask.Rows > 10)
{
byte[] maskBytes = new byte[outMask.Rows * outMask.Cols];
outMask.GetArray(out maskBytes);
Cv2.DrawMatches(matSrc, keyPointsSrc, matTo, keyPointsTo, goodMatches, outMat, matchesMask: maskBytes, flags: DrawMatchesFlags.NotDrawSinglePoints);
}
else
Cv2.DrawMatches(matSrc, keyPointsSrc, matTo, keyPointsTo, goodMatches, outMat, flags: DrawMatchesFlags.NotDrawSinglePoints);
return goodMatches;
}
}
}
本文来自博客园,作者:꧁执笔小白꧂,转载请注明原文链接:https://www.cnblogs.com/qq2806933146xiaobai/p/18295649
合集:
C#+机器视觉OpenCV
分类:
C#+机器视觉OpenCV
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 记一次.NET内存居高不下排查解决与启示
2023-07-11 Element-动态控制el-table的行的显示与隐藏
2019-07-11 javascript修改css样式表