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;
}
}
}
标签:匹配,Mat,C#,模版,OpenCV,var,new,out,图片
From: https://www.cnblogs.com/qq2806933146xiaobai/p/18295649