美文网首页边缘检测
OpenCV+Python特征匹配

OpenCV+Python特征匹配

作者: 音符纸飞机 | 来源:发表于2018-10-13 14:54 被阅读194次

特征描述符用来表述图像的特征,通过匹配特征描述符来匹配图像的特征。
OpenCV官方教程

基本流程

  1. 初始化匹配器
  2. 调用匹配器的match方法得到DMatch对象
  3. drawMatches方法画出匹配结果
The result of 
matches = algorithm.match(descriptor1,descriptor2) 
is a list of DMatch objects. This DMatch object has the following attributes:

    DMatch.distance - Distance between descriptors. The lower, the better it is.
    DMatch.trainIdx - Index of the descriptor in train descriptors
    DMatch.queryIdx - Index of the descriptor in query descriptors
    DMatch.imgIdx - Index of the train image.
descriptor1对应的图像是queryImage
descriptor2对应的图像是trainImage
cv2.drawMatches(img1, keypoints1, img2, keypoints2, matches1to2[, outImg[, matchColor[, singlePointColor[, matchesMask[, flags]]]]]) → outImg
"""
Parameters: 
img1 – First source image.
keypoints1 – Keypoints from the first source image.
img2 – Second source image.
keypoints2 – Keypoints from the second source image.
matches1to2 – Matches from the first image to the second one, which means that keypoints1[i] has a corresponding point in keypoints2[matches[i]] .
outImg – Output image. Its content depends on the flags value defining what is drawn in the output image. See possible flags bit values below.
matchColor – Color of matches (lines and connected keypoints). If matchColor==Scalar::all(-1) , the color is generated randomly.
singlePointColor – Color of single keypoints (circles), which means that keypoints do not have the matches. If singlePointColor==Scalar::all(-1) , the color is generated randomly.
matchesMask – Mask determining which matches are drawn. If the mask is empty, all matches are drawn.
flags – Flags setting drawing features. Possible flags bit values are defined by DrawMatchesFlags.
"""
struct DrawMatchesFlags
{
    enum
    {
        DEFAULT = 0, // Output image matrix will be created (Mat::create),
                     // i.e. existing memory of output image may be reused.
                     // Two source images, matches, and single keypoints
                     // will be drawn.
                     // For each keypoint, only the center point will be
                     // drawn (without a circle around the keypoint with the
                     // keypoint size and orientation).
        DRAW_OVER_OUTIMG = 1, // Output image matrix will not be
                       // created (using Mat::create). Matches will be drawn
                       // on existing content of output image.
        NOT_DRAW_SINGLE_POINTS = 2, // Single keypoints will not be drawn.
        DRAW_RICH_KEYPOINTS = 4 // For each keypoint, the circle around
                       // keypoint with keypoint size and orientation will
                       // be drawn.
    };
};
Brute-Force匹配(暴力匹配)

用暴力方法找到点集一中每个descriptor在点集二中距离最近的 descriptor。

bf = cv2.BFMatcher(normType=cv2.NORM_HAMMING, crossCheck=True)
'''
        .   @param normType One of NORM_L1, NORM_L2, NORM_HAMMING, NORM_HAMMING2. L1 and L2 norms are
        .   preferable choices for SIFT and SURF descriptors, NORM_HAMMING should be used with ORB, BRISK and
        .   BRIEF, NORM_HAMMING2 should be used with ORB when WTA_K==3 or 4 (see ORB::ORB constructor
        .   description).
        .   @param crossCheck If it is false, this is will be default BFMatcher behaviour when it finds the k
        .   nearest neighbors for each query descriptor. If crossCheck==true, then the knnMatch() method with
        .   k=1 will only return pairs (i,j) such that for i-th query descriptor the j-th descriptor in the
        .   matcher's collection is the nearest and vice versa, i.e. the BFMatcher will only return consistent
        .   pairs. Such technique usually produces best results with minimal number of outliers when there are
        .   enough matches. This is alternative to the ratio test, used by D. Lowe in SIFT paper.
matching结果包含许多错误匹配,错误的匹配分为两种:

False-positive matches: 将非对应特征点检测为匹配(我们可以对他做文章,尽量消除它)
False-negative matches: 未将匹配的特征点检测出来(无法处理,因为matching算法拒绝)

crossCheck(交叉验证)是消除False-positive matches的一种方式
另外一种方式是ratio,knn就是ratio的一种。使用knnMatch的时候,crossCheck要设置成False
'''
matches = bf.match(des1, des2)
# match 简单查找最优匹配
matches = sorted(matcheds, key = lambda x:x.distance)
Knn筛选匹配点
bf = cv2.BFMatcher(normType=cv2.NORM_HAMMING, crossCheck=False)
matches = bf.knnMatch(des1, des2, k=2)
# 为每个descriptor查找K-nearest-matches,k用来指定匹配的数量
img = cv2.drawMatchesKnn(img1, kp1, img2, kp2, matches, None, flags=2)
FLANN匹配

使用快速近似最近邻搜索算法寻找,适合在大量数据中查找匹配图像。
FlannBasedMatcher为descriptor建立索引树,这种操作将在匹配大量数据时发挥巨大作用(比如在上百幅图像的数据集中查找匹配图像)。而Brute-force matcher在这个过程并不进行操作,它只是将train descriptors保存在内存中。
Flann匹配的速度远远快于Blute-Force,大约是10倍。

# FLANN parameters
FLANN_INDEX_KDTREE = 0
index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)
search_params = dict(checks=50) # or pass empty dictionary
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))]
# ratio test as per Lowe's paper
for i,(m,n) in enumerate(matches):
    if m.distance < 0.7*n.distance:
        matchesMask[i]=[1,0]

draw_params = dict(matchColor = (0,255,0), singlePointColor = (255,0,0), matchesMask = matchesMask, flags = 0)
img = cv2.drawMatchesKnn(img1,kp1,img2,kp2,matches,None,**draw_params)

实例

BFMatcher
import cv2
from matplotlib import pyplot as plt

img1 = cv2.imread("train.jpg", 0)
img2 = cv2.imread("test.jpg", 0)
orb = cv2.ORB_create()

keypoints1, des1 = orb.detectAndCompute(img1, None)
keypoints2, des2 = orb.detectAndCompute(img2, None)

bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
matches = bf.match(des1, des2)
matches = sorted(matches, key=lambda x: x.distance)
img3 = cv2.drawMatches(img1, keypoints1, img2, keypoints2, matches[:20], None, flags=2)
plt.imshow(img3)
plt.show()
BF效果
KNN Matcher
import cv2
from matplotlib import pyplot as plt

img1 = cv2.imread("train.jpg", 0)
img2 = cv2.imread("test.jpg", 0)
orb = cv2.ORB_create()

keypoints1, des1 = orb.detectAndCompute(img1, None)
keypoints2, des2 = orb.detectAndCompute(img2, None)

bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=False)
matches = bf.knnMatch(des1, des2, k=2)
img3 = cv2.drawMatchesKnn(img1, keypoints1, img2, keypoints2, matches[:30], None, flags=2)
plt.imshow(img3)
KNN效果图
FLANN
import cv2
from matplotlib import pyplot as plt

img1 = cv2.imread("train.jpg", 0)
img2 = cv2.imread("test.jpg", 0)
sift = cv2.xfeatures2d.SIFT_create()

# find the keypoints and descriptors with SIFT
kp1, des1 = sift.detectAndCompute(img1, None)
kp2, des2 = sift.detectAndCompute(img2, None)
# FLANN parameters
FLANN_INDEX_KDTREE = 0
index_params = dict(algorithm=FLANN_INDEX_KDTREE, trees=5)
search_params = dict(checks=50)  # or pass empty dictionary
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))]
# ratio test as per Lowe's paper
for i, (m, n) in enumerate(matches):
    if m.distance < 0.5 * n.distance:
        matchesMask[i] = [1, 0]
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.show()
FLANN效果

Trouble Shoot

  1. error: (-215) (type == CV_8U && dtype == CV_32S) || dtype == CV_32F in function cv::batchDistance
    http://answers.opencv.org/question/10046/feature-2d-feature-matching-fails-with-assert-statcpp/

相关文章

  • OpenCV+Python特征匹配

    特征描述符用来表述图像的特征,通过匹配特征描述符来匹配图像的特征。OpenCV官方教程 基本流程 初始化匹配器 调...

  • 模板匹配(OpenCV+Python)

    本文内容是对Opencv官方文档的学习笔记 原理 模板匹配就是在一副大的图像中去搜索查找模板图像的方法,模板图像相...

  • opencv+python -- 模板匹配

    百度百科:模板匹配是一种最原始、最基本的模式识别方法,研究某一特定对象物的图案位于图像的什么地方,进而识别对象物,...

  • opencv+Python特征检测及K-最近邻匹配

     鉴于即将启程旅行,先上传篇简单的图像检索介绍,与各位一起学习opencv的同学共勉 一.特征检测  图片的特征主...

  • OpenCV+Python FLANN特征匹配与单应性变换(Ho

    OpenCV官方文档 FLANN邻近搜索 FLANN库全称是Fast Library for Approximat...

  • 图像局部不变性特征与描述笔记

    图像的特征点匹配概述 特征点匹配原理 如果提取的两个特征点描述矢量间距离很小,这两个特征点在对应场景的同一位置,特...

  • 2019-05-04派森学习第166天

    51、正则匹配,匹配日期2018-03-20 仍有同学问正则,其实匹配并不难,提取一段特征语句,用(.*?)匹配即...

  • 图匹配问题系列(三)判断“相等性”

    图匹配问题分为两类:精确匹配与近似匹配。我们先考虑精确图匹配问题。 比起图匹配,字符串、特征向量等的匹配相对更简单...

  • 使用Opencv+Python的AR小demo

    使用Opencv+Python的AR小demo[https://blog.csdn.net/weixin_4433...

  • 初探图像特征匹配

    在很多功能的实现都离不开图像的匹配算法,如何又快又准的进行匹配,匹配的过程又是怎么实现的呢?最近趁着编译的空闲,初...

网友评论

    本文标题:OpenCV+Python特征匹配

    本文链接:https://www.haomeiwen.com/subject/ygknaftx.html