Hessian焦点检测
- 基本概念
- 角点检测是检测边缘上的角点。
- 角点是曲率变大的点,由高斯曲率来描述
- 高斯曲率公式
- 高斯曲率公式
- 其中
- 高斯曲率公式解释
-
H
表示Hessian
矩阵。图像的二次微分(通过将Sobel
滤波器应用于灰度图像计算得来)。对于图像上的一点,按照下式定义: -
:应用x方向上的Sobel滤波器;
-
:应用y方向上的Sobel滤波器;
- 公式理解
- 在
Hessian
角点检测中,将极大点视为j角点。
- 如果中心像素与其8−近邻像素相比值最大,则中心像素为极大点。
- 解答中,角点是
为极大值,并且大于
的点。
- 代码分析
import cv2
import numpy as np
import matplotlib.pyplot as plt#导入图像处理的三个常用库
# Hessian corner detection hessian角点检测
def Hessian_corner(img):
## Grayscale
def BGR2GRAY(img):#转灰度
gray = 0.2126 * img[..., 2] + 0.7152 * img[..., 1] + 0.0722 * img[..., 0]
gray = gray.astype(np.uint8)
return gray
## Sobel Sobel滤波
def Sobel_filtering(gray):
# get shape
H, W = gray.shape
# sobel kernel 构造不同方向上的sobel滤波器
sobely = np.array(((1, 2, 1),
(0, 0, 0),
(-1, -2, -1)), dtype=np.float32)
sobelx = np.array(((1, 0, -1),
(2, 0, -2),
(1, 0, -1)), dtype=np.float32)
# padding 扩充图像边缘
tmp = np.pad(gray, (1, 1), 'edge')
# prepare 准备Ix Iy
Ix = np.zeros_like(gray, dtype=np.float32)
Iy = np.zeros_like(gray, dtype=np.float32)
# get differential
for y in range(H):
for x in range(W):
Ix[y, x] = np.mean(tmp[y: y + 3, x: x + 3] * sobelx)#生成Ix矩阵
Iy[y, x] = np.mean(tmp[y: y + 3, x: x + 3] * sobely)#生成Iy矩阵
Ix2 = Ix ** 2#得到Ix平方
Iy2 = Iy ** 2#得到Iy平方
Ixy = Ix * Iy#得到Ix与Iy的积
return Ix2, Iy2, Ixy
## Hessian
def corner_detect(gray, Ix2, Iy2, Ixy):
# get shape
H, W = gray.shape
# prepare for show detection
out = np.array((gray, gray, gray))
out = np.transpose(out, (1, 2, 0))
# get Hessian value
Hes = np.zeros((H, W))
for y in range(H):
for x in range(W):
Hes[y, x] = Ix2[y, x] * Iy2[y, x] - Ixy[y, x] ** 2#生成hassian矩阵
## Detect Corner and show
for y in range(H):
for x in range(W):
if Hes[y, x] == np.max(Hes[max(y - 1, 0): min(y + 2, H), max(x - 1, 0): min(x + 2, W)]) and Hes[
y, x] > np.max(Hes) * 0.1:#选取角点
out[y, x] = [0, 0, 255]#将其标红
out = out.astype(np.uint8)
return out
# 1. grayscale
gray = BGR2GRAY(img)
# 2. get difference image
Ix2, Iy2, Ixy = Sobel_filtering(gray)
# 3. corner detection
out = corner_detect(gray, Ix2, Iy2, Ixy)
return out
# Read image
img = cv2.imread("123.jpg").astype(np.float32)
# Hessian corner detection
out = Hessian_corner(img)
cv2.imwrite("out.jpg", out)
cv2.imshow("result", out)
cv2.waitKey(0)
Harris角点检测
基本思想
- 算法基本思想是使用一个固定窗口在图像上进行任意方向上的滑动,比较滑动前与滑动后两种情况,窗口中的像素灰度变化程度,如果存在任意方向上的滑动,都有着较大灰度变化,那么我们可以认为该窗口中存在角点。
如何刻画 - 当窗口发生
[u,v]
移动时,那么滑动前与滑动后对应的窗口中的像素点灰度变化描述如下 -
公式解释 -
[u,v]
是窗口的偏移量 -
(x,y)
是窗口内所对应的像素坐标位置,窗口有多大,就有多少个位置 -
w(x,y)
是窗口函数,最简单情形就是窗口内的所有像素所对应的w权重系数均为1。但有时候,我们会将w(x,y)
函数设定为以窗口中心为原点的二元正态分布。如果窗口中心点是角点时,移动前与移动后,该点的灰度变化应该最为剧烈,所以该点权重系数可以设定大些,表示窗口移动时,该点在灰度变化贡献较大;而离窗口中心(角点)较远的点,这些点的灰度变化几近平缓,这些点的权重系数,可以设定小点,以示该点对灰度变化贡献较小,那么我们自然想到使用二元高斯函数来表示窗口函数 - 根据上述表达式,当窗口处在平坦区域上滑动,可以想象的到,灰度不会发生变化,那么
E(u,v) = 0
;如果窗口处在比纹理比较丰富的区域上滑动,那么灰度变化会很大。算法最终思想就是计算灰度发生较大变化时所对应的位置,当然这个较大是指针任意方向上的滑动,并非单指某个方向。
E(u,v)表达式进一步演化 -
这个式子是一个很简单的二元泰勒公式一阶展开
- 按照上述对
进行处理,即可得到
- 即
- 这里我们取
-
难道我们是直接求上述的E(u,v)值来判断角点吗?Harris角点检测并没有这样做,而是通过对窗口内的每个像素的x方向上的梯度与y方向上的梯度进行统计分析。这里以Ix和Iy为坐标轴,因此每个像素的梯度坐标可以表示成(Ix,Iy)。针对平坦区域,边缘区域以及角点区域三种情形进行分析.
20170120232541519.jpg
-
下图是对这三种情况窗口中的对应像素的梯度分布进行绘制:
20170120232555296.png
- 如果使用椭圆进行数据集表示,则绘制图示如下:
20170120232729130.png
20170120232734098.png
因此可以得出下列结论:
- 特征值都比较大时,即窗口中含有角点
- 特征值一个较大,一个较小,窗口中含有边缘
- 特征值都比较小,窗口处在平坦区域
- 于是
其中
,
- 我们来看一下
的函数图像
20170120232746954.png ,刚好满足上述特征,我们只需要对R给定阈值就可以得到角点位置坐标了,具体步骤如下
基本步骤
- 对图像进行灰度化处理;
- 利用
Sobel
滤波器求出海森矩阵(Hessian matrix)
- 将高斯滤波器分别应用于
- 计算每个像素的
。通常K在
[0.04,0.16]
范围内取值. - 满足
的像素点即为角点。
- 参数选取 高斯滤波器:
代码分析
import cv2
import numpy as np
import matplotlib.pyplot as plt#导入三个常用的图像库
# Harris corner detection角点检测函数
def Harris_corner(img):
## Grayscale
def BGR2GRAY(img):#图像转灰度
gray = 0.2126 * img[..., 2] + 0.7152 * img[..., 1] + 0.0722 * img[..., 0]
gray = gray.astype(np.uint8)
return gray
## Sobel
def Sobel_filtering(gray):#两个方向上进行sobel滤波得到Ix核Iy
# get shape
H, W = gray.shape
# sobel kernel
sobely = np.array(((1, 2, 1),
(0, 0, 0),
(-1, -2, -1)), dtype=np.float32)
sobelx = np.array(((1, 0, -1),
(2, 0, -2),
(1, 0, -1)), dtype=np.float32)
# padding
tmp = np.pad(gray, (1, 1), 'edge')
# prepare
Ix = np.zeros_like(gray, dtype=np.float32)
Iy = np.zeros_like(gray, dtype=np.float32)
# get differential
for y in range(H):
for x in range(W):
Ix[y, x] = np.mean(tmp[y: y + 3, x: x + 3] * sobelx)
Iy[y, x] = np.mean(tmp[y: y + 3, x: x + 3] * sobely)
Ix2 = Ix ** 2
Iy2 = Iy ** 2
Ixy = Ix * Iy
return Ix2, Iy2, Ixy
# gaussian filtering
def gaussian_filtering(I, K_size=3, sigma=3):#高斯滤波函数
# get shape
H, W = I.shape
## gaussian
I_t = np.pad(I, (K_size // 2, K_size // 2), 'edge')
# gaussian kernel高斯核的生成
K = np.zeros((K_size, K_size), dtype=np.float)
for x in range(K_size):
for y in range(K_size):
_x = x - K_size // 2
_y = y - K_size // 2
K[y, x] = np.exp(-(_x ** 2 + _y ** 2) / (2 * (sigma ** 2)))
K /= (sigma * np.sqrt(2 * np.pi))
K /= K.sum()#归一化高斯核
# filtering
for y in range(H):
for x in range(W):
I[y, x] = np.sum(I_t[y: y + K_size, x: x + K_size] * K)
return I
# corner detect
def corner_detect(gray, Ix2, Iy2, Ixy, k=0.04, th=0.1):
# prepare output image
out = np.array((gray, gray, gray))
out = np.transpose(out, (1, 2, 0))
# get R 计算R
R = (Ix2 * Iy2 - Ixy ** 2) - k * ((Ix2 + Iy2) ** 2)#Ix2、Iy2和Ixy均为海森矩阵中的元素
# detect corner
out[R >= np.max(R) * th] = [0, 0, 255]#将图像上色
out = out.astype(np.uint8)
return out
# 1. grayscale#转灰度
gray = BGR2GRAY(img)
# 2. get difference image#sobel滤波之后得到的矩阵
Ix2, Iy2, Ixy = Sobel_filtering(gray)
# 3. gaussian filtering#对2得到的图像进行高斯滤波
Ix2 = gaussian_filtering(Ix2, K_size=3, sigma=3)
Iy2 = gaussian_filtering(Iy2, K_size=3, sigma=3)
Ixy = gaussian_filtering(Ixy, K_size=3, sigma=3)
# 4. corner detect角点检测
out = corner_detect(gray, Ix2, Iy2, Ixy)
return out
# Read image
img = cv2.imread("123.jpg").astype(np.float32)
# Harris corner detection
out = Harris_corner(img)
cv2.imwrite("out.jpg", out)
cv2.imshow("result", out)
cv2.waitKey(0)
网友评论