34-SURF特征匹配

Record


1、原理:



2、SURF类说明:


3、特征点的两种匹配方法:BF与Flann,,BF更加精确,运行时间更长,Flann计算速度更快,精度稍差;

应用场景

1、目标查找(具有尺度不变特点)
2、图像拼接(将多幅图像拼接起来)

Code

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.Drawing;
using Emgu.CV;
using Emgu.CV.Structure;
using Emgu.CV.CvEnum;
using Emgu.Util;
using Emgu.CV.Util;
using Emgu.CV.XFeatures2D;      //包含SURF
using Emgu.CV.Features2D;       //包含Features2DToolbox
using Emgu.CV.Flann;

namespace lesson34
{
   
    class Program
    {
   
        static void Main(string[] args)
        {
   
            Mat src1 = CvInvoke.Imread("11.jpg");
            Mat src2 = CvInvoke.Imread("22.jpg");

            CvInvoke.Imshow("src1", src1);
            CvInvoke.Imshow("src2", src2);

            SURF surf = new SURF(400);
            //计算特征点
            MKeyPoint[] keyPoints1 =  surf.Detect(src1);
            MKeyPoint[] keyPoints2 =  surf.Detect(src2);
            VectorOfKeyPoint vkeyPoints1 = new VectorOfKeyPoint(keyPoints1);
            VectorOfKeyPoint vkeyPoints2 = new VectorOfKeyPoint(keyPoints2);
            Mat suft_feature1 = new Mat();
            Mat suft_feature2 = new Mat();
            //绘制特征点
            Features2DToolbox.DrawKeypoints(src1, vkeyPoints1, suft_feature1, new Bgr(0, 255, 0));
            Features2DToolbox.DrawKeypoints(src2, vkeyPoints2, suft_feature2, new Bgr(0, 255, 0));
            //显示特征点
            CvInvoke.Imshow("suft_feature1", suft_feature1);
            CvInvoke.Imshow("suft_feature2", suft_feature2);

            //计算特征描述符
            Mat descriptors1 = new Mat();
            Mat descriptors2 = new Mat();
            surf.Compute(src1, vkeyPoints1, descriptors1);
            surf.Compute(src2, vkeyPoints2, descriptors2);
            ///匹配方法1
            //设置暴力匹配器进行匹配显示
            //VectorOfVectorOfDMatch matches = new VectorOfVectorOfDMatch();
            //BFMatcher bFMatcher = new BFMatcher(DistanceType.L2);
            //bFMatcher.Add(descriptors1);
            //bFMatcher.KnnMatch(descriptors2, matches, 2, null);

            //筛选符合条件的匹配点
            //double min_dis = 100, max_dis = 0;
            //for (int i = 0; i < descriptors1.Rows; i++)
            //{
   
            // 不知道为啥会抛出异常
            // try
            // {
   
            // if (max_dis < matches[i][0].Distance)
            // {
   
            // max_dis = matches[i][0].Distance;
            // }
            // if (min_dis > matches[i][0].Distance)
            // {
   
            // min_dis = matches[i][0].Distance;
            // }
            // }
            // catch (Exception)
            // {
   
            // Console.WriteLine("exception...");
            // }

            //}
            //VectorOfVectorOfDMatch good_matches = new VectorOfVectorOfDMatch();
            //for (int i = 0; i < matches.Size; i++)
            //{
   
            // if (matches[i][0].Distance < 2 * min_dis) //倍数关系自由调整
            // {
   
            // good_matches.Push(matches[i]);
            // }
            //}
            //不使用掩膜,直接绘制出匹配的特征点
            //Mat result = new Mat();
            //Features2DToolbox.DrawMatches(src1, vkeyPoints1, src2, vkeyPoints2, good_matches, result,
            // new MCvScalar(0, 255, 0), new MCvScalar(0, 0, 255), null);
            //显示最终结果
            //CvInvoke.Imshow("match-result", result);
            //CvInvoke.WaitKey(0);

            ///匹配方法2-Flann快速匹配
            //创建Flann对象
            IIndexParams id = new LinearIndexParams();
            SearchParams sp = new SearchParams();
            FlannBasedMatcher flannBasedMatcher = new FlannBasedMatcher(id, sp);
            //添加模板
            flannBasedMatcher.Add(descriptors1);
            //计算匹配
            VectorOfVectorOfDMatch matches = new VectorOfVectorOfDMatch();
            flannBasedMatcher.KnnMatch(descriptors2, matches, 2, null);

            Mat mask = new Mat(matches.Size, 1, DepthType.Cv8U, 1);
            mask.SetTo(new MCvScalar(255));
            Features2DToolbox.VoteForUniqueness(matches, 0.7, mask); //计算掩膜
            //绘制并显示匹配的特征点
            Mat result = new Mat();
            Features2DToolbox.DrawMatches(src1, vkeyPoints1, src2, vkeyPoints2, matches, result, new MCvScalar(0, 255, 0),
                new MCvScalar(0, 0, 255), mask);

            CvInvoke.Imshow("match-result", result);
            CvInvoke.WaitKey(0);
        }
    }
}


效果

SURF的BF匹配:(不知道为啥出现了一对多的情况)

SURF的Flann匹配: