欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C# String字符串案例詳解

    C# String字符串案例詳解

    這篇文章主要介紹了C# String字符串案例詳解,本篇文章通過簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-07-07
  • c#中分割字符串的幾種方法

    c#中分割字符串的幾種方法

    c#中分割字符串的幾種方法...
    2007-04-04
  • C#執(zhí)行EXE文件與輸出消息的提取操作

    C#執(zhí)行EXE文件與輸出消息的提取操作

    這篇文章主要介紹了C#執(zhí)行EXE文件與輸出消息的提取操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2021-04-04
  • C#并行編程之信號(hào)量

    C#并行編程之信號(hào)量

    這篇文章介紹了C#并行編程之信號(hào)量,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-05-05
  • c# 二分查找算法

    c# 二分查找算法

    折半搜索,也稱二分查找算法、二分搜索,是一種在有序數(shù)組中查找某一特定元素的搜索算法
    2013-10-10
  • c#實(shí)現(xiàn)數(shù)據(jù)庫(kù)事務(wù)示例分享

    c#實(shí)現(xiàn)數(shù)據(jù)庫(kù)事務(wù)示例分享

    這篇文章主要介紹了c#執(zhí)行多條sql更新語句實(shí)現(xiàn)數(shù)據(jù)庫(kù)事務(wù)的示例,大家參考使用吧
    2014-01-01
  • C#編程簡(jiǎn)單實(shí)現(xiàn)生成PDF文檔的方法示例

    C#編程簡(jiǎn)單實(shí)現(xiàn)生成PDF文檔的方法示例

    這篇文章主要介紹了C#編程簡(jiǎn)單實(shí)現(xiàn)生成PDF文檔的方法,結(jié)合實(shí)例形式分析了C#生成PDF文檔的具體步驟與相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2017-07-07
  • 基于WPF開發(fā)簡(jiǎn)單的顏色選擇器

    基于WPF開發(fā)簡(jiǎn)單的顏色選擇器

    這篇文章主要介紹了如何基于WPF實(shí)現(xiàn)簡(jiǎn)單的顏色選擇器,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)或工作有一定幫助,需要的小伙伴可以參考一下
    2023-07-07
  • C#實(shí)現(xiàn)保存文件時(shí)重名自動(dòng)生成新文件的方法

    C#實(shí)現(xiàn)保存文件時(shí)重名自動(dòng)生成新文件的方法

    這篇文章主要介紹了C#實(shí)現(xiàn)保存文件時(shí)重名自動(dòng)生成新文件的方法,涉及C#針對(duì)保存文件時(shí)出現(xiàn)重命名情況的自動(dòng)處理技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-07-07
  • UnityUI中繪制線狀統(tǒng)計(jì)圖

    UnityUI中繪制線狀統(tǒng)計(jì)圖

    這篇文章介紹了UnityUI中繪制線狀統(tǒng)計(jì)圖的方法,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-04-04

最新評(píng)論