HOG特征原理

HOG特征:

方向梯度直方图(Histogram of Oriented Gradient, HOG)特征是一种在计算机视觉和图像处理中用来进行物体检测的特征描述子。

它通过计算和统计图像局部区域的梯度方向直方图来构成特征。Hog特征结合SVM分类器已经被广泛应用于图像识别中,尤其在行人检测中获得了极大的成功。

HOG+SVM进行行人检测的方法是法国研究人员Dalal在2005的CVPR上提出的,而如今虽然有很多行人检测算法不断提出,但基本都是以HOG+SVM的思路为主。

(1)主要思想:

在一副图像中,局部目标的表象和形状(appearance and shape)能够被梯度边缘的方向密度分布很好地描述。(本质:梯度的统计信息,而梯度主要存在于边缘的地方)。

(2)具体的实现方法是:

首先将图像分成小的连通区域,我们把它叫细胞单元(cell or patch)。然后采集细胞单元中各像素点的梯度的或边缘的方向直方图。最后把这些直方图组合起来就可以构成特征描述器。

(3)提高性能:

把这些局部直方图在图像的更大的范围内(我们把它叫区间或block)进行对比度归一化(contrast-normalized),所采用的方法是:先计算各直方图在这个区间(block)中的密度,然后根据这个密度对区间中的各个细胞单元做归一化。通过这个归一化后,能对光照变化和阴影获得更好的效果。

(4)优点:

与其他的特征描述方法相比,HOG有很多优点。首先,由于HOG是在图像的局部方格单元上操作,所以它对图像几何的和光学的形变都能保持很好的不变性,这两种形变只会出现在更大的空间领域上。其次,在粗的空域抽样、精细的方向抽样以及较强的局部光学归一化等条件下,只要行人大体上能够保持直立的姿势,可以容许行人有一些细微的肢体动作,这些细微的动作可以被忽略而不影响检测效果。因此HOG特征是特别适合于做图像中的人体检测的

HOG计算过程

原论文中的计算流程图:

(1)图像预处理

包括伽马校正灰度化。这是可选的步骤,因为实验证明做不做影响不大。伽马校正是减少光度对实验的影响。灰度化是将彩色图片变成灰度图。其实彩色图片也可以直接处理。不过是分别对三通道的颜色值进行梯度计算,最后选择梯度最大的那个。为简单起见,假设输入为灰度图,同时大小是64*128(这个大小是上面论文的大小,也可以自己确定不同的大小,但是实验效果就不能得到保证)。

(2)计算每一个像素的梯度(大小和原图一样)

A.分别计算水平梯度(horizontal gradient)和垂直梯度(vertical gradient)

使用下面的核(kernel)来计算

例:

对于像素点A,要计算水平梯度和竖直梯度,如上图,水平梯度 =30-20=10,竖直梯度 =64-32=32.

// C++ gradient calculation.
// Read image
Mat img = imread("bolt.png");
img.convertTo(img, CV_32F, 1/255.0); // Calculate gradients gx, gy
Mat gx, gy;
Sobel(img, gx, CV_32F, 1, 0, 1);
Sobel(img, gy, CV_32F, 0, 1, 1);
# Python gradient calculation 

# Read image
im = cv2.imread('bolt.png')
im = np.float32(im) / 255.0 # Calculate gradient
gx = cv2.Sobel(img, cv2.CV_32F, 1, 0, ksize=1)
gy = cv2.Sobel(img, cv2.CV_32F, 0, 1, ksize=1)

B.计算梯度大小(magnitude of gradient)和梯度方向(direction of gradient)

梯度大小和梯度方向将按照以下公式计算

梯度方向将会取绝对值,因此梯度方向的范围是0-180度。取绝对值的原因是这样效果更好。

(3)计算梯度直方图

按照第二步的计算,每一个像素点都会有两个值:梯度强度/梯度方向。

现在计算梯度直方图,这是一个最关键的步骤,也是HOG能够工作的原因。

梯度直方图是在一个88的cell里面计算的。那么在88的cell里面就会有882=128个值,2是包括了梯度强度和梯度方向。通过统计形成梯度直方图,128个值将会变成9个值,大大降低了计算量,同时又对光照等环境变化更加地robust。

首先,我将0-180度分成9个bins,分别是0,20,40...160。然后统计每一个像素点所在的bin。



梯度方向为80,梯度大小为2的点:80对应80的位置,值为2;

梯度方向为10,梯度大小为4的点:10在0-20正中间,所以0和2位置值均为2;

梯度方向为165,梯度大小为85的点:165在160-180之间,所以160位置值为855/20=21.5,0位置值为8515/20=63.5;

最终得到一个cell的梯度直方图:

归一化

将四个cell组成一个blocks,对16 * 16大小的blocks进行归一化。

归一化的目的是降低光照的影响。

归一化的方法是向量的每一个值除以向量的模长。

比如对于一个(128,64,32)的三维向量来说,模长是

那么归一化后的向量变成了(0.87,0.43,0.22)

那么16*16大小的block是怎么来的?

请看下图

动图戳这里

得到HOG特征向量

每一个16 * 16大小的block将会得到36大小的vector。那么对于一个64 * 128大小的图像,按照上图的方式提取block,将会有7个水平位置和15个竖直位可以取得,所以一共有7 * 15=105个block,所以我们整合所有block的vector,形成一个大的一维vector的大小将会是36 * 105=3780。

得到HOG特征向量,就可以用来可视化和分类了。对于这么大的HOG特征,SVM就派上用场了。

结果如图:

代码实现

# @hichens

import cv2
import numpy as np
import math
import matplotlib.pyplot as plt class Hog_descriptor():
def __init__(self, img, cell_size=16, bin_size=8):
self.img = img
'''
伽马校正
self.img = np.sqrt(img / np.max(img))
self.img = img * 255
'''
self.cell_size = cell_size
self.bin_size = bin_size
self.angle_unit = 360 / self.bin_size def extract(self):
height, width = self.img.shape
#1.计算每个像素的梯度和方向
gradient_magnitude, gradient_angle = self.global_gradient()
gradient_magnitude = abs(gradient_magnitude) cell_gradient_vector = np.zeros((height // self.cell_size, width // self.cell_size, self.bin_size))
for i in range(cell_gradient_vector.shape[0]):
for j in range(cell_gradient_vector.shape[1]):
#取一个cell中的梯度大小和方向
cell_magnitude = gradient_magnitude[i * self.cell_size:(i + 1) * self.cell_size,
j * self.cell_size:(j + 1) * self.cell_size]
cell_angle = gradient_angle[i * self.cell_size:(i + 1) * self.cell_size,
j * self.cell_size:(j + 1) * self.cell_size] #得到每一个cell的梯度直方图;
cell_gradient_vector[i][j] = self.cell_gradient(cell_magnitude, cell_angle) #得到HOG特征可视化图像
hog_image = self.render_gradient(np.zeros([height, width]), cell_gradient_vector) #HOG特征向量
hog_vector = []
#使用滑动窗口
for i in range(cell_gradient_vector.shape[0] - 1):
for j in range(cell_gradient_vector.shape[1] - 1):
#4个cell得到一个block
block_vector = cell_gradient_vector[i:i+1][j:j+1].reshape(-1, 1)
#正则化
block_vector = np.array([vector / np.linalg.norm(vector) for vector in block_vector])
hog_vector.append(block_vector)
return hog_vector, hog_image def global_gradient(self):
#得到每个像素的梯度
gradient_values_x = cv2.Sobel(self.img, cv2.CV_64F, 1, 0, ksize=5)#水平
gradient_values_y = cv2.Sobel(self.img, cv2.CV_64F, 0, 1, ksize=5)#垂直
gradient_magnitude = np.sqrt(gradient_values_x**2 + gradient_values_y**2)#总
gradient_angle = cv2.phase(gradient_values_x, gradient_values_y, angleInDegrees=True)#方向
return gradient_magnitude, gradient_angle def cell_gradient(self, cell_magnitude, cell_angle):
#得到cell的梯度直方图
orientation_centers = [0] * self.bin_size
for i in range(cell_magnitude.shape[0]):
for j in range(cell_magnitude.shape[1]):
gradient_strength = cell_magnitude[i][j]
gradient_angle = cell_angle[i][j]
min_angle, max_angle, mod = self.get_closest_bins(gradient_angle)
orientation_centers[min_angle] += (gradient_strength * (1 - (mod / self.angle_unit)))
orientation_centers[max_angle] += (gradient_strength * (mod / self.angle_unit))
return orientation_centers def get_closest_bins(self, gradient_angle):
idx = int(gradient_angle / self.angle_unit)
mod = gradient_angle % self.angle_unit
return idx, (idx + 1) % self.bin_size, mod def render_gradient(self, image, cell_gradient):
#得到HOG特征图
cell_width = self.cell_size / 2
max_mag = np.array(cell_gradient).max()
for x in range(cell_gradient.shape[0]):
for y in range(cell_gradient.shape[1]):
cell_grad = cell_gradient[x][y]
cell_grad /= max_mag
angle = 0
angle_gap = self.angle_unit
for magnitude in cell_grad:
angle_radian = math.radians(angle)
x1 = int(x * self.cell_size + magnitude * cell_width * math.cos(angle_radian))
y1 = int(y * self.cell_size + magnitude * cell_width * math.sin(angle_radian))
x2 = int(x * self.cell_size - magnitude * cell_width * math.cos(angle_radian))
y2 = int(y * self.cell_size - magnitude * cell_width * math.sin(angle_radian))
cv2.line(image, (y1, x1), (y2, x2), int(255 * math.sqrt(magnitude)))
angle += angle_gap
return image img = cv2.imread('/home/hichens/Desktop/lena_full.jpg', cv2.IMREAD_GRAYSCALE) # 灰度图片
hog = Hog_descriptor(img, cell_size=8, bin_size=9)
vector, image = hog.extract()
print (np.array(vector).shape)
plt.subplot(121)
plt.imshow(img, cmap=plt.cm.gray)
plt.subplot(122)
plt.imshow(image, cmap=plt.cm.gray)
plt.show()

参考文献

1.目标检测的图像特征提取之(一)HOG特征

2.HOG特征

3.Histogram of Oriented Gradients

4.基于传统图像处理的目标检测与识别(HOG+SVM附代码)

HOG特征原理及代码实现的更多相关文章

  1. HOG特征-理解篇

    网上去找关于HOG的资料,发现理解性的较少,并且较为冗长,为方便大家理解便自己写了篇,希望能对奋斗在特征提取第一线的同志们有所帮助: HOG即histogram of oriented gradien ...

  2. 行人检測之HOG特征(Histograms of Oriented Gradients)

    之前的文章行人计数.计次提到HOG特征这个概念,这两天看了一下原版的论文,了解了一下HOG特征的原理,并依据自己的理解将这种方法的流程写了下来,假设有不正确的地方欢迎指正. HOG(Histogram ...

  3. 使用HOG特征+BP神经网络进行车标识别

    先挖个坑,快期末考试了,有空填上w 好了,今晚刚好有点闲,就把坑填上吧. //-------------------------------开篇---------------------------- ...

  4. Opencv学习之路—Opencv下基于HOG特征的KNN算法分类训练

    在计算机视觉研究当中,HOG算法和LBP算法算是基础算法,但是却十分重要.后期很多图像特征提取的算法都是基于HOG和LBP,所以了解和掌握HOG,是学习计算机视觉的前提和基础. HOG算法的原理很多资 ...

  5. 图像的特征工程:HOG特征描述子的介绍

    介绍 在机器学习算法的世界里,特征工程是非常重要的.实际上,作为一名数据科学家,这是我最喜欢的方面之一!从现有特征中设计新特征并改进模型的性能,这就是我们进行最多实验的地方. 世界上一些顶级数据科学家 ...

  6. SVM+HOG特征训练分类器

    #1,概念 在机器学习领域,支持向量机SVM(Support Vector Machine)是一个有监督的学习模型,通常用来进行模式识别.分类.以及回归分析. SVM的主要思想可以概括为两点:⑴它是针 ...

  7. paper 80 :目标检测的图像特征提取之(一)HOG特征

    1.HOG特征: 方向梯度直方图(Histogram of Oriented Gradient, HOG)特征是一种在计算机视觉和图像处理中用来进行物体检测的特征描述子.它通过计算和统计图像局部区域的 ...

  8. HOG特征(Histogram of Gradient)总结(转载)

    整理一下我个人觉得比较好的HOG博文 博文1:OpenCV HOGDescriptor: 参数与图解 http://blog.csdn.NET/raodotcong/article/details/6 ...

  9. HOG参数简介及Hog特征维数的计算(转)

    HOG构造函数 CV_WRAP HOGDescriptor() :winSize(64,128), blockSize(16,16), blockStride(8,8),      cellSize( ...

随机推荐

  1. Ubantu学习笔记2

    又是新的一天,继续学习Ubantu命令 cat 可以查看文件内容 cat -n p.py 可以在查看文件内容的同时显示行号 cat -s p.py 可以将多行空白的地方进行合并成一行(输入空格的地方不 ...

  2. SpringBoot Application事件监听

    SpringBoot Application共支持6种事件监听,按顺序分别是: ApplicationStartingEvent:在Spring最开始启动的时候触发 ApplicationEnviro ...

  3. UVA - 12186 Another Crisis(工人的请愿书)(树形dp)

    题意:某公司有1个老板和n(n<=105)个员工组成树状结构,除了老板之外每个员工都有唯一的直属上司.老板的编号为0,员工编号为1~n.无下属的员工(叶子)打算签署一项请愿书递给老板,但不能跨级 ...

  4. 字符串匹配之BF算法

    1)算法原理 BF(Brute Force)算法是普通的模式匹配算法,BF算法的思想就是将目标串S的第一个字符与模式串P的第一个字符进行匹配,若相等,则继续比较S的第二个字符和P的第二个字符:若不相等 ...

  5. 二十、CI框架数据库操作之查看生产的sql语句

    一.代码如下: 二.我们访问一下: 三.我们对比一下数据库内容 不忘初心,如果您认为这篇文章有价值,认同作者的付出,可以微信二维码打赏任意金额给作者(微信号:382477247)哦,谢谢.

  6. 十五、CI框架之自动加载数据库

    一.在config的autoload.php文件中,如果写入以下代码,那么在控制器中无需再次加载数据库了,相当于全局自动加载数据库了 不忘初心,如果您认为这篇文章有价值,认同作者的付出,可以微信二维码 ...

  7. IIS7实现访问HTTP定向至HTTPS访问

    工具及软件: 系统:windows2008R2 软件:IIS7.0,IIS的Microsoft URL重写模块2.0 下载 操作步骤: 1.下载并在IIS中安装Microsoft URL重写模块2.0 ...

  8. stm32h7 开发板学习

    按键和 IO 之间连接一个 1K 电阻,可以防止当 IO 被配置为高电平输出的时候,按下按键,导致 VDD 和 GND 直接连通.

  9. Linux笔记01

    linux目录结构 : linux只有一个目录. usr:等价于programfiles: etc:存放系统配置 root:管理员(超级用户)目录, home:存放其他用户的目录: lib:共享包: ...

  10. 吴裕雄--天生自然JAVA SPRING框架开发学习笔记:Java Spring的特点和优点

    Spring 是另一个主流的 Java Web 开发框架,该框架是一个轻量级的应用框架,具有很高的凝聚力和吸引力. Spring 是分层的 Java SE/EE full-stack 轻量级开源框架, ...