您的位置:首页 > 运维架构

opencv图像特征检测及匹配(harris,sift,surf,fast,breif,orb,BFmatch,FlannBasedMatcher)

2018-01-17 22:16 1426 查看
本文简单概括各种算法的提出背景及opencv实现,对具体原理不做讨论

一般而言,一个物体的角点最能够代表物体的特征,所以所谓的特征检测又叫角点(Corner)检测
harris是最早提出的特征提取算法:
opencv实现如下:

dst=cv2.cornerHarris(gray,blockSize=2,ksize=5,k=0.04)
# blockSize -检测的临点数
# •ksize - sobel边缘检测的核
# •k - 目标函数的一个参数(一般取值较小)

sift:harris Corner算法能够解决旋转不变性问题,但不能解决尺度变化问题,由此背景提出了sift算法
opencv实现如下:

sift=cv2.xfeatures2d.SIFT_create()
kp,des=sift.detectAndCompute(gray,None) #计算描述子
其中kp指关键点 des指关键点的特征描述

surf:尽管sift的计算效果较好,但是计算速度较慢 surf(speed up robust features)算法是一个加速算法
速度是sift算法的3倍。
opencv实现如下:

# 400 是Hessian矩阵的阈值,阈值越大能检测的特征就越少
surf=cv2.xfeatures2d.SURF_create(400)
# None为mask参数
kp,des=surf.detectAndCompute(gray,None)

下面结合surf算法做一个简单的测试,上代码:

import cv2
import numpy as np
import matplotlib.pyplot as plt

img=cv2.imread('../images/example_01.jpg')
gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
# Here I set Hessian Threshold to 400 阈值越大能检测的特征就越少
surf=cv2.xfeatures2d.SURF_create(400)
# None 为mask参数
kp,des=surf.detectAndCompute(gray,None)

surf.setHessianThreshold(5000)
kp,des=surf.detectAndCompute(gray,None)

img2=cv2.drawKeypoints(img,kp,None,(0,255,0),4)
plt.imshow(img2),plt.title('surf'),plt.xticks([]),plt.yticks([]),plt.show()

上效果:



orb算法结合了fast算法与brief算法优点,是目前最快的目标检测算法:
fast算法是特征检测的再提速(能够满足实时检测关键点的要求),breif是特征描述子计算的简化与提速,sift与surf算法
每个关键的特征描述子是128维都是单精度,所以每个描述子占128*4=512bytes的内存,breif每个特征描述子32bytes,大大减少内存,
且运算快(利于嵌入式开发)
orb的opencv实现:
import numpy as np
import cv2
import matplotlib.pyplot as plt

img=cv2.imread('../images/example_01.jpg',0)

orb=cv2.ORB_create()
# kp=orb.detect(img,None)
# kp,des=orb.compute(img,kp)

kp,des=orb.detectAndCompute(img,None)
img2=cv2.drawKeypoints(img,kp,None,(0,255,0),flags=0)
plt.imshow(img2),plt.show()
上效果:



特征匹配:
BFmatch(暴力匹配):计算匹配图层的一个特征描述子与待匹配图层的所有特征描述子的距离返回最近距离。
上代码:
import cv2
import numpy as np
import matplotlib.pyplot as plt
train=cv2.imread('../images/train.jpg',0)
query=cv2.imread('../images/example_01.jpg',0)
# 暴力匹配
orb=cv2.ORB_create()
kp1,des1=orb.detectAndCompute(train,None)
kp2,des2=orb.detectAndCompute(query,None)
# 针对ORB算法 NORM_HAMMING 计算特征距离 True判断交叉验证
bf=cv2.BFMatcher(cv2.NORM_HAMMING,crossCheck=True)
# 特征描述子匹配
matches=bf.match(des1,des2)

matches=sorted(matches,key=lambda x:x.distance)
# print(len(matches))
img3=cv2.drawMatches(train,kp1,query,kp2,matches[:20],None,flags=2)
plt.imshow(img3),plt.show()
上效果:



FlannBasedMatcher:是目前最快的特征匹配算法(最近邻搜索)
上代码:
import cv2
import numpy as np
import matplotlib.pyplot as plt
train=cv2.imread('../images/train.jpg',0)
query=cv2.imread('../images/example_01.jpg',0)

sift=cv2.xfeatures2d.SIFT_create()
kp1,des1=sift.detectAndCompute(train,None)
kp2,des2=sift.detectAndCompute(query,None)

# find the keypoints and descriptors with SIFT
kp1, des1 = sift.detectAndCompute(train,None)
kp2, des2 = sift.detectAndCompute(query,None)

# FLANN parameters
FLANN_INDEX_KDTREE = 1
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):
#如果第一个邻近距离比第二个邻近距离的0.7倍小,则保留
    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)

img3 = cv2.drawMatchesKnn(train,kp1,query,kp2,matches,None,**draw_params)
plt.imshow(img3,),plt.show()

上效果:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息