12月13日 OpenCV 实战基础学习笔记——Harris、SIFT


前言

本文为12月13日 OpenCV 实战基础学习笔记,分为两个章节:

  • Harri 角点检测;
  • SIFT。

一、Harris 角点检测

使用一个固定窗口在图像上进行任意方向上的滑动,比较滑动前与滑动后两种情况,窗口中的像素灰度变化程度,如果存在任意方向上的滑动,都有着较大灰度变化,那么我们可以认为该窗口中存在角点。

1

1、公式推导

设窗口平移 [ 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

其中:

  • u , v u, v u,v: 窗口偏移量;
  • x , y x, y x,y: 窗口内像素的坐标;
  • w ( x , y ) w(x, y) w(x,y): 窗口函数,内含权重信息,常用的有权重为1和呈二元高斯正太分布的权重;
  • I I I: 像素密度函数,类比与像素值.

2、找到 E ( u , v ) E(u, v) E(u,v) 的最大值

  • 泰勒展开式:
    f ( x + u , y + v ) ≈ f ( x , y ) + u f x ( x , y ) + v f y ( x , y ) f(x+u, y+v) \approx f(x, y) + uf_x(x, y) + vf_y(x, y) f(x+u,y+v)f(x,y)+ufx(x,y)+vfy(x,y)

所以:
∑ [ 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 求偏导得:

  • λ 1 \lambda_1 λ1: X 轴方向的偏导的特征值;
  • λ 2 \lambda_2 λ2: Y 轴方向的偏导的特征值.

2

  • 代码如下:
    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()

3

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()

4

二、SIFT

Scale-Invariant Feature Transform. 步骤主要分两步:

    1. 关键点定位 keypoint localisation;
    1. 特征描述 feature description.

1、关键点定位 keypoint localisation

  • 尺度空间极值检测: 通过使用高斯差分函数来计算并搜索所有尺度上的图像位置,用于识别对尺度和方向不变的潜在兴趣点。

5

  • DoG空间极值检测: 将每个像素点和其图像域(同一尺度空间)和尺度域(相邻的尺度空间)的所有相邻点进行比较。
    当其大于(或者小于)所有相邻点时,该点就是极值点。
    中间的检测点要和其所在图像的 3 × 3 3\times 3 3×3 邻域 8 个像素点,以及其相邻的上下两层的 3 × 3 3\times 3 3×3 领域 18 个像素点,共 26 个像素点进行比较。

  • 关键点精确定位: 通过一个拟合精细的模型在每个候选位置上确定位置和尺度,关键点的选择依赖于它们的稳定程度。

6

  • 方向匹配: 基于局部图像的梯度方向,为每个关键点位置分配一个或多个方向,后续所有对图像数据的操作都是相对于关键点的方向、尺度和位置进行变换,从而而这些变换提供了不变形。

2、特征描述 feature description

  • 使用直方图统计邻域内像素的梯度和方向:

7
为了保证特征矢量的旋转不变性,要以特征点为中心,在附近邻域内将坐标轴旋转θ角度,即将坐标轴旋转为特征点的主方向。

8
旋转之后的主方向为中心取 8 × 8 8\times 8 8×8 的窗口,求每个像素的梯度幅值和方向,箭头方向代表梯度方向,长度代表梯度幅值,然后利用高斯窗口对其进行加权运算,最后在每个 4 × 4 4\times 4 4×4 的小块上绘制 8 个方向的梯度直方图,计算每个梯度方向的累加值,即可形成一个种子点,即每个特征的由 4 个种子点组成,每个种子点有 8 个方向的向量信息。

9

  • 代码如下:
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()

10

# 得到特征点
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()

11

# 计算特征
kp, des = sift.compute(img_gray, kp)
print(np.array(kp).shape)

des.shape
>>> (6809, 128)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值