首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

OpenCV for python-图像特征点检测及匹配

近期一直研究图像的拼接问题,所以和大家在这里分享一下。图像拼接前,找到各个图像的特征点是个非常关键的步骤。这期专栏,我将介绍两种较常用的特征匹配方法(基于OpenCV),Brute-Force匹配和FLANN匹配。

1

BF匹配

cv2.BFMatch(normType,crossCheck=True/False)

其中normType是用来指定要使用的距离测试类型。默认值为cv2.Norm_L2,适用于SIFT,SURF方法,还有一个参数为cv2.Norm_L1。如果是ORB,BRIEF,BRISK算法等,要是用cv2.NORM_HAMMING,如果ORB算法的参数设置为VTA_K==3或4,normType就应该设置为cv2.NORM_HAMMING2.

第二个参数是crossCheck,默认值是False。如果设置为True,匹配条件会更加严格。举例来说,如果A图像中的i点和B图像中的j点距离最近,并且B中的j点到A中的i点距离也最近,相互匹配,这个匹配结果才会返回。

import cv2 as cv

from matplotlib import pyplot as plt

img1=cv.imread("image/work1.jpg",0)

img2=cv.imread("image/work2.jpg",0)

orb=cv.ORB_create() #创建一个orb特征检测器

kp1,des1=orb.detectAndCompute(img1,None) #计算img1中的特征点和描述符

kp2,des2=orb.detectAndCompute(img2,None) #计算img2中的

bf = cv.BFMatcher(cv.NORM_HAMMING,crossCheck=True) #建立匹配关系

mathces=bf.match(des1,des2)# 匹配描述符

mathces=sorted(mathces,key=lambda x:x.distance) #据距离来排序

img3= cv.drawMatches(img1,kp1,img2,kp2,mathces[:40],img2,flags=2) #画出匹配关系

plt.imshow(img3),plt.show() #用matplotlib描绘出来

2

FLANN匹配

import cv2 as cv

from matplotlib import pyplot as plt

img1=cv.imread("image/work1.jpg",0)

img2=cv.imread("image/work2.jpg",0)

orb=cv.ORB_create() #创建一个orb特征检测器

kp1,des1=orb.detectAndCompute(img1,None) #计算img1中的特征点和描述符

kp2,des2=orb.detectAndCompute(img2,None) #计算img2中的特征点和描述符

bf = cv.BFMatcher(cv.NORM_HAMMING,crossCheck=True) #建立匹配关系

mathces=bf.match(des1,des2) #匹配描述符

mathces=sorted(mathces,key=lambda x:x.distance) #据距离来排序

img3= cv.drawMatches(img1,kp1,img2,kp2,mathces[:40],img2,flags=2)# 画出匹配关系

plt.imshow(img3),plt.show() #用matplotlib描绘出来

FLANN 匹配器有两个参数,一个是indexParams,另一个是searchParams,以字典的形式进行参数传递。为了计算匹配,FLANN内部会决定如何处理索引和搜索对象。

索引方法可以选择LinearIndex,KTreeIndex,KMeansIndex等,其中KTreeIndex配置索引简单,只需制定待处理核密度的数量即可,推荐值为1~16。SearchParams只包含一个字段,checks,表示制定索引树要被遍历的次数。经验值推荐,5 kd—trees,50 checks 可以取得较好的匹配精度,并且可以在较短的时间内完成。

在匹配结果中我们根据Lowe的论文,删除匹配结果距离大于0.7的。通过这种过滤,可以避免几乎90%的错误匹配。原文“Distinctive Image Feature from scale Scale-Invariant Keypoints”

匹配结果如下:

图2 FLANN匹配结果

3

FLANN单应性匹配

两幅不在一个平面角度的照片,通过其中一幅照片(小图像)的特征点,与第二幅(大图像)中的特征点可以确定这部分位置在第二幅中的位置。我们通过cv2.findHomography()函数,计算这对图像的透视变化矩阵,然后通过cv2.perspectiveTransform()找到在第二图像(大图像)中的第一幅图像的位置。

import numpy as np

import cv2 as cv

from matplotlib import pyplot as plt

MIN_MATCH_COUNT=10 #设置最低匹配数量为10

img1=cv.imread("image/pen.jpg",0) #读取第一个图像(小图像)

img2=cv.imread("image/work2.jpg",0) #读取第二个图像(大图像)

sift=cv.xfeatures2d.SIFT_create() #创建sift检测器

kp1,des1=sift.detectAndCompute(img1,None)

kp2,des2=sift.detectAndCompute(img2,None)

#创建设置FLAAN匹配

FLANN_INDEX_KDTREE=0

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

search_params=dict(checks=50)

flann=cv.FlannBasedMatcher(index_params,search_params)

mathces=flann.knnMatch(des1,des2,k=2)

good=[]

#过滤不合格的匹配结果,大于0.7的都舍弃

for m,n in mathces:

if m.distance

good.append(m)

#如果匹配结果大于10,则获取关键点的坐标,用于计算变换矩阵

if len(good)>MIN_MATCH_COUNT:

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=cv.findHomography(src_pts,dst_pts,cv.RANSAC,10.0)

matchesMask=mask.ravel().tolist()

#根据变换矩阵进行计算,找到小图像在大图像中的位置

h,w=img1.shape

pts=np.float32([[0,0],[0,h-1],[w-1,h-1],[w-1,0]]).reshape(-1,1,2)

dst=cv.perspectiveTransform(pts,M)

cv.polylines(img2,[np.int32(dst)],True,0,5,cv.LINE_AA)

else:

print(" Not Enough matches are found")

matchesMask=None

#画出特征匹配线

draw_params=dict(matchColor=(0,255,0),singlePointColor=None,

matchesMask=matchesMask,flags=2)

#plt展示最终的结果

img3=cv.drawMatches(img1,kp1,img2,kp2,good,None,**draw_params)

plt.imshow(img3),plt.show()

展示下最终的结果,其中白色和黑色的边框,就是通过变换矩阵计算得到的。

原始照片(大图像)

原始照片(小图像)

原始照片(小图像)

原始图像(大图像)

原始图像(小图像)

FLANN单应性匹配

关注我们

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180404G1EY4500?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券