opencv图像特征值特征匹配

1.蛮力匹配

首先在第一幅图像中选取一个关键点,然后依次与第二幅图像的每个关键点进行(描述符)距离测试,最后返回距离最近的关键点。

(1)对ORB 描述符进行蛮力匹配

代码速记:

  • cv2.ORB_create()
  • orb.detectAndCompute()
  • cv2.BFMatcher()
  • bf.match()
  • sorted()
  • cv2.drawMatches()

参数解释:

bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
  • normType:它是用来指定要使用的距离测试类型。默认值为cv2.Norm_L2。这很适合SIFT 和SURF 等(c2.NORM_L1 也可以)。对于使用二进制描述符的ORB,BRIEF,BRISK算法等,要使用cv2.NORM_HAMMING,这样就会返回两个测试对象之间的汉明距离。如果ORB 算法的参数设置为V TA_K==3 或4,normType就应该设置成cv2.NORM_HAMMING2。
  • crossCheck:默认值为False。如果设置为True,匹配条件就会更加严格,只有到A 中的第i 个特征点与B 中的第j 个特征点距离最近,并且B 中的第j 个特征点到A 中的第i 个特征点也是最近(A 中没有其他点到j 的距离更近)时才会返回最佳匹配(i,j)。也就是这两个特征点要互相匹配才行。这样就能提供统一的结果,这可以用来替代D.Lowe在SIFT 文章中提出的比值测试方法。
matches = bf.match(des1, des2)#返回最佳匹配

matches = bf.knnMatch(des1, des2, k=2)
#每个关键点返回k 个最佳匹配(降序排列之后取前k 个),其中k 是由用户设定的。
#如果除了匹配之外还要做其他事情的话可能会用上(比如进行比值测试)。

bf:match(des1,des2)返回值是一个DMatch 对象列表。这个DMatch 对象具有下列属性:

  • DMatch.distance:描述符之间的距离。越小越好。
  • DMatch.trainIdx:目标图像中描述符的索引。
  • DMatch.queryIdx:查询图像中描述符的索引。
  • DMatch.imgIdx:目标图像的索引。
img3 = cv2.drawMatches(img1, kp1, img2, kp2, matches[:10], None, flags=2)  # 前10个匹配

img3 = cv2.drawMatchesKnn(img1, kp1, img2, kp2, good, None, flags=2)

用来绘制匹配的点。它会将这两幅图像先水平排列,然后在最佳匹配的点之间绘制直线(从原图像到目标图像)。如果前面使用的是BFMatcher.knnMatch(),现在我们可以使用函数cv2.drawMatchsKnn为每个关键点和它的k 个最佳匹配点绘制匹配线。如果k 等于2,就会为每个关键点绘制两条最佳匹配直线。如果我们要选择性绘制话就要给函数传入一个掩模。

实战:

我们有一个查询图像和一个目标图像。我们要使用特征匹配的方法在目标图像中寻找查询图像的位置。

def bf_orb(self):
    img1 = cv2.imread('../images/box.png', 0)  # queryImage
    img2 = cv2.imread('../images/box_in_scene.png', 0)  # trainImage
    #【1】初始ORB特征检测器
    orb = cv2.ORB_create()
    #【2】用ORB找到两幅图像的关键点和描述符
    kp1, des1 = orb.detectAndCompute(img1, None)
    kp2, des2 = orb.detectAndCompute(img2, None)
    #【3】创建BFMatcher对象
    bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
    #【4】匹配两幅图像的描述符
    matches = bf.match(des1, des2)
    #【5】根据描述符之间的距离来排序
    matches = sorted(matches, key=lambda x: x.distance)
    #【6】画出前10匹配的特征点
    img3 = cv2.drawMatches(img1, kp1, img2, kp2, matches[:10], None, flags=2)  # 前10个匹配
    plt.imshow(img3), plt.xticks([]), plt.yticks([]),plt.show()

在这里插入图片描述

(2)对SIFT 描述符进行蛮力匹配和比值测试

代码速记:

  • cv2.xfeatures2d.SIFT_create()
  • sift.detectAndCompute()
  • cv2.BFMatcher()
  • bf.knnMatch()
  • cv2.drawMatchesKnn()

实战:

def bf_sift(self):
    img1 = cv2.imread('../images/box.png', 0)# queryImage
    img2 = cv2.imread('../images/box_in_scene.png', 0)  # trainImage
    #【1】初始化SIFT对象
    sift = cv2.xfeatures2d.SIFT_create()
    #【2】用SIFT找到关键点和描述符
    kp1, des1 = sift.detectAndCompute(img1, None)
    kp2, des2 = sift.detectAndCompute(img2, None)
    #【3】创建BFMatcher对象,使用默认参数
    bf = cv2.BFMatcher()
    #【4】用knn方法获得k 对最佳匹配
    matches = bf.knnMatch(des1, des2, k=2)
    #【5】比值测试
    # 首先获取与 A距离最近的点 B (最近)和 C (次近),
    # 只有当 B/C 小于阀值时(0.75)才被认为是匹配,
    # 因为假设匹配是一一对应的,真正的匹配的理想距离为0
    good = []
    for m, n in matches:
        if m.distance < 0.75 * n.distance:
            good.append([m])
    #【6】画出匹配点:参数是match list
    img3 = cv2.drawMatchesKnn(img1, kp1, img2, kp2, good, None, flags=2)
    plt.imshow(img3), plt.xticks([]), plt.yticks([]),plt.show()

在这里插入图片描述

2.FLANN 匹配器

FLANN 是快速最近邻搜索包(Fast_Library_for_Approximate_Nearest_Neighbors)的简称。它是一个对大数据集和高维特征进行最近邻搜索的算法的集合,而且这些算法都已经被优化过了。在面对大数据集时它的效果要好于BFMatcher。

代码速记:

  • cv2.xfeatures2d.SIFT_create()
  • sift.detectAndCompute()
  • cv2.FlannBasedMatcher()
  • flann.knnMatch()
  • cv2.drawMatchesKnn()

参数解释:

flann = cv2.FlannBasedMatcher(index_params, search_params)

我们需要传入两个字典作为参数。这两个用来确定要使用的算法和其他相关参数等。第一个是IndexParams。各种不同算法的信息可以在FLANN 文档中找到。这里我们总结一下,对于SIFT 和SURF 等,我们可以传入的参数是:

index_params = dict(algorithm=FLANN_INDEX_KDTREE, trees=5)]

第二个字典是SearchParams。用它来指定递归遍历的次数。值越高结果越准确,但是消耗的时间也越多。如果你想修改这个值,传入参数:

search_params = dict(checks=50)

实战:

def flann(self):
    img1 = cv2.imread('../images/box.png', 0)  # queryImage
    img2 = cv2.imread('../images/box_in_scene.png', 0)  # trainImage
    #【1】特征检测、特征描述
    sift = cv2.xfeatures2d.SIFT_create()
    kp1, des1 = sift.detectAndCompute(img1, None)
    kp2, des2 = sift.detectAndCompute(img2, None)
    #【2】准备FLANN parameters
    FLANN_INDEX_KDTREE = 0
    index_params = dict(algorithm=FLANN_INDEX_KDTREE, trees=5)
    search_params = dict(checks=50)  # or pass empty dictionary
    #【3】FLANN匹配
    flann = cv2.FlannBasedMatcher(index_params, search_params)
    matches = flann.knnMatch(des1, des2, k=2)
    # Need to draw only good matches, so create a mask
    matchesMask = [[0, 0] for i in range(len(matches))]
    # 比值测试
    for i, (m, n) in enumerate(matches):
        if m.distance < 0.7 * n.distance:
            matchesMask[i] = [1, 0]
    #【4】画出匹配点
    draw_params = dict(matchColor=(0, 255, 0),
                       singlePointColor=(255, 0, 0),
                       matchesMask=matchesMask,
                       flags=0)

    img3 = cv2.drawMatchesKnn(img1, kp1, img2, kp2, matches, None, **draw_params)
    plt.imshow(img3), plt.xticks([]), plt.yticks([]),plt.show()

在这里插入图片描述

3.使用特征匹配和单应性查找对象

  • 目标是联合使用特征提取和calib3d 模块中的findHomography 在复杂图像中查找已知对象。如果将这两幅图像中的特征点集传给cv2.findHomography(),他就会找到这个对象的透视图变换。然后我们就可以使用函数cv2.perspectiveTransform() 找到这个对象了。至少要4 个正确的点才能找到这种变换。
  • 我们已经知道在匹配过程可能会有一些错误,而这些错误会影响最终结
    果。为了解决这个问题,算法使用RANSAC 和LEAST_MEDIAN(可以通过参数来设定)。所以好的匹配提供的正确的估计被称为inliers,剩下的被称为outliers。cv2.findHomography() 返回一个掩模,这个掩模确定了inlier 和outlier 点。

代码速记:

  • cv2.findHomography()
  • cv2.perspectiveTransform()
  • cv2.drawMatches()

参数解释:

M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 5.0)
  • 第三个参数:Method used to computed a homography matrix. 可能取值有:
    • 0:a regular method using all the points
    • CV_RANSAC:RANSAC-based robust method
    • CV_LMEDS:Least-Median robust method
  • 第四个参数取值范围在1 到10,拒绝一个点对的阈值。原图像的点经过变换后点与目标图像上对应点的误差。超过误差就认为是outlier。
  • 返回值中M 为变换矩阵。

实战:

def homo(self):
    #【1】先在图像中来找到SIFT 特征点,然后再使用比值测试找到最佳匹配。
    img1 = cv2.imread('../images/box.png', 0)  # queryImage
    img2 = cv2.imread('../images/box_in_scene.png', 0)  # trainImage
    sift = cv2.xfeatures2d.SIFT_create()
    kp1, des1 = sift.detectAndCompute(img1, None)
    kp2, des2 = sift.detectAndCompute(img2, None)
    FLANN_INDEX_KDTREE = 0
    index_params = dict(algorithm=FLANN_INDEX_KDTREE, trees=5)
    search_params = dict(checks=50)
    flann = cv2.FlannBasedMatcher(index_params, search_params)
    matches = flann.knnMatch(des1, des2, k=2)
    good = []
    for m, n in matches:
        if m.distance < 0.7 * n.distance:
            good.append(m)
    #【2】只有存在10 个以上匹配时才去查找目标,否则显示警告消息:“现在匹配不足!”
    MIN_MATCH_COUNT = 10
    if len(good) > MIN_MATCH_COUNT:
        #【3】提取两幅图像中匹配点的坐标
        src_pts = np.float32([kp1[m.queryIdx].pt for m in good]).reshape(-1, 1, 2)
        dst_pts = np.float32([kp2[m.trainIdx].pt for m in good]).reshape(-1, 1, 2)
        #【4】传入到函数中计算透视变换矩阵        
        M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 5.0)
        matchesMask = mask.ravel().tolist()
        h, w = img1.shape# 获得原图像的高和宽
        #【5】使用得到的变换矩阵对原图像的四个角进行变换,获得在目标图像上对应的坐标。
        pts = np.float32([[0, 0], [0, h - 1], [w - 1, h - 1], [w - 1, 0]]).reshape(-1, 1, 2)
        dst = cv2.perspectiveTransform(pts, M)
        #【6】在train image中画出变换后的白色对象框
        img2 = cv2.polylines(img2, [np.int32(dst)], True, 255, 3, cv2.LINE_AA)
    else:
        print("Not enough matches are found - %d/%d" % (len(good), MIN_MATCH_COUNT))
        matchesMask = None
    #【7】绘制inliers(如果能成功的找到目标图像的话)或者匹配的关键点(如果失败)。
    draw_params = dict(matchColor=(0, 255, 0),  # draw matches in green color
                       singlePointColor=None,
                       matchesMask=matchesMask,  # draw only inliers
                       flags=2)
    img3 = cv2.drawMatches(img1, kp1, img2, kp2, good, None, **draw_params)
    plt.imshow(img3), plt.xticks([]), plt.yticks([]),plt.show()

在这里插入图片描述

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: OpenCV4是一个广泛使用的计算机视觉库,它提供了许多用于图像处理和分析的函数和算法。特征值提取是图像处理中的一个重要任务,可用于目标检测、图像配准、图像分类等应用中。 在OpenCV4中,特征值提取可以通过不同的方法实现。其中一种常用的方法是利用SIFT(尺度不变特征变换)算法。SIFT算法能够提取图像中的关键点,并计算出这些关键点的描述子,从而构建图像的特征向量。这个特征向量可以用于比较不同图像之间的相似性。 另一个常用的特征值提取方法是SURF(快速稳健特征)算法。SURF算法在计算图像的关键点和描述子时比SIFT算法更快速,但对于小尺寸的图像可能会产生较低的准确性。 除了SIFT和SURF,OpenCV4还提供了其他一些特征值提取算法,如ORB(Oriented FAST and Rotated BRIEF)和AKAZE(加速稳健特征)算法。ORB算法是一种计算速度较快的算法,适用于实时图像处理。AKAZE算法结合了SIFT和SURF的优点,在提取图像特征时具有较高的准确性和鲁棒性。 特征值提取在计算机视觉领域中扮演着重要的角色,它们可以帮助我们从原始图像中提取出最具代表性的特征,从而实现图像的进一步分析和处理。OpenCV4提供了多种不同的方法和算法,可以根据具体需求选择合适的特征值提取方法。 ### 回答2: 特征值提取是计算机视觉中一种重要的技术方法,opencv4中也提供了丰富的特征值提取函数和工具。 在opencv4中,可以通过SIFT(尺度不变特征变换)、SURF(加速稳健特征)、ORB(Oriented FAST and Rotated BRIEF)等函数来进行特征值提取。这些函数可以根据图像中的局部特征点来计算其特征描述子,从而对图像做出鲁棒性的描述。这些描述子可以用于识别、匹配和定位图像中的目标。 SIFT算法通过检测尺度空间极值点,并计算极值点局部邻域的高斯图像梯度,从而得到关键点的尺度和方向信息。SURF算法则通过加速积分图像的计算,提取图像的特征点和描述子,具有较高的计算效率和鲁棒性。ORB是一种结合了FAST关键点检测和BRIEF特征描述子的算法,具有兼顾速度和性能的特点。 opencv4中还提供了更高级的特征值提取方法,比如HOG(方向梯度直方图)、LBP(局部二值模式)等。HOG算法通过计算图像中的梯度方向直方图,提取图像的纹理和形状特征。LBP算法则通过计算图像中像素点的局部二值模式,提取图像的纹理特征。 总之,opencv4提供了丰富的特征值提取函数和工具,可以根据不同的需求和场景选择合适的算法进行特征值的提取和描述。这些特征值可以在计算机视觉中广泛应用于图像处理、目标检测和图像识别等领域。 ### 回答3: 在OpenCV4中,特征值提取是指从图像或者其他数据中提取出具有代表性和辨别性的特征点或特征描述符,用于图像处理、计算机视觉和模式识别等领域。 OpenCV4提供了多种特征值提取的方法,最常用的是SIFT和SURF算法。 SIFT算法(尺度不变特征变换)是一种用于在不同尺度下提取特征点的方法。它通过在多个尺度下对图像进行高斯模糊,并计算图像的梯度和高斯差分来寻找具有稳定特征的关键点。然后,对每个关键点,在其周围计算出局部特征描述符,用于后续的匹配或识别。 SURF算法(加速稳健特征)是SIFT算法的改进版,它利用积分图像和快速Hessian矩阵计算方法来加速特征点提取的过程。SURF算法的优势在于提取速度更快,对尺度变化和旋转更具鲁棒性。 除了SIFT和SURF算法外,OpenCV4还提供了其他的特征值提取方法,如ORB(快速响应二进制)、BRISK(加速受限鲁棒特征)、FREAK(快速稳健增强描述符)等等。在选择特征值提取方法时,需要根据具体应用场景和需求来考虑特征点数量、计算效率、鲁棒性等因素。 总之,通过OpenCV4提供的特征值提取方法,我们可以从图像或其他数据中提取出具有代表性和辨别性的特征点或特征描述符,为后续的图像处理、计算机视觉和模式识别任务提供重要的基础。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值