特征匹配

import numpy as np
import cv2
import matplotlib
import matplotlib.pyplot as plt
%matplotlib inline
def cv_show(name, img):
    cv2.imshow(name, img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

一、Brute-Force蛮力匹配

主要流程:

  1. 求出原图像与模板图像的所有特征点
  2. 将模板图像的特征点依次和原图像中的每个特征向量使用欧氏距离进行匹配
  3. 使用归一化的结果进行比较
# 将带匹配图像和模板图像读入
img = cv2.imread('box_in_scene.png')
template = cv2.imread('box.png')
cv_show('Origine', img)
cv_show('template', template)

例图显示

① 待匹配图像:

OpenCV day 13 - Features_match

② 模板图像

OpenCV day 13 - Features_match

# 计算各自的特征向量
sift = cv2.SIFT_create()
kp1, des1 = sift.detectAndCompute(img, None)
kp2, des2 = sift.detectAndCompute(template, None)
# 构造匹配器
# crossCheck参数表示两个特征点要求相互匹配,例如A中的第 i 个特征点和B中的第 j 个特征点匹配最佳,
# 那么只有当 B 中所有特征点仅有第 j 个特征点到 A 的第 i 个特征点最详尽,那么匹配成功
bf = cv2.BFMatcher(crossCheck = True)

1. 1 对 1 匹配

# des 是特征向量
matches = bf.match(des1, des2)
matches = sorted(matches, key = lambda x:x.distance) # 将 match 返回的结果中的distance函数结果值作为匹配标准
# 各参数含义:原图、特征点、模板图、特征点、显示匹配的前10个特征点、、
res = cv2.drawMatches(img, kp1, template, kp2, matches[:10], None, flags = 2)
cv_show('result',res)

结果显示:

OpenCV day 13 - Features_match

2. k 最佳匹配

# 匹配器仍为蛮力匹配器
bf = cv2.BFMatcher()
# des 是特征向量, 最后的 k 表示 不限制匹配为一对一,可以一对多(反过来也一样)
matches = bf.knnMatch(des1, des2, k =2)
# 筛选出匹配对
good = []
for m,n in matches:
    if m.distance < 0.75 * n.distance:
        good.append([m])
# good是筛选过后的匹配对
res = cv2.drawMatchesKnn(img, kp1, template, kp2, good, None, flags = 2)
cv_show('result',res)

若需要更快速的完成匹配,可以尝试使用 cv2.FlannBasedMatcher

3. 随机抽样一致算法(Random sample consensus, RANSAC)

  • 下面红色线条是最小二乘法的出的线性回归模型,绿色线条是由RANSAC得出的模型

OpenCV day 13 - Features_match

选择初始样本点进行拟合,给定一个容忍范围,并不断地进行迭代

OpenCV day 13 - Features_match

每次迭代完毕,容忍范围内都有对应的数据点数,找出数据个数最多的情况,这就是最终的拟合结果

  • 这样看来,RANSAC是只能拟合直线吗?

OpenCV day 13 - Features_match

4. 单应性矩阵

求图像变化的矩阵H,一般为 3 * 3.

H=[h11h12h13h21h22h23h31h321]H=left[begin{array}{ccc} h_{11} & h_{12} & h_{13} \ h_{21} & h_{22} & h_{23} \ h_{31} & h_{32} & 1 end{array}right]

下面的 (x′,y′)(x^{prime}, y^{prime} )是经过H(x,y)(x, y)进行变换后的结果

[x′y′1]=[h11h12h13h21h22h23h31h321][xy1]left[begin{array}{c} x^{prime} \ y^{prime} \ 1 end{array}right]=left[begin{array}{ccc} h_{11} & h_{12} & h_{13} \ h_{21} & h_{22} & h_{23} \ h_{31} & h_{32} & 1 end{array}right]left[begin{array}{c} x \ y \ 1 end{array}right]

[x1,y1,1,0,0,0,−x1′x1,−x1′y10,0,0,×1,y1,1,−y1′x1,−y1′y1x2,y2,1,0,0,0,−x2′x2,−x2′y20,0,0,×2,y2,1,−y2′x2,−y2′y2x3,y3,1,0,0,0,−x3′x3,−x3′y30,0,0,×3,y3,1,−y3′x3,−y3′y3x4,y4,1,0,0,0,−x4′x4,−x4′y40,0,0,×4,y4,1,−y4′x4,−y4′y4][h11h12h13h21h22h23h31h32]=[x1′y1′x2′y2′x3′y3′x4′y4′]left[begin{array}{c} x_{1}, y_{1}, 1,0,0,0,-x_{1}^{prime} x_{1},-x_{1}^{prime} y_{1} \ 0,0,0, x_{1}, y_{1}, 1,-y_{1}^{prime} x_{1},-y_{1}^{prime} y_{1} \ x_{2}, y_{2}, 1,0,0,0,-x_{2}^{prime} x_{2},-x_{2}^{prime} y_{2} \ 0,0,0, x_{2}, y_{2}, 1,-y_{2}^{prime} x_{2},-y_{2}^{prime} y_{2} \ x_{3}, y_{3}, 1,0,0,0,-x_{3}^{prime} x_{3},-x_{3}^{prime} y_{3} \ 0,0,0, x_{3}, y_{3}, 1,-y_{3}^{prime} x_{3},-y_{3}^{prime} y_{3} \ x_{4}, y_{4}, 1,0,0,0,-x_{4}^{prime} x_{4},-x_{4}^{prime} y_{4} \ 0,0,0, x_{4}, y_{4}, 1,-y_{4}^{prime} x_{4},-y_{4}^{prime} y_{4} end{array}right]left[begin{array}{l} h_{11} \ h_{12} \ h_{13} \ h_{21} \ h_{22} \ h_{23} \ h_{31} \ h_{32} end{array}right]=left[begin{array}{c} x_{1}^{prime} \ y_{1}^{prime} \ x_{2}^{prime} \ y_{2}^{prime} \ x_{3}^{prime} \ y_{3}^{prime} \ x_{4}^{prime} \ y_{4}^{prime} end{array}right]

通过上面的分析,则在投影变换之前,应该至少求出4对特征点才能求解出变换矩阵H,所以我们应该挑选出 匹配最佳 的点,滤除杂散点

二、图像拼接

基本流程:

  1. 对两幅图像进行特征提取
  2. 进行特征匹配(挑选出至少四对特征点)
  3. 对其中某一张图进行投影变换,使其视角和另外一张图像匹配
  4. 图像拼接