C# OpenCvSharp实现通过特征点匹配图片
更新时间:2023年11月09日 10:37:01 作者:天天代码码天天
这篇文章主要为大家详细介绍了C#如何结合OpenCVSharp4实现通过特征点匹配图片,文中的示例代码简洁易懂,具有一定的学习价值,需要的小伙伴可以参考下
SIFT匹配
SURF匹配
项目
代码
using OpenCvSharp; using OpenCvSharp.Extensions; using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Text.RegularExpressions; using System.Windows.Forms; using static System.Net.Mime.MediaTypeNames; namespace OpenCvSharp_Demo { public partial class frmMain : Form { public frmMain() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { } private void button2_Click(object sender, EventArgs e) { Mat matSrc = new Mat("1.jpg"); Mat matTo = new Mat("2.jpg"); var outMat = MatchPicBySift(matSrc, matTo); pictureBox2.Image = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(outMat); } private void button1_Click(object sender, EventArgs e) { Mat matSrc = new Mat("1.jpg"); Mat matTo = new Mat("2.jpg"); var outMat = MatchPicBySurf(matSrc, matTo, 10); pictureBox2.Image = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(outMat); } public Point2d Point2fToPoint2d(Point2f point) => new Point2d((double)point.X, (double)point.Y); public Mat MatchPicBySift(Mat matSrc, Mat matTo) { 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 OpenCvSharp.BFMatcher()) { var matches = bfMatcher.KnnMatch(matSrcRet, matToRet, k: 2); var pointsSrc = new List<Point2f>(); var pointsDst = new List<Point2f>(); var goodMatches = new List<DMatch>(); foreach (DMatch[] items in matches.Where(x => x.Length > 1)) { 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}"); } } var 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 outMat; } } } public Mat MatchPicBySurf(Mat matSrc, Mat matTo, 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($"max distance : {maxDistance}"); Console.WriteLine($"min distance : {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]); } } var 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 outMat; } } } } }
到此这篇关于C# OpenCvSharp实现通过特征点匹配图片的文章就介绍到这了,更多相关C# OpenCvSharp匹配图片内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
C# 9 中新加入的关键词 init,record,with
这篇文章主要介绍了C# 9 中新加入的关键词 init,record,with的相关资料,帮助大家更好的理解和学习c# 9,感兴趣的朋友可以了解下2020-08-08HashTable、HashSet和Dictionary的区别点总结
在本篇文章里小编给大家整理的是关于HashTable、HashSet和Dictionary的区别点,需要的朋友们可以学习下。2020-03-03
最新评论