zoukankan      html  css  js  c++  java
  • 手动绘制方向梯度直方图(HOG)

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

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

    1. 从图像中获取特征量(特征提取);
    2. 基于特征量识别和检测(识别和检测);
      由于深度学习通过卷积网络自动执行特征提取和识别,所以看不到HOG,但在深度学习变得流行之前,HOG经常被用作特征量表达。

    获得HOG算法如下:

    • 图像灰度化,然后在x方向和y方向上求出亮度的梯度:
      • x方向:
        x方向亮度梯度计算公式
      • y方向:
        y方向亮度梯度计算公式
    • 从g_x和g_y确定梯度幅值和梯度方向:
      • 梯度幅值:
        梯度幅值
      • 梯度方向:
        梯度方向
    • 将梯度方向[0,180]进行9等分量化。也就是说,对于[0,20]量化为index 0,对于[20,40]量化为index 1......
    • 将图像划分为N x N个区域(该区域称为cell),并作出cell内上一步得到的index的直方图。
    • C x C个cell被称为一个block,对每个block内的cell的直方图通过下面的式子进行归一化。由于归一化过程中窗口一次移动一个cell来完成,因此一个cell会被归一化多次,通常ε=1。
      归一化
    • 以上,求出HOG特征值。
    • 将得到的特征量可视化。为 cell 内的每个 index 的方向画一条线段,并且值越大,线段越白,
      值越小,线段越黑。
    import cv2
    import numpy as np
    import matplotlib.pyplot as plt
    
    # get HOG
    def HOG(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 quantization
        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
    
    
        # get gradient histogram
        def gradient_histogram(gradient_quantized, magnitude, N=8):
            # get shape
            H, W = magnitude.shape
    
            # get cell num
            cell_N_H = H // N
            cell_N_W = W // N
            histogram = np.zeros((cell_N_H, cell_N_W, 9), dtype=np.float32)
    
            # each pixel
            for y in range(cell_N_H):
                for x in range(cell_N_W):
                    for j in range(N):
                        for i in range(N):
                            histogram[y, x, gradient_quantized[y * 4 + j, x * 4 + i]] += magnitude[y * 4 + j, x * 4 + i]
    
            return histogram
    
    		# histogram normalization
        def normalization(histogram, C=3, epsilon=1):
            cell_N_H, cell_N_W, _ = histogram.shape
            ## each histogram
            for y in range(cell_N_H):
        	    for x in range(cell_N_W):
           	    #for i in range(9):
                    histogram[y, x] /= np.sqrt(np.sum(histogram[max(y - 1, 0) : min(y + 2, cell_N_H),
                                                                max(x - 1, 0) : min(x + 2, cell_N_W)] ** 2) + epsilon)
    
            return histogram
    
        # 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)
    
        # 4. Gradient histogram
        histogram = gradient_histogram(gradient_quantized, magnitude)
        
        # 5. Histogram normalization
        histogram = normalization(histogram)
    
        return histogram
    
    
    # draw HOG
    def draw_HOG(img, histogram):
        # Grayscale
        def BGR2GRAY(img):
            gray = 0.2126 * img[..., 2] + 0.7152 * img[..., 1] + 0.0722 * img[..., 0]
            return gray
    
        def draw(gray, histogram, N=8):
            # get shape
            H, W = gray.shape
            cell_N_H, cell_N_W, _ = histogram.shape
            
            ## Draw
            out = gray[1 : H + 1, 1 : W + 1].copy().astype(np.uint8)
    
            for y in range(cell_N_H):
                for x in range(cell_N_W):
                    cx = x * N + N // 2
                    cy = y * N + N // 2
                    x1 = cx + N // 2 - 1
                    y1 = cy
                    x2 = cx - N // 2 + 1
                    y2 = cy
                    
                    h = histogram[y, x] / np.sum(histogram[y, x])
                    h /= h.max()
            
                    for c in range(9):
                        #angle = (20 * c + 10 - 90) / 180. * np.pi
                        # get angle
                        angle = (20 * c + 10) / 180. * np.pi
                        rx = int(np.sin(angle) * (x1 - cx) + np.cos(angle) * (y1 - cy) + cx)
                        ry = int(np.cos(angle) * (x1 - cx) - np.cos(angle) * (y1 - cy) + cy)
                        lx = int(np.sin(angle) * (x2 - cx) + np.cos(angle) * (y2 - cy) + cx)
                        ly = int(np.cos(angle) * (x2 - cx) - np.cos(angle) * (y2 - cy) + cy)
    
                        # color is HOG value
                        c = int(255. * h[c])
    
                        # draw line
                        cv2.line(out, (lx, ly), (rx, ry), (c, c, c), thickness=1)
    
            return out
        
    
        # get gray
        gray = BGR2GRAY(img)
    
        # draw HOG
        out = draw(gray, histogram)
    
        return out
    
    # Read image
    img = cv2.imread("../baby.png").astype(np.float32)
    
    # get HOG
    histogram = HOG(img)
    
    # draw HOG
    out = draw_HOG(img, histogram)
    
    
    # Save result
    cv2.imwrite("out.jpg", out)
    cv2.imshow("result", out)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    
    

    原图可视化特征量

  • 相关阅读:
    sass接触
    css 文字超出部分显示省略号(原)
    vue组件
    字节流
    File类、递归
    异常
    静态导入、可变参数、Collections集合工具类、集合嵌套
    Map接口
    Set接口
    List接口
  • 原文地址:https://www.cnblogs.com/wojianxin/p/12560337.html
Copyright © 2011-2022 走看看