C# OpenCvSharp實(shí)現(xiàn)通過特征點(diǎn)匹配圖片
更新時(shí)間:2023年11月09日 10:37:01 作者:天天代碼碼天天
這篇文章主要為大家詳細(xì)介紹了C#如何結(jié)合OpenCVSharp4實(shí)現(xiàn)通過特征點(diǎn)匹配圖片,文中的示例代碼簡(jiǎn)潔易懂,具有一定的學(xué)習(xí)價(jià)值,需要的小伙伴可以參考下
SIFT匹配
SURF匹配
項(xiàng)目
代碼
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對(duì)匹配的結(jié)果做過濾 var pSrc = pointsSrc.ConvertAll(Point2fToPoint2d); var pDst = pointsDst.ConvertAll(Point2fToPoint2d); var outMask = new Mat(); // 如果原始的匹配結(jié)果為空, 則跳過過濾步驟 if (pSrc.Count > 0 && pDst.Count > 0) Cv2.FindHomography(pSrc, pDst, HomographyMethods.Ransac, mask: outMask); // 如果通過RANSAC處理后的匹配點(diǎn)大于10個(gè),才應(yīng)用過濾. 否則使用原始的匹配點(diǎn)結(jié)果(匹配點(diǎn)過少的時(shí)候通過RANSAC處理后,可能會(huì)得到0個(gè)匹配點(diǎn)的結(jié)果). 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>(); //篩選較好的匹配點(diǎn) 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對(duì)匹配的結(jié)果做過濾 var pSrc = pointsSrc.ConvertAll(Point2fToPoint2d); var pDst = pointsDst.ConvertAll(Point2fToPoint2d); var outMask = new Mat(); // 如果原始的匹配結(jié)果為空, 則跳過過濾步驟 if (pSrc.Count > 0 && pDst.Count > 0) Cv2.FindHomography(pSrc, pDst, HomographyMethods.Ransac, mask: outMask); // 如果通過RANSAC處理后的匹配點(diǎn)大于10個(gè),才應(yīng)用過濾. 否則使用原始的匹配點(diǎn)結(jié)果(匹配點(diǎn)過少的時(shí)候通過RANSAC處理后,可能會(huì)得到0個(gè)匹配點(diǎn)的結(jié)果). 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; } } } } }
到此這篇關(guān)于C# OpenCvSharp實(shí)現(xiàn)通過特征點(diǎn)匹配圖片的文章就介紹到這了,更多相關(guān)C# OpenCvSharp匹配圖片內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
您可能感興趣的文章:
- C#中OpenCvSharp 通過特征點(diǎn)匹配圖片的方法
- C#中OpenCVSharp實(shí)現(xiàn)輪廓檢測(cè)
- C#安裝OpenCvSharp4的實(shí)現(xiàn)步驟
- C#借助OpenCvSharp讀取攝像頭并顯示的實(shí)現(xiàn)示例
- c#中WinForm用OpencvSharp實(shí)現(xiàn)ROI區(qū)域提取的示例
- c#中WinForm使用OpencvSharp4實(shí)現(xiàn)簡(jiǎn)易抓邊
- C#結(jié)合OpenCVSharp4實(shí)現(xiàn)圖片相似度識(shí)別
- C#結(jié)合OpenCVSharp4使用直方圖算法實(shí)現(xiàn)圖片相似度比較
相關(guān)文章
c#實(shí)現(xiàn)數(shù)據(jù)庫(kù)事務(wù)示例分享
這篇文章主要介紹了c#執(zhí)行多條sql更新語句實(shí)現(xiàn)數(shù)據(jù)庫(kù)事務(wù)的示例,大家參考使用吧2014-01-01C#編程簡(jiǎn)單實(shí)現(xiàn)生成PDF文檔的方法示例
這篇文章主要介紹了C#編程簡(jiǎn)單實(shí)現(xiàn)生成PDF文檔的方法,結(jié)合實(shí)例形式分析了C#生成PDF文檔的具體步驟與相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2017-07-07C#實(shí)現(xiàn)保存文件時(shí)重名自動(dòng)生成新文件的方法
這篇文章主要介紹了C#實(shí)現(xiàn)保存文件時(shí)重名自動(dòng)生成新文件的方法,涉及C#針對(duì)保存文件時(shí)出現(xiàn)重命名情況的自動(dòng)處理技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-07-07