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匹配: