首页 > 编程语言 >C#+OpenCV基础(十八)_模版匹配

C#+OpenCV基础(十八)_模版匹配

时间:2024-07-11 11:09:06浏览次数:16  
标签:匹配 Mat C# 模版 OpenCV var new out 图片

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

相关文章

  • C. Count Triangles
    原题链接题解我们知道,三角形成立的条件是任意两边之和都要大于第三边,因为这里已经明确了三条边的大小关系,即\(x\leqy\leqz\)所以,该三角形成立的条件是\(x+y>z\)看到\(5e5\)我们不难想到遍历其中某条边的长度这里我遍历的是\(y\)遍历\(y\),找到最小的\(x\)使得至少......
  • Docker 因端口映射不一致出现的问题
    问题描述因为服务器原先已经安装了nginx(非容器安装),并且占用80端口;而我方习惯使用容器进行安装应用,故用安装了一个容器ngixn;docker-compose.ymlversion:'3'services:nginx:restart:alwayscontainer_name:nginximage:nginxports:-81:80......
  • WPF/C#:在WPF中如何实现依赖注入
    前言本文通过WPFGallery这个项目学习依赖注入的相关概念与如何在WPF中进行依赖注入。什么是依赖注入依赖注入(DependencyInjection,简称DI)是一种设计模式,用于实现控制反转(InversionofControl,简称IoC)原则。依赖注入的主要目的是将对象的创建和对象之间的依赖关系的管......
  • StarRocks跨集群迁移最佳实践|得物技术
    一、引言2024年之前,DBA维护的StarRocks集群存在在用低版本多、稳定性受组件bug影响大的问题,给日常运维带来一定压力,版本升级迫在眉睫。于是,我们在今年年初安排了针对2.5以下版本升级2.5.13的专项。这里和大家分享下,针对因版本兼容问题而不能原地升级的场景下,进行跨集群升级......
  • TCP协议三次握手和四次挥手原理图文解析
    前言TCP协议(TransmissionControlProtocol)是计算机网络中最常用的传输层协议之一,负责提供可靠、面向连接的数据传输服务。它存在的目的就是为了让传输更可靠,也更稳定,但同样也会对端口与端口之间的传输速率造成影响。它一般采用两种方式来使传输更加可靠。一种是面向连接,而另......
  • Kubernetes高可用集群二进制离线部署(Runtime Docker)
    Kubernetes高可用集群二进制部署(RuntimeDocker)Kubernetes(简称为:k8s)是Google在2014年6月开源的一个容器集群管理系统,使用Go语言开发,用于管理云平台中多个主机上的容器化的应用,Kubernetes的目标是让部署容器化的应用简单并且高效,Kubernetes提供了资源调度、部署管理、服务......
  • Qt开发 | Qt创建线程 | Qt并发-QtConcurrent
    文章目录一、Qt创建线程的三种方法二、Qt并发:QtConcurrent介绍三、QtConcurrentrun参数说明四、获取QtConcurrent的返回值五、C++其他线程技术介绍一、Qt创建线程的三种方法  以下是Qt创建线程的三种方法:方法一:派生于QThread派生于QThread,这是Qt创建线程最常用......
  • ES6 Reflect 详解(三)
    Reflect对象与Proxy对象一样,也是ES6为了操作对象而提供的新API。Reflect对象的设计目的有4个。将Object对象的一些明显属于语言内部的方法(比如Object.defineProperty),放到Reflect对象上。现阶段,某些方法同时在Object和Reflect对象上部署,未来的新方法将只......
  • Android 应用、驱动开发(五十九)Calendar应用(DatePicker、TimePicker )
    一、运行效果:二、主函数MainActivity.java:packagecom.example.a074_calendarapp;importstaticjava.lang.String.format;importandroidx.appcompat.app.AppCompatActivity;importandroid.os.Bundle;importandroid.view.View;importandroid.widget.Button;im......
  • (免费领取源码)计算机毕业设计项目:宠物店管理系统 19849(开题答辩+程序定制+全套文案 )上
    目 录摘要1绪论1.1背景及意义1.2研究现状1.3springboot框架介绍2 宠物店管理系统系统分析2.1可行性分析2.2系统流程分析2.2.1数据流程3.3.2业务流程2.3系统功能分析2.3.1功能性分析2.3.2非功能性分析2.4系统用例分析2.5本章小结......