用 OpenCVSharp 4.5 跑一遍 OpenCV 官方教程
原 OpenCV 官方教程链接:OpenCV: Features2D + Homography to find a known object
核心函数:
using System;
using OpenCvSharp;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenCvSharp.XFeatures2D;
namespace ConsoleApp1
{
class tutorial48 : ITutorial
{
public void Run()
{
string input1 = @"I:\csharp\images\match1.png";
string input2 = @"I:\csharp\images\match2.png";
Mat img1 = Cv2.ImRead(input1, ImreadModes.Color);
Mat img2 = Cv2.ImRead(input2, ImreadModes.Color);
if (img1.Empty() || img2.Empty())
{
Console.WriteLine("无法打开图像文件");
return;
}
//第一步:用 SURF Detector 检测关键点,然后计算特征描述向量
int minHessian = 400;
SURF detector = SURF.Create(minHessian);
KeyPoint[] keypoints1, keypoints2;
Mat descriptor1 = new Mat(), descriptor2 = new Mat();
detector.DetectAndCompute(img1, null, out keypoints1, descriptor1);
detector.DetectAndCompute(img2, null, out keypoints2, descriptor2);
//第二步:用基于 FLANN 的方法匹配特征描述向量
DescriptorMatcher matcher = DescriptorMatcher.Create("FlannBased");
DMatch[][] matches = matcher.KnnMatch(descriptor1, descriptor2, 2);
//用 lowe 比法则过滤匹配结果
double ratio_thresh = 0.8;
List<DMatch> good_matches = new List<DMatch>();
for (int i = 0; i < matches.Length; i++)
{
if (matches[i][0].Distance < ratio_thresh * matches[i][1].Distance)
{
good_matches.Add(matches[i][0]);
}
}
//第三步:画出匹配线
Mat image_matches = new Mat();
Cv2.DrawMatches(img1, keypoints1, img2, keypoints2, good_matches, image_matches,
null, null, null, DrawMatchesFlags.NotDrawSinglePoints);
//第四步:锚定物体
Point2d[] obj = new Point2d[good_matches.Count()], scene = new Point2d[good_matches.Count()];
for (int i = 0; i < good_matches.Count(); i++)
{
obj[i] = keypoints1[good_matches[i].QueryIdx].Pt.ToPoint();
scene[i] = keypoints2[good_matches[i].TrainIdx].Pt.ToPoint();
}
Mat H = Cv2.FindHomography(obj, scene, HomographyMethods.Ransac, 3, null);
Point2f[] obj_corners = new Point2f[4];
obj_corners[0] = new Point(0, 0);
obj_corners[1] = new Point((float)img1.Cols, 0);
obj_corners[2] = new Point((float)img1.Cols, (float)img1.Rows);
obj_corners[3] = new Point(0, (float)img1.Rows);
Point2f[] scene_corners = Cv2.PerspectiveTransform(obj_corners, H);
//第五步:画出锚定物体
Point p1 = new Point(scene_corners[0].X + img1.Cols, scene_corners[0].Y);
Point p2 = new Point(scene_corners[1].X + img1.Cols, scene_corners[1].Y);
Cv2.Line(image_matches, p1, p2, new Scalar(0, 255, 0), 4);
p1 = new Point(scene_corners[1].X + img1.Cols, scene_corners[1].Y);
p2 = new Point(scene_corners[2].X + img1.Cols, scene_corners[2].Y);
Cv2.Line(image_matches, p1, p2, new Scalar(0, 255, 0), 4);
p1 = new Point(scene_corners[2].X + img1.Cols, scene_corners[2].Y);
p2 = new Point(scene_corners[3].X + img1.Cols, scene_corners[3].Y);
Cv2.Line(image_matches, p1, p2, new Scalar(0, 255, 0), 4);
p1 = new Point(scene_corners[3].X + img1.Cols, scene_corners[3].Y);
p2 = new Point(scene_corners[0].X + img1.Cols, scene_corners[0].Y);
Cv2.Line(image_matches, p1, p2, new Scalar(0, 255, 0), 4);
Cv2.ImShow("Matches", image_matches);
Cv2.WaitKey();
}
}
}