/// <summary>
/// 特征点Surf匹配
/// </summary>
/// <param name="imgSrc">输入图1</param>
/// <param name="imgSub">输入图2</param>
/// <param name="threshold">Surf的阈值</param>
/// <returns></returns>
public static Bitmap MatchPicBySurf(Bitmap imgSrc, Bitmap imgSub, double threshold = 400)
{
Mat matSrc = BitmapConverter.ToMat(imgSrc);
Mat matTo = BitmapConverter.ToMat(imgSub);
Mat matSrcRet = new Mat();
Mat matToRet = new Mat();
KeyPoint[] keyPointsSrc, keyPointsTo;
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;
}
}
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]);
}
}
var outMat = new Mat();
var pSrc = new List<Point2d>();
var pDst = new List<Point2d>();
//单精度点转为双精度点
foreach (Point2f point in pointsSrc) { pSrc.Add(new Point2d(point.X, point.Y)); }
foreach (Point2f point in pointsDst) { pDst.Add(new Point2d(point.X, point.Y)); }
var outMask = new Mat();
// 如果原始的匹配结果为空, 则跳过过滤步骤
if (pSrc.Count > 0 && pDst.Count > 0)
// 算法RANSAC对匹配的结果做过滤
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 OpenCvSharp.Extensions.BitmapConverter.ToBitmap(outMat);
}
}
OpenCvSharp特征点提取与匹配
于 2021-04-16 13:57:37 首次发布
该代码示例展示了如何利用OpenCvSharp库进行SURF特征点的检测与匹配,并通过FlannBasedMatcher筛选出高质量匹配点。在匹配过程中,还运用了RANSAC算法进行几何变换的过滤,以提高匹配的准确性。
摘要由CSDN通过智能技术生成