方向梯度直方图(HOG)第一步:梯度幅值・梯度方向
求出imori.jpg
的 HOG 特征量的梯度幅值和梯度方向吧!
HOG(Histogram of Oriented Gradients)是一种表示图像特征量的方法。特征量是表示图像的状态等的向量集合。
在图像识别(图像是什么)和检测(物体在图像中的哪个位置)中,我们需要:
- 从图像中获取特征量(特征提取);
- 基于特征量识别和检测(识别和检测)。
由于深度学习通过机器学习自动执行特征提取和识别,所以看不到 HOG,但在深度学习变得流行之前,HOG 经常被用作特征量表达。
通过以下算法获得HOG:
- 图像灰度化之后,在x方向和y方向上求出亮度的梯度:
- $$x$$方向:
$$
g_x=I(x+1,y)-I(x-1,y)
$$ -
$$y$$方向:
$$
g_y=I(x,y+1)-I(x,y-1)
$$
- 从g_x和g_y确定梯度幅值和梯度方向:
-
梯度幅值
mag=\sqrt{{g_x}^2+{g_y}^2}
-
梯度方向:
ang=\arctan{\frac{g_y}{g_x}}
-
将梯度方向[0,180]进行9等分量化。也就是说,对于[0,20]量化为 index 0,对于[20,40]量化为 index 1……
-
将图像划分为N \times N个区域(该区域称为 cell),并作出 cell 内步骤3得到的 index 的直方图。
-
C x C个 cell 被称为一个 block。对每个 block 内的 cell 的直方图通过下面的式子进行归一化。由于归一化过程中窗口一次移动一个 cell 来完成的,因此一个 cell 会被归一化多次,通常\epsilon=1:
h(t)=\frac{h(t)}{\sqrt{\sum\ h(t)+\epsilon}}
以上,求出 HOG 特征值。
这一问,我们完成步骤1到3。
为了使示例答案更容易看出效果,gra
是彩色的。此外,mag
被归一化至[0,255]。
python实现:
import cv2
import numpy as np
import matplotlib.pyplot as plt
# get HOG step1
def HOG_step1(img):
# Grayscale
def BGR2GRAY(img):
gray = 0.2126 * img[..., 2] + 0.7152 * img[..., 1] + 0.0722 * img[..., 0]
return gray
# Magnitude and gradient
def get_gradXY(gray):
H, W = gray.shape
# padding before grad
gray = np.pad(gray, (1, 1), 'edge')
# get grad x
gx = gray[1:H+1, 2:] - gray[1:H+1, :W]
# get grad y
gy = gray[2:, 1:W+1] - gray[:H, 1:W+1]
# replace 0 with
gx[gx == 0] = 1e-6
return gx, gy
# get magnitude and gradient
def get_MagGrad(gx, gy):
# get gradient maginitude
magnitude = np.sqrt(gx ** 2 + gy ** 2)
# get gradient angle
gradient = np.arctan(gy / gx)
gradient[gradient < 0] = np.pi / 2 + gradient[gradient < 0] + np.pi / 2
return magnitude, gradient
# Gradient histogram
def quantization(gradient):
# prepare quantization table
gradient_quantized = np.zeros_like(gradient, dtype=np.int)
# quantization base
d = np.pi / 9
# quantization
for i in range(9):
gradient_quantized[np.where((gradient >= d * i) & (gradient <= d * (i + 1)))] = i
return gradient_quantized
# 1. BGR -> Gray
gray = BGR2GRAY(img)
# 1. Gray -> Gradient x and y
gx, gy = get_gradXY(gray)
# 2. get gradient magnitude and angle
magnitude, gradient = get_MagGrad(gx, gy)
# 3. Quantization
gradient_quantized = quantization(gradient)
return magnitude, gradient_quantized
# Read image
img = cv2.imread("imori.jpg").astype(np.float32)
# get HOG step1
magnitude, gradient_quantized = HOG_step1(img)
# Write gradient magnitude to file
_magnitude = (magnitude / magnitude.max() * 255).astype(np.uint8)
cv2.imwrite("out_mag.jpg", _magnitude)
# Write gradient angle to file
H, W, C = img.shape
out = np.zeros((H, W, 3), dtype=np.uint8)
# define color
C = [[255, 0, 0], [0, 255, 0], [0, 0, 255], [255, 255, 0], [255, 0, 255], [0, 255, 255],
[127, 127, 0], [127, 0, 127], [0, 127, 127]]
# draw color
for i in range(9):
out[gradient_quantized == i] = C[i]
cv2.imwrite("out_gra.jpg", out)
cv2.imshow("result", out)
cv2.waitKey(0)
cv2.destroyAllWindows()
输入(imori.jpg):
梯度幅值(answer_66_mag.jpg):
梯度方向(answer_66_gra.jpg):