特征点检测与匹配
特征检测的基本概念
特征检测的应用场景#
- 图像搜索,一帧图片如果进行完全搜索是非常困难的,因为一帧图片小则几十k,多则好几M,如果对其中每个信息都进行比较的话,这个信息量是难以接受的,所以我们一般是把一帧图片的特征点提取出来,提取出来的特征点只有几k字节,这么少的数据我们再进行搜索就会非常方便,比如google每天从全球获取了大量的图片就会对其进行处理,这些处理就是搜索或者提取图像的特征点,把一帧图片的特征点提取出来之后存储到数据库中,当用户在进行搜索的时候它也会对用户提交的图像进行特征检测,检测出特征点之后再去它的数据库中进行搜索,极大的提高了搜索效率和优化了存储成本
- 图像拼接,当我们在户外看见一幅美丽的景象之后就会想着把它拍照记录下来,但拍摄下来的图像和我们看到的景色还是有很大区别的,其中一个关键原因是我们镜头的面积是有限的,与我们眼睛看见的范围不一致,人眼看到的范围更加广阔。为了使得拍摄的景色与我们人眼看到的景色一致,就需要用全景图像,全景图像就是用相机在不同的角度上连续拍照,将拍摄的照片拼接到一起,这些图片的拼接就是用OpenCV的特征点检测实现的。当相机进行照相的时候,它照的每一帧图像都是有重合度的,将重合部分的特征值找到后就能将图像进行拼接,这样就形成了一张全景图像
什么是特征#
1.特征点是唯一的,可追踪的,能比较的。
2.平坦部分很难找到它在原图的位置,边缘比较好找但也不能确定,角点可以轻易查找到位置
3.图像特征就是指有意义的图像区域,具有独特性、易于识别性,比如角点、斑点以及高密度区
计算机可识别的角点#
1.灰度梯度图的最大值对应的像素
2.两条线的交点
3.极值点(一阶导数的最大值,二阶导数为零的点)
Harris角点检测#
1.光滑地区,无论向哪个方向移动,衡量系数不变
2.边缘地区,垂直边缘移动时,衡量系统变换剧烈
3.在交点处,朝着任何一个方向移动,衡量系统都会剧烈变换
cornerHarris(img, dst, blockSize, ksize, k)
blockSize(窗口大小)
ksize(Sobel卷积核)
k: 权重系数
Shi-Tomasi角点检测#
goodFeaturesToTrack(img, maxCorners,...)
maxCorners:角点的最大数,值为0表示无限制
qualityLevel: 小于1.0的正数,一般在0.01-0.1之间
minDistance: 角之间的最小欧式距离,忽略小于此距离的点
mask:感兴趣的区域
blockSize: 检测窗口
useHarrisDetector:是否使用Harris算法,默认Tomasi
k:默认0.04
SIFT: Harris当图片放大后,原来的角检测不出来#
img = cv2.imread('chess.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
sift = cv2.xfeatures2d.SIFT_create()
kp = sift.detect(gray, None)
kp, des = sift.detectAndCompute(gray,None)
sift.drawKeypoints(gray, kp, img)
cv2.imshow('img', img)
cv2.waitKey(0)
##SURF:诞生于SIFT速度慢
```python
surf = cv2.xfeatures2d.SURF_create()
kp, des = surf.detectAndCompute(gray,None)
ORB#
可以做到实时检测#
orb = cv2.ORB_create()
kp, des = orb.detectAndCompute(gray,None)
暴力特征匹配#
bf = cv2.BFMatcher(cv2.NORM_L1)
match = bf.match(des1, des2)
img3 = cv2.drawMatches(img1, kp1, img2, kp2, match, None)
FLANN特征匹配 速度快效果差#
sift = cv2.xfeatures2d.SIFT_create()
kp1, des1 = sift.detectAndCompute(img1,None)
kp2, des2 = sift.detectAndCompute(img2,None)
#创建匹配器
index_params = dict(algorithm = 1, trees = 5)
search_params = dict(checks = 50)
flann = cv2.FlannBasedMatcher(index_params, search_params)
flann.knnMatch(des1, des2, k = 2)
good = []
for i, (m, n) in enumerate(matchs):
if m.distance < 0.7 * n.distance:
good.append(m)
ret = cv2.drawMatchesKnn(img1, kp1, img2, kp2, [good], None)
cv2.imshow('result', ret)
cv2.waitKey()
图像查找#
cv2.findHomography(srcPts)
图像拼接#
#获取单应性矩阵
def get_homo(img1, img2)
#创建特征转换对象
sift = cv2.xfeatures2d.SIFT_create()
k1, d1 = sift.detectAndCompute(img1,None)
k2, d2 = sift.detectAndCompute(img2,None)
#创建特征匹配器
bf = cv2.BFMatcher()
maches = 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_matches = 8
if len(verify_matches) > min_matches:
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:
exit()
def stitch_image(img1, img2, H)
h1,w1 = img1.shape[:2]
h2,w2 = img2.shape[:2]
img1_dims = np.float32([[0,0],[0,h1],[w1,h1],[w1,0]]).reshape(-1,1,2)
img2_dims = np.float32([[0,0],[0,h2],[w2,h2],[w2,0]]).reshape(-1,1,2)
img1_transform = cv2.perspectiveTransform(img1_dims, H)
#矩阵拼接 axis = 0 横向
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.max(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.resize(img1,(640,480))
img2 = cv2.resize(img2,(640,480))
inputsImg = np.hstack((img1,img2))
#找到特征点 描述子 计算单应性矩阵
H = get_homo(img1, img2)
#根据矩阵对图像进行变换平移
result_image = stitch_image(img1, img2,H)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律