本文为12月13日 OpenCV 实战基础学习笔记,分为两个章节:
使用一个固定窗口在图像上进行任意方向上的滑动,比较滑动前与滑动后两种情况,窗口中的像素灰度变化程度,如果存在任意方向上的滑动,都有着较大灰度变化,那么我们可以认为该窗口中存在角点。
设窗口平移 [ U , V ] [U, V] [U,V] 产生灰度变化 E ( u , v ) E(u, v) E(u,v) :
E ( u , v ) = ∑ x , y w ( x , y ) [ I ( x + u , y + v ) − I ( x , y ) ] 2 E(u,v) = {\textstyle \sum_{x, y}} w(x, y)[I(x+u, y+v) - I(x, y)]^2 E(u,v)=∑x,yw(x,y)[I(x+u,y+v)−I(x,y)]2
其中:
所以:
∑ [ I ( x + u , y + v ) − I ( x , y ) ] 2 ≈ ∑ [ I ( x , y ) + u I x ( x , y ) + v I y ( x , y ) − I ( x , y ) ] 2 = ∑ u 2 I x 2 + 2 v u I x I y + v 2 I y 2 = ∑ [ u v ] [ I x 2 I x I y I x I y I y 2 ] [ u v ] M = ∑ x , y w ( x , y ) [ I x 2 I x I y I x I y I y 2 ] \sum [I(x+u, y+v) - I(x, y)]^2 \approx \sum [ I(x, y) + uI_x(x, y) + vI_y(x, y)- I(x, y)]^2 = \sum u^2 I_x^2 + 2vu I_x I_y + v^2 I_y^2 = \sum [uv]\begin{bmatrix} I_x^2 & I_x I_y \\ I_x I_y & I_y^2 \end{bmatrix} \begin{bmatrix} u \\ v \end{bmatrix}\\ M = {\textstyle \sum_{x, y}}w(x, y) \begin{bmatrix} I_x^2 & I_x I_y \\ I_x I_y & I_y^2 \end{bmatrix} ∑[I(x+u,y+v)−I(x,y)]2≈∑[I(x,y)+uIx(x,y)+vIy(x,y)−I(x,y)]2=∑u2Ix2+2vuIxIy+v2Iy2=∑[uv][Ix2IxIyIxIyIy2][uv]M=∑x,yw(x,y)[Ix2IxIyIxIyIy2]
其中, ∑ x , y w ( x , y ) {\textstyle \sum_{x, y}}w(x, y) ∑x,yw(x,y) 为窗口功能, I x , I y I_x, I_y Ix,Iy 分别为每个像素点 x 方向的强度和 y 方向的强度。 对 I x , I y I_x, I_y Ix,Iy 求偏导得:
cv2.cornerHarris()
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
img = cv.imread("./Harris_SIFT/test_1.jpg")
# img = cv.cvtColor(img, cv.COLOR_BGR2RGB)
cv.imshow("Origin", img)
cv.waitKey(0)
cv.destroyAllWindows()
img_gray = cv.cvtColor(img, cv.COLOR_RGB2GRAY)
# img_gray = np.float32(img_gray)
dst = cv.cornerHarris(img_gray, 2, 3, 0.04)
print("dst.shape: ", dst.shape)
>>> dst.shape: (800, 1200)
img[dst > 0.01 * dst.max()] = [0, 0, 255]
cv.imshow("Dst", img)
cv.waitKey(0)
cv.destroyAllWindows()
Scale-Invariant Feature Transform. 步骤主要分两步:
DoG空间极值检测: 将每个像素点和其图像域(同一尺度空间)和尺度域(相邻的尺度空间)的所有相邻点进行比较。
当其大于(或者小于)所有相邻点时,该点就是极值点。
中间的检测点要和其所在图像的 3 × 3 3\times 3 3×3 邻域 8 个像素点,以及其相邻的上下两层的 3 × 3 3\times 3 3×3 领域 18 个像素点,共 26 个像素点进行比较。
关键点精确定位: 通过一个拟合精细的模型在每个候选位置上确定位置和尺度,关键点的选择依赖于它们的稳定程度。
为了保证特征矢量的旋转不变性,要以特征点为中心,在附近邻域内将坐标轴旋转θ角度,即将坐标轴旋转为特征点的主方向。
旋转之后的主方向为中心取 8 × 8 8\times 8 8×8 的窗口,求每个像素的梯度幅值和方向,箭头方向代表梯度方向,长度代表梯度幅值,然后利用高斯窗口对其进行加权运算,最后在每个 4 × 4 4\times 4 4×4 的小块上绘制 8 个方向的梯度直方图,计算每个梯度方向的累加值,即可形成一个种子点,即每个特征的由 4 个种子点组成,每个种子点有 8 个方向的向量信息。
import cv2 as cv
import numpy as np
img = cv.imread("./Harris_SIFT/test_1.jpg")
img_gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
cv.imshow("Gray", img_gray)
cv.waitKey(0)
cv.destroyAllWindows()
# 得到特征点
sift = cv.SIFT_create()
kp = sift.detect(img_gray, None)
img = cv.drawKeypoints(img_gray, kp, img)
cv.imshow("Keypoints", img)
cv.waitKey(0)
cv.destroyAllWindows()
# 计算特征
kp, des = sift.compute(img_gray, kp)
print(np.array(kp).shape)
des.shape
>>> (6809, 128)