Opencv 梯度幅值 梯度方向

方向梯度直方图(HOG)第一步:梯度幅值・梯度方向

求出imori.jpg的 HOG 特征量的梯度幅值和梯度方向吧!

HOG(Histogram of Oriented Gradients)是一种表示图像特征量的方法。特征量是表示图像的状态等的向量集合。

在图像识别(图像是什么)和检测(物体在图像中的哪个位置)中,我们需要:

  1. 从图像中获取特征量(特征提取);
  2. 基于特征量识别和检测(识别和检测)。

由于深度学习通过机器学习自动执行特征提取和识别,所以看不到 HOG,但在深度学习变得流行之前,HOG 经常被用作特征量表达。

通过以下算法获得HOG:

  1. 图像灰度化之后,在x方向和y方向上求出亮度的梯度:
  • $$x$$方向:
    $$
    g_x=I(x+1,y)-I(x-1,y)
    $$

  • $$y$$方向:
    $$
    g_y=I(x,y+1)-I(x,y-1)
    $$

  1. g_xg_y确定梯度幅值和梯度方向:
  • 梯度幅值

    mag=\sqrt{{g_x}^2+{g_y}^2}

  • 梯度方向:
    ang=\arctan{\frac{g_y}{g_x}}

  1. 将梯度方向[0,180]进行9等分量化。也就是说,对于[0,20]量化为 index 0,对于[20,40]量化为 index 1……

  2. 将图像划分为N \times N个区域(该区域称为 cell),并作出 cell 内步骤3得到的 index 的直方图。

  3. 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):

Opencv 梯度幅值 梯度方向

梯度幅值(answer_66_mag.jpg):

Opencv 梯度幅值 梯度方向

梯度方向(answer_66_gra.jpg):

Opencv 梯度幅值 梯度方向

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程