OpenCV特征的场景
实例:寻找目标图在原图中的位置
图像特征定义
角点
用一个方块移动进行衡量
光滑地区,无论向哪里移动,衡量系数不变
边缘地区,垂直边缘移动时,衡量系数变化剧烈
角点处,无论向哪里移动,衡量系数都变化剧烈
cornerHarris(img,dst,blockSize,ksize,k)
#灰度化
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#处理的是灰度化后的图片
dst = cv2.cornerHarris(gray,2.3.0.04)
#Harris角点的展示
img[dst>0.01 * dst.max()] = [0,0,255]
corners = cv2.goodfeaturesToTrack(gray,1000,0.01,10)
corners = np.int0(corners)
for i in corners:
x,y = i.ravel()
cv2.circle(img,(x,y),3,(255,0,0),-1)
SIFT:Scale-Invariant Feature Transform 与缩放无关的特征转换
SIFT出现的原因:
使用SIFT步骤:
#灰度化
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#创建SIFT对象
sift = cv2.xfeatures2d.SIFT_create()
#进行检测
kp = sift.detect(gray,None)
#绘制关键点
cv2.drawKeypoints(gray,kp,img)
#创建SURF对象
surf= cv2.xfeatures2d.SURF_create()
#进行检测
kp,des = surf.detectAndcompute(gray,None)
#绘制关键点
cv2.drawKeypoints(gray,kp,img)
OBR:Oriented FAST and Rotated BRIEF
OBR优势:可以做到实时监测
抛弃部分数据以提升速度,因此准确性不如SIFT、SURF
FAST:可以做到特征点的实时监测
BRIEF是对已检测到的特征点进行描述,它加快了特征描述符建立的速度,同时也极大的降低了特征匹配的时间
使用ORB步骤:
obr = cv2.ORB_create()
kp,des = obr.detectAndcompute(gray,None)
BF(Brute-Force) 暴力特征匹配
暴力特征匹配原理:它使用第一组中的每个特征的描述子与第二组中的所有特征描述子进行匹配,计算它们之间的差距,然后将最接近的一个匹配值返回
OpenCV特征匹配步骤:
创建匹配器,BFMatchaer(normType,crossCheck)
进行特征匹配,bf.match(des1,des2)
绘制匹配点,cv2.drawMatches(img1,kp1,img2,kp2,match
bf = BFMatchaer(cv2.NORM_L1)
match = bf.match(des1,des2)
cv2.drawMatches(img1,kp1,img2,kp2,match,None)
在进行批量特征匹配时,FLANN速度更快
由于它使用的是临近近似值,所以精度较差
使用FLANN特征匹配的步骤:
KDTREE
knnMatch()
drawMatchesKnn()
#创建匹配器
index_params = dict(algorithm = FLANN_INDEX_KDTREE,trees = 5)
search_params = dict(checks = 50)
flann = cv2.FlannBasedMatcher(index_params,search_params)
#对描述子进行匹配计算
matches = flann.knnMatch(des1,des2,k = 2)
for i,(m,n) in enumerate(matches):
if m.distance < 0.7 * n.distance:
good.append(m)
ret = cv2.drawMatchesKnn(img1,kp1,img2,kp2,[good],None)
srcPts = np.float32([kp1[m.queryIdx].pt for m in good]).reshape(-1,1,2)
dstPts = np.float32([kp2[m.trainIdx].pt for m in good]).reshape(-1,1,2)
H,_ = cv2.findHomography(srcPts,dstPts,cv2.RANSAC,5.0)
h,w = img1.shape[:2]
pts = np.float32([[0,0],[0,h-1],[w-1,h-1],[w-1,0]]).reshape(-1,1,2)
dst = cv2.perspectiveTransform(pts,H)
cv2.polylines(img2,[np.int32(dst)],True,(0,0,255))
import cv2
import numpy as np
#第一步,读取文件,将图片设置成一样的大小 640*480
#第二步,找特征点,描述子,计算单应性矩阵
#第三步,根据单应性矩阵对图像进行变换,然后平移
#第四步,拼接并输出最终结果
def get_homo(img1,img2):
#1.创建特征转换对象
#2.通过调整转换对象获得特征点和描述子
#3.创建特征匹配器
#4.进行特征匹配
#5.过滤特征,找出有效的特征匹配点
sift = cv2.xfeatures2d.SIFT_create()
k1, d1 = sift.detectAndCompute(img1, None)
k2, d2 = sift.detectAndCompute(img2, None)
bf = cv2.BFMatcher()
matches = bf.knnMatch(d1, d2, k=2)
verify_ratio = 0.8
for m1,m2 in matches:
if m1.distance < 0.8 * m2.distance :
verify_matches.append(m1)
min_matcher = 8
if len(verify_matches) > min_matcher:
img1_pts = []
img2_pts = []
for m in verify_matches:
img1_pts.append(k1[m.queryIdx].pt)
img2_pts.append(k2[m.queryIdx].pt)
img1_pts = np.float(img1_pts).reshape(-1,1,2)
img2_pts = np.float(img2_pts).reshape(-1,1,2)
H, mask = cv2.findHomography(img1_pts, img2_pts, cv2.RANSAC, 5.0)
return H
else:
print('error')
exit()
def stitch_image(img1, img2, H):
#1.获得每张图片的四个角点
#2.对图片进行变换(单应性矩阵使图进行旋转,平移)
#3.创建一张大图,将两张图拼接到一起
#4.将结果输出
#获得原始图的高/宽
h1, w1 = img1.shape[:2]
h2, w2 = img2.shape[:2]
img1_dims = np.float([[0,0],[0,h1],[w1,h1],[w1,0]]).reshape(-1,1,2)
img2_dims = np.float([[0,0],[0,h2],[w2,h2],[w2,0]]).reshape(-1,1,2)
img1_transform = cv2.perspectiveTransform(img1_dims, H)
result_dims = np.concatenate((img2_dims, img1_transform), axis = 0)
[x_min, y_min] = np.int32(result_dims.min(axis = 0).ravel() - 0.5)
[x_max, y_max] = np.int32(result_dims.min(axis = 0).ravel() + 0.5)
#平移的距离
transform_dist = [-x_min, -y_min]
transform_array = np.array[1,0,transform_dist[0],[0,1,transform_dist[1]],[0,0,1]]
result_img = cv2.warpPerspective(img1, transform_array.dot(H), (x_max - x_min, y_max - y_min))
result_img[transform_dist[1]:transform_dist[1] + h2,transform_dist[0]:transform_dist[0] + w2] = img2
return result_img
#读取两张图片
img1 = cv2.imread('map1.png')
img2 = cv2.imread('map2.png')
#将两张图片设置成同样大小
img1 = cv2.resize(img1,(640,480))
img2 = cv2.resize(img2,(640,480))
inputs = np.hstack((img1,img2))
#获取单应性矩阵
H = get_homo(img1,img2)
#进行图像拼接
result_image = stitch_image(img1, img2, H)
cv2.imshow('input img',inputs)
cv2.waitKey(0)