Opencv之特征匹配

Brute-Force 蛮力匹配

1、导入需要的库

import cv2 
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

2、定义绘图函数

def cv_show(name,img):
    cv2.imshow(name, img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

3、读入需要进行匹配的两张图片

img1 = cv2.imread('box.png', 0)
img2 = cv2.imread('box_in_scene.png', 0)
cv_show('img1',img1)
cv_show('img2',img2)

展示图片:
在这里插入图片描述在这里插入图片描述

4、实例化SIFT函数

sift = cv2.xfeatures2d.SIFT_create()

5、检测特征点并计算特征

kp1, des1 = sift.detectAndCompute(img1, None)
print(np.array(kp1).shape)
print(np.array(des1).shape)
kp2, des2 = sift.detectAndCompute(img2, None)
print(np.array(kp2).shape)
print(np.array(des2).shape)

可以得到结果:img1中有603个特征点,img2中有969个特征点,因为从img1和img2本身的图像来看,img2中是包含img1的,所以进行特征匹配的时候只会匹配img1和img2共有的603个特征点。
ps:当然,这里也可以分开来做,即先检测特征点再计算特征。即:

kp1 = sift.detect(img1, None)
kp2 = sift.detect(img2, None)
kp1, des1 = sift.compute(img1, kp1)
kp2, des2 = sift.compute(img2, kp2)

6、进行BF匹配

此时,情况应分成进行1对1的匹配还是k对最佳匹配。

1对1匹配

创建BF匹配器对象

函数介绍:
cv2.BFMatcher(normType=cv2.NORM_L2, crossCheck=True)

传入参数:

  • normType:指定要使用的距离量度。默认是cv2.NORM_L2。适用于SIFT和SURF特征。对于二进制字符串的描述子,比如ORB,BRIEF,BRISK等,应该用cv2.NORM_HAMMING。使用Hamming距离度量,如果ORB使用VTA_K == 3或者4,应该用cv2.NORM_HAMMING2。
  • crossCheck:表示两个特征点要互相匹配,例如A中的第i个特征点与B中的第j个特征点最近的,并且B中的第j个特征点到A中的第i个特征点也是。当BF匹配器对象创建以后,两个重要的方法是BFMatcher.match()和BFMatcher.knnMatch()。第一个返回最匹配的,crossCheck=True,第二个方法返回k个最匹配的,k由用户指定,此时crossCheck=False。
bf = cv2.BFMatcher(normType=cv2.NORM_L2, crossCheck=True)
进行匹配操作

函数介绍:
bf.match(des1, des2)

输出:
DMatch类型的数据结构。

那么这个这个DMatch数据结构究竟是什么呢?
它包含三个非常重要的数据分别是queryIdx,trainIdx,distance。

  • queryIdx:此匹配对应的测试图像的特征描述子索引(第几个特征点描述符)。即DMatch.queryIdx表示一个测试图像中的特征点。对于一个特征点来说,它本身也具有以下属性:.pt:关键点坐标,.angle:表示关键点方向,.response表示响应强度,.size:表示该点的直径大小。
  • trainIdx:此匹配对应的训练(模板)图像的特征描述子索引(第几个特征点描述符)。即DMatch.trainIdx表示一个训练(模板)图像中的特征点。同样地,对于一个特征点来说,它本身也具有以下属性:.pt:关键点坐标,.angle:表示关键点方向,.response表示响应强度,.size:表示该点的直径大小。
  • distance:代表这对匹配的特征点描述符的欧式距离,数值越小也就说明俩个特征点越相近。即DMatch.distance表示一个距离。
matches = bf.match(des1, des2)
找出最匹配的十个特征点并将它们用线连起来

函数介绍:
cv2.drawMatches(imageA, kpsA, imageB, kpsB, matches[:10], None, flags=2)

传入参数:

  • imageA和imageB表示图片。
  • kpsA和kpsB表示关键点。
  • matches表示进过cv2.BFMatcher获得的匹配的索引值,也有距离。
  • flags表示有几个图像。
matches = sorted(matches, key=lambda x: x.distance)
img3 = cv2.drawMatches(img1, kp1, img2, kp2, matches[:10], None,flags=2)
cv_show('img3',img3)

得到结果:
在这里插入图片描述

k对最佳匹配

k对最佳匹配是指,每一个特征点在另一张图片上都会有k个最匹配的点存在,例如k=2,它会给每个特征点画两根匹配线。
实现方法与1对1匹配大同小异。

创建BF匹配器对象

注意,此时,crossCheck=False(默认)

bf = cv2.BFMatcher()
进行匹配操作

函数介绍:
bf.knnMatch(des1, des2, k=2)

输出:
Knnmatch与match的返回值类型一样,都是DMatch类型的数据结构,只不过一组返回的k(此处=2)个DMatch类型。

matches = bf.knnMatch(des1, des2, k=2)
找出匹配的特征点并将它们用线连起来

在这里,每一个特征点(设为A)都有最匹配的另外两个特征点在另一张图上,设为B和C。其中AB的距离最短,AC的距离次短。
那么规定,如果AB间的距离小于AC间距离的0.75倍,则认为AB的匹配度远远大于A与其他任何点的匹配度,则将AB两点连起来。

good = []
for m, n in matches:
    if m.distance < 0.75 * n.distance:
        good.append([m])
img3 = cv2.drawMatchesKnn(img1,kp1,img2,kp2,good,None,flags=2)
cv_show('img3',img3)

得到结果:
在这里插入图片描述

在C#中使用OpenCV进行特征匹配是一个涉及计算机视觉和图像处理的过程。这通常包括以下步骤: 1. 特征检测:首先需要从图像中提取关键点(特征点),这些关键点在图像中是独特的,并且能够抵抗旋转、缩放和其他变化。OpenCV提供了多种特征检测器,如SIFT、SURF、ORB等。 2. 特征描述:对于每一个检测到的关键点,计算一个描述符(特征描述子),这个描述符描述了关键点周围的局部图像区域。这些描述符用于后续的匹配过程。 3. 特征匹配:使用一些匹配算法,如FLANN匹配器或BFMatcher(暴力匹配器),根据特征描述子在两幅图像之间寻找相似的特征点对。匹配的结果可以用来估计图像之间的几何变换,或者进行对象识别等。 在C#中,你可以使用Emgu CV库,这是一个基于OpenCV的跨平台.NET封装库,提供了对OpenCV功能的访问。以下是一个简单的例子,展示了如何使用Emgu CV进行特征匹配: ```csharp // 初始化ORB特征检测器 var detector = new ORB(); // 使用检测器找到关键点和描述子 KeyPoint[] keypoints1 = null; FeatureDescriptor[] features1 = null; detector.DetectAndCompute(img1, null, out keypoints1, out features1); KeyPoint[] keypoints2 = null; FeatureDescriptor[] features2 = null; detector.DetectAndCompute(img2, null, out keypoints2, out features2); // 创建匹配器 BFMatcher matcher = new BFMatcher(DistanceType.L2); // 匹配两个图像的特征描述子 MatchesArray matches = matcher.Match(features1, features2); // 根据距离排序匹配结果 matches = matches.OrderBy(m => m.Distance).ToArray(); // 可视化匹配结果 Mat matchImage = new Mat(); CvInvoke.DrawMatches(img1, keypoints1, img2, keypoints2, matches, matchImage); // 显示结果 CvInvoke.Imshow("Matches", matchImage); CvInvoke.WaitKey(0); ``` 在上述代码中,`img1`和`img2`是需要匹配的两幅图像,`matches`数组包含了匹配的结果。使用`DrawMatches`方法将匹配结果显示在一个新图像上,然后使用`Imshow`方法显示出来。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cofisher

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值