美文网首页
C#:SURF特征匹配

C#:SURF特征匹配

作者: 大龙10 | 来源:发表于2024-02-23 12:49 被阅读0次

一、SURF算法

  • SURF(Speeded Up Robust Features)
    是一种用于特征检测和图像匹配的算法,
    其主要特点是在提供良好特征匹配性能的同时,具有高速性和对图像变换的鲁棒性。

二、核心函数

1、SURF.Create()

创建SURF检测器

SURF.Create(hessianThreshold, extended, upright)

  • hessianThreshold:
    Hessian阈值,用于控制关键点检测。通常,较大的值将导致更少但更重要的关键点。
  • extended:
    如果为 true,则使用扩展的SURF描述符。扩展的描述符具有更多信息,但也更大。
  • upright:
    如果为 true,则只检测正立(不旋转)的SURF特征。这在某些情况下可以提高性能。

2、detector.DetectAndCompute()

检测关键点并计算特征描述向量

DetectAndCompute(Mat image, Mat mask, out KeyPoint[] keypoints, Mat descriptors)

  • image:
    要检测关键点的图像。
  • mask:
    一个可选的掩膜,可用于限制关键点的检测区域。
  • keypoints:
    输出参数,存储检测到的关键点。
  • descriptors:
    输出参数,存储计算的特征描述向量。

3、Cv2.DrawMatches()

绘制特征匹配

void Cv2.DrawMatches(
Mat img1, KeyPoint[] keypoints1,
Mat img2, KeyPoint[] keypoints2,
DMatch[] matches1to2,
Mat outImg,
Scalar matchColor, Scalar singlePointColor,
MatOfByte mask,
DrawMatchesFlags flags = DrawMatchesFlags.Default );

  • img1 和 img2:
    两幅输入图像,用于绘制特征匹配。
  • keypoints1 和 keypoints2:
    分别是两幅图像的关键点数组。
  • matches1to2:
    一个包含特征点匹配关系的数组,通常是使用特征匹配算法(如SIFT,SURF,ORB)得出的。
  • outImg:
    存储输出结果的 Mat 对象,通常是一个空白图像,这个方法会在这个图像上绘制特征匹配。
  • matchColor:
    用于绘制匹配线的颜色。
  • singlePointColor:
    用于绘制单个特征点的颜色。
  • mask:
    可选参数,一个指示哪些匹配有效的掩码图像。如果不使用掩码,可以传递 null。
  • flags:
    一个可选参数,控制绘制特征匹配的方式。可以是DrawMatchesFlags.Default 或其他选项。

4、KeyPoint 类:

  • 用于表示检测到的关键点的类,包括位置、尺度、方向等信息。

三、匹配思路:

1、创建检测器
2、检测关键点并计算特征描述向量
3、创建特征点匹配器并进行匹配
4、绘制两个图像匹配出得关键点
5、显示匹配图像

四、程序

        private Image image = null;
        private Image image2 = null;
        private Mat dst = new Mat();
        private Mat srcImage1;
        private Mat srcImage2;
        string filePath = "";

       private void button2_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.Title = "选择操作的图片";
            openFileDialog.Filter = "图片 *.jpg|*.jpg|*.bmp|*.bmp|图像*.png|*.png";
            if (openFileDialog.ShowDialog() == DialogResult.OK)
            {
                filePath = openFileDialog.FileName;
                image2 = Image.FromFile(filePath);
                srcImage2 = Cv2.ImRead(filePath);

            }
            if (filePath != "")
            {
                pictureBox2.Image = image2;
            }

        }

        private void button3_Click(object sender, EventArgs e)
        {
            // 定义SURF中的hessian阈值特征点检测算子
            int minHessian = 400;
            // 定义一个特征检测类对象
            var MySurf = OpenCvSharp.XFeatures2D.SURF.Create(minHessian, 4, 3, true, true);

            Mat descriptors1 = new Mat();
            Mat descriptors2 = new Mat();

            // 模板类是能够存放任意类型的动态数组,能够增加和压缩数据
            // 方法1:计算描述符(特征向量),将Detect和Compute操作分开
            //KeyPoint[] keyPoint1 = MySurf.Detect(srcImage1);
            //KeyPoint[] keyPoint2 = MySurf.Detect(srcImage2);
            //MySurf.Compute(srcImage1, ref keyPoint1, descriptors1);
            //MySurf.Compute(srcImage2, ref keyPoint2, descriptors2);

            // 方法2:计算描述符(特征向量),将Detect和Compute操作合并
            OpenCvSharp.KeyPoint[] keyPoint1, keyPoint2;
            MySurf.DetectAndCompute(srcImage1, null, out keyPoint1, descriptors1);
            MySurf.DetectAndCompute(srcImage2, null, out keyPoint2, descriptors2);

            // 使用BruteForce进行匹配 暴力匹配
            // 创建特征点匹配器
            BFMatcher matcher = new BFMatcher(NormTypes.L2, crossCheck: false);
            // 匹配两幅图中的描述子(descriptors)
            DMatch[] matches = matcher.Match(descriptors1, descriptors2);


            // 设置比率阈值
            double ratio_thresh = 0.2;

            List<DMatch> good_matches = new List<DMatch>();
            for (int i = 0; i < matches.Length; i++)
            {
                if (matches[i].Distance < ratio_thresh)
                {
                    good_matches.Add(matches[i]);
                }
            }

            if (good_matches.Count <= 4)
            {
                // 匹配点不足,无法进行透视变换
                MessageBox.Show("合格匹配点数量不足" + good_matches.Count);
            }


            // 创建一个新的图像以绘制匹配结果
            Mat imgMatches = new Mat();
            // 绘制匹配关键点
            Cv2.DrawMatches(srcImage1, keyPoint1, srcImage2, keyPoint2, good_matches, imgMatches, null, null, null, DrawMatchesFlags.NotDrawSinglePoints);


            // -------锚定物体------------
            // 创建两个数组来存储匹配成功的特征点,一个用于物体图像(obj),另一个用于场景图像(scene)
            Point2d[] obj = new Point2d[good_matches.Count()], scene = new Point2d[good_matches.Count()];


            // 遍历匹配成功的特征点
            for (int i = 0; i < good_matches.Count(); i++)
            {
                // 获取查询图像中特征点的坐标,通过good_matches[i].QueryIdx找到对应特征点的索引
                obj[i] = new Point2d((int)keyPoint1[good_matches[i].QueryIdx].Pt.X, (int)keyPoint1[good_matches[i].QueryIdx].Pt.Y);

                // 获取模板图像中对应的特征点坐标,通过good_matches[i].TrainIdx找到对应特征点的索引
                scene[i] = new Point2d((int)keyPoint2[good_matches[i].TrainIdx].Pt.X, (int)keyPoint2[good_matches[i].TrainIdx].Pt.Y);
            }
            if (obj.Length < 4)
            {
                MessageBox.Show("obj优秀匹配点不足,数量为" + obj.Length);

            }

            if (scene.Length < 4)
            {
                MessageBox.Show("匹配点不足,数量为" + scene.Length);
                return;
            }
            // 使用Cv2.FindHomography方法计算透视变换矩阵H,它可以将物体图像映射到场景图像上
            // HomographyMethods.Ransac表示使用RANSAC算法来估计透视变换矩阵,3表示RANSAC算法的最大迭代次数,null表示不使用掩码
            Mat H = Cv2.FindHomography(obj, scene, HomographyMethods.Ransac, 3, null);

            // 创建两点,初始值设为最小和最大的浮点数,用于存储最左上角和最右下角的点
            OpenCvSharp.Point2f topLeft = new OpenCvSharp.Point2f(float.MaxValue, float.MaxValue);
            OpenCvSharp.Point2f bottomRight = new OpenCvSharp.Point2f(float.MinValue, float.MinValue);

            // 遍历所有匹配点
            foreach (DMatch match in good_matches)
            {
                // 获取当前匹配对中源图像和目标图像的点坐标
                OpenCvSharp.Point2f srcPt = keyPoint1[match.QueryIdx].Pt;
                OpenCvSharp.Point2f dstPt = keyPoint2[match.TrainIdx].Pt;

                // 寻找最左上角的点
                topLeft.X = Math.Min(topLeft.X, srcPt.X);
                topLeft.Y = Math.Min(topLeft.Y, srcPt.Y);

                // 寻找最右下角的点
                bottomRight.X = Math.Max(bottomRight.X, srcPt.X);
                bottomRight.Y = Math.Max(bottomRight.Y, srcPt.Y);
            }

            // 将浮点数坐标转换为整数坐标
            OpenCvSharp.Point topLeftPoint = new OpenCvSharp.Point((int)topLeft.X, (int)topLeft.Y);
            OpenCvSharp.Point bottomRightPoint = new OpenCvSharp.Point((int)bottomRight.X, (int)bottomRight.Y);
            // 绘制一个矩形框,框住匹配的区域
            Cv2.Rectangle(imgMatches, topLeftPoint, bottomRightPoint, new Scalar(0, 255, 0), 2);
            // 显示最终的匹配图像
            Cv2.ImShow("匹配图", imgMatches);

        }

五、结果

SURF特征匹配结果

六、资料

亦陈不染的博客:
https://blog.csdn.net/m0_55074196/article/details/134181416

相关文章

  • python 3+opencv 3.4(五)--图像特征提取

    应用:图像拼接、图像匹配 特征检测和提取算法:Harris(检测角点)SIFT(检测斑点blob)SURF(检测斑...

  • Surf特征

    在对未配准图像进行融合处理时,现在尝试着先对所有图像进行配准操作,在这儿用到的特征是SURF,SURF是SIFT的...

  • SURF匹配点单应性提纯

    1、SURF简介   Speeded Up Robust Features(SURF,加速稳健特征),是一种稳健的...

  • 特征点检测算法

    特征点检测算法 Harris角点检测 SIFT特征检测 SURF特征检测 ORB特征检测

  • ORB特征描述子

    之所以会要说到ORB特征描述,是因为在做图像拼接时,选取特征点时,我所采用的是SURF特征,因为相比于SIFT特征...

  • 关于BOW详细介绍

    这篇文章属于小笔记类型奥~~ 1 特征提取 使用SIFT或者SURF生成图像特征的描述子 2 构建词典(Vocab...

  • 计算机视觉 OpenCV Android | 特征检测与匹配 之

    引言及特征点监测器 前面提到的SURF与SIFT特征检测器与描述子,其实都是OpenCV扩展模块xfeature2...

  • CV笔记

    Harris Coner Keypoint角点SIFT/SURF算子 寻找特征 128维向量 开运算 先进性腐蚀再...

  • OpenCV+Python特征匹配

    特征描述符用来表述图像的特征,通过匹配特征描述符来匹配图像的特征。OpenCV官方教程 基本流程 初始化匹配器 调...

  • 《C# 教程》菜鸟教程

    学习地址 C#有用的网站 C# Programming Guide - 介绍了有关关键的 C# 语言特征以及如何通...

网友评论

      本文标题:C#:SURF特征匹配

      本文链接:https://www.haomeiwen.com/subject/hcfnadtx.html