1、角点的定义
如果一个点在任意方向的微小变动都会导致灰度很大的变化,那么这个点就被称为角点。也就是一阶导数中的局部最大值就是角点。
2、Harris角点检测
harris角点具有平移不变性和旋转不变性,但不具有尺度变换不变性。
步骤:
- RGB2GRAY
- sobel算子计算Ix Iy
- 构建M矩阵
- 计算det(M) - trace(M)^2 阈值取0.04 ~ 0.06,大于一定阈值作为角点
- R = det(M) = λ1 * λ2 trace(M) = λ1 + λ2
- 可不一定正确的将λ1看作x方向梯度,λ2看作y方向梯度,则二者都很小时,说明是内部,二者都很大时说明是角点,二者一个很大一个很小时,说明是边缘
harris返回的是一个由角点分数构成的灰度图像,选取适当的阈值对结果图像进行二值化就检测到了图像的角点。
# opencv中的harris角点检测 要求输入图像为float32
score_img = cv2.cornerHarris(img, blockSize, ksize, k)
blockSize:角点检测的领域大小
ksize:sobel核的大小
k:0.04 ~ 0.06
3、Shi-Tomasi角点检测
harris的改进,将打分函数R修改为 R = min(λ1, λ2),如果得分超过阈值,即认定该点为角点,即要求λ1和λ2都超过阈值
# opencv中的Shi-Tomasi检测
corners = cv2.goodFeaturesToTrack(gray, nums, level, distance)
nums:返回的角点个数
level:角点的质量水平 0 ~ 1
distance: 相邻角点之间的最短欧式距离
4、SIFT角点检测
为解决尺度变换导致的角点检测问题,提出sift角点检测,分为四步实现
- 尺度空间极值检测:LoG 高斯拉普拉斯算子计算量很大,故sift用DoG来对LoG做近似;在DoG搞定后,就可以在不同的尺度空间和2D平面搜索局部最大值了。
- 对于图像中的一个像素点来说,需要与自己周围八邻域和尺度空间中上下两层中的18个点点关闭,如果是局部最大值,说明是关键点
- 关键点定位:要对找到的关键点进行修正
- 为关键点指定方向参数:
- 关键点描述符:选取关键点周围的16X16邻域,由16个4x4方块的方向直方图组成的长度为128的向量构成描述符
- 关键点匹配:采用关键顶啊特征向量的欧式距离作为两幅图像中关键点的相似性判定度量
# opencv中的sift检测 3.4.1之后sift进专利,付费了
sift = cv2.SIFT()
keypoints = sift.detect(gray, None)
由特征检测延伸到图像拼接
实现方法:
1、用SIFT提取图像中的特征点,对关键点计算特征向量
sift = cv2.xfeatures2d.SIFT_create()
keypoints, feature = sift.detectAndCompute(image,None)
2、利用两张图像的特征点和特征向量进行匹配,可以用Knn进行匹配,但是用FLANN(快速最近邻搜索包)更快,使用FLANN的单应性匹配
3、单应性匹配后获得透视变换矩阵H,用H矩阵的逆矩阵对第二幅图进行透视变换,转换成第一张图一样的视角 (单应性被定义为图像的两个平面投影之间的映射)
4、透视变换后就可以直接拼接图片了,将图片通过numpy直接加到透视变化完成的图像的左边,覆盖掉重合的部分,可以加权平均,但拉普拉斯金字塔效果更好