在OpenCV3中进行特征点筛选与优化-Python版

在前面的记录中对使用OpenCV2进行特征匹配的步骤做了一个简单的介绍,详见:https://www.jianshu.com/p/5083f8d75439,使用了ORB提取特征点,但是匹配出的结果是非常粗糙的,结果显然包含了很多错误的匹配,这就需要使用一些方法来过滤掉这些错误的匹配。因此继续在这里记录对特征点进行进一步筛选的过程,同时,也对几个关键的计算流程做个更详细的说明,方便将来参考。

特征点匹配

OpenCV里面的二维特征匹配,有两种常用的方法,

  • Brute Force Matcher

  • Flann based Matcher

继承于DescriptorMatcher类,分别对应BFMatcher和FlannBasedMatcher。

二者的区别: BFMatcher总是尝试所有可能的匹配,从而使得它总能够找到最佳匹配。这也是Brute Force(暴力法)的原始含义。方法是计算某一个特征点描述子与其他所有特征点描述子之间的距离,然后将得到的距离进行排序,取距离最近的一个作为匹配点。 FlannBasedMatcher中FLANN的含义是Fast Library forApproximate Nearest Neighbors,它是一种近似法,算法更快但是找到的是最近邻近似匹配,当我们需要找到一个相对好的匹配但是不需要最佳匹配的时候可以用FlannBasedMatcher。当然也可以通过调整FlannBasedMatcher的参数来提高匹配的精度或者提高算法速度,但是相应地算法速度或者算法精度会受到影响。

此外,使用特征提取过程得到的特征描述符(descriptor)数据类型有的是float类型的,ORB和BRIEF特征描述子只能使用BruteForce匹配法。

具体matching的方法

  • match: 给定查询集合中的每个特征描述子,寻找最佳匹配,返回值按距离升序排列。

  • knnMatch:给定查询集合中的每个特征描述子,寻找k个最佳匹配

  • radiusMatch:在特定范围内寻找特征描述子,返回特定距离内的匹配

特征点筛选

通过上述过程得到了raw_matches之后,接下来对其进行筛选。

  • 交叉验证(Cross-match filter)

这种方法只针对BFMatcher, 就是将BFMatcher的最后一个参数,交叉验证声明为true,即matcher = cv2.BFMatcher(cv2.NORM_HAMMING,crossCheck=True),如果图1的一个特征点和图2的一个特征点相匹配,则进行一个相反的检查,即从图2上的特征点进行匹配图1的特征点,如果相互之间都匹配成功,才认为是一个好的匹配。

cross-match filter 结果如图(似乎还不够好):


long-cross-match.jpg
  • knnMatch

knnMatch返回K个好的匹配,k可以自行指定。这里指定k=2,raw_matches = matcher.knnMatch(desc1, desc2,2) ,然后每个match得到两个最接近的descriptor,再计算最接近距离和次接近距离之间的比值,当比值大于某个设定的值时,才作为最终的match。

knnMatch结果如图:


long-knn-match.jpg
  • RANSAC

为了进一步提升精度,还可以采用随机采样一致性(RANSAC)来过滤错误的匹配,该方法是利用匹配点计算两图像之间的单应矩阵,然后利用重投影误差来判定某一个匹配是否是正确的匹配。OpenCV中封装了求解单应矩阵的方法 findHomography ,可以为该方法设定一个重投影误差的阈值,可以得到一个向量mask来指定那些是符合重投影误差的匹配点对,用来过滤掉错误的匹配。

RANSAC结果如图,左边是ORB后未筛选的结果,右边是筛选优化后的:


ransac-1.jpg

ransac-2.jpg

可以看出,优化的作用还是很明显的。最后,贴项目代码如下:

"""
Created on Fri Jan 12 17:59:06 2018
Ransac test
@author:wanqingfeng
"""

import numpy as np
import cv2

img1 = cv2.imread("pic/face1.jpg",0)
img2 = cv2.imread("pic/face2.jpg",0)

detector = cv2.ORB_create()

flann_params= dict(algorithm = 6,
 table_number = 6, # 12
 key_size = 12, # 20
 multi_probe_level = 1) #2

matcher = cv2.BFMatcher(cv2.NORM_HAMMING,crossCheck=False)

kp1,desc1 = detector.detectAndCompute(img1,None)
kp2,desc2 = detector.detectAndCompute(img2,None)

raw_matches = matcher.knnMatch(desc1, desc2,2) #2

good = []

for m,n in raw_matches:
 if m.distance < 0.7*n.distance:
 good.append(m)

if len(good)>10:
 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)
 M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC,5.0)

 matchesMask = mask.ravel().tolist()

else:
 print("Not enough matches are found - %d/%d" % (len(good),10))
 matchesMask = None
draw_params = dict(matchColor = (0,255,0), # draw matches in green color
 singlePointColor = (0,0,255),
 matchesMask = matchesMask, 
 flags = 2)# draw only inliers 

vis = cv2.drawMatches(img1,kp1,img2,kp2,good,None,**draw_params)   

cv2.imshow("", vis)
cv2.imwrite("pic/face_brisk_bf_ransac_1519.jpg", vis)
cv2.waitKey()
cv2.destroyAllWindows()

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,980评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,178评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,868评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,498评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,492评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,521评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,910评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,569评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,793评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,559评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,639评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,342评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,931评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,904评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,144评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,833评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,350评论 2 342