一文理解图像处理之HOG特征

点上方蓝字计算机视觉联盟获取更多干货

在右上方 ··· 设为星标 ★,与你不见不散

HOG特征学习

1.特征描述

特征描述符是图像或图像块的表示,其通过提取有用信息和丢弃无关信息来简化图像。

通常,特征描述将尺寸宽度x高度x 3(通道)的图像转换为长度为n的特征向量/阵列。在HOG特征描述符的情况下,输入图像的大小为64×128×3,输出特征向量的长度为3780。(这里后续会有解释,接着往下看)

在HOG特征描述符中,梯度方向(定向梯度)的分布(直方图)被用作特征。图像的梯度(x和y导数)是有用的,因为渐变的幅度在边缘和角落(突然强度变化的区域)周围很大,并且我们知道边缘和角落包含关于物体形状的更多信息而不是平坦区域。

2.HOG特征概述

HOG的全称为Histogram of Oriented Gradients ,即方向梯度的直方图。由 Navneet Dalal & Bill Triggs 在 CVPR 2005发表的论文中提出来的,广泛应用于图像识别,尤其是解决行人检测的问题。

(1)HOG中的win,block,cell

HOG最先是用来做行人检测的,显然这是一个目标检测的任务,当我们使用滑动窗遍历方法实现目标检测任务时,首先我们需要构建一个滑动窗,这个滑动窗就是HOG中win的概念。可以理解为,在HOG特征提取时,一个窗口是最小的特征提取单元,在目标检测任务中,滑动窗将以一个设定的步长在整个图像中顺序的滑动,每一次滑动后,都会提取窗口内的HOG特征,提取到的特征将送入到预先训练好的分类器中,如果分类器模型判定其为目标,则完成目标检测任务。

3.HOG计算

为了说明问题,我们会使用图像的patch来解释。

(1)预处理

图像可以是任何尺寸。通常,唯一的限制是被分析的pathh具有固定的宽高比。如patch需要具有1:2的宽高比,则它们可以是100×200,128×256或1000×2000但不是101×205。

为了说明这一点,展示了一个大小为720×475的大图像。我们选择了一个大小为100×200的patch来计算我们的HOG特征描述符。从图像中裁剪出来100*200的patch并调整为64×128。

(Dalal和Triggs的论文也提到了伽马校正作为预处理步骤,但性能提升很小,因此我们正在跳过这一步。)

(2)计算梯度图像

我们需要首先计算水平和垂直梯度; 毕竟,我们想要计算梯度的直方图。通过使用以下两个kernel来计算,也可以直接用OpenCV里面的kernel大小为1的Sobel算子来计算。

// 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);

使用以下公式找到梯度的大小和方向

OpenCV,则可以使用cartToPolar函数完成计算,如下所示

// C++ Calculate gradient magnitude and direction (in degrees)
Mat mag, angle; 
cartToPolar(gx, gy, mag, angle, 1);

得到的梯度图如下:

左边是X方向的绝对梯度;中间是y方向的绝对梯度;右边表示梯度幅值

从上面的图像中可以看到x轴方向的梯度主要凸显了垂直方向的线条,y轴方向的梯度凸显了水平方向的梯度,梯度幅值凸显了像素值有剧烈变化的地方。

图像的梯度去掉了很多不必要的信息(比如不变的背景色),加重了轮廓。换句话说,从梯度的图像中还是可以轻而易举的发现有个人。

在每个像素点,都有一个幅值(magnitude)和方向,对于有颜色的图片,会在三个channel上都计算梯度。那么相应的幅值就是三个channel上最大的幅值,角度(方向)是最大幅值所对应的角。

(3)计算8×8细胞中梯度的直方图

在这一步,上面的patch图像会被分割成8*8大小的网格(如下图),每个网格都会计算一个梯度直方图。

这个patch的大小是64*128,分割成8*8的cell,那么一共有64/8 * 128/8 = 8*16=128个网格

为什么要分成8*8的呢?用特征描述子的一个主要原因是它提供了一个紧凑(compact)/压缩的表示。一个8*8的图像有8*8*3=192个像素值,每个像素有两个值(幅值magnitude和方向direction,三个channel取最大magnitude那个),加起来就是8*8*2=128,后面我们会看到这128个数如何用一个9个bin的直方图来表示成9个数的数组。不仅仅是可以有紧凑的表示,用直方图来表示一个patch也可以更加抗噪,一个gradient可能会有噪音,但是用直方图来表示后就不会对噪音那么敏感了。

对于64*128的这幅patch来说,8*8的网格已经足够大来表示有趣的特征比如脸,头等等。

直方图基本上是对应于角度0,20,40,60 ...... 160的9个区间(数字)的矢量(或阵列)。

下图显示了每个8*8的cell的梯度的显示:

中间: 一个网格用箭头表示梯度 右边: 这个网格用数字表示的梯度

中间这个图的箭头是梯度的方向,长度是梯度的大小,可以发现箭头的指向方向是像素强度都变化方向,幅值是强度变化的大小。

右边的梯度方向矩阵中可以看到角度是0-180度,不是0-360度,这种被称之为"无符号"梯度("unsigned" gradients)因为一个梯度和它的负数是用同一个数字表示的,也就是说一个梯度的箭头以及它旋转180度之后的箭头方向被认为是一样的。那为什么不用0-360度的表示呢?在事件中发现unsigned gradients比signed gradients在行人检测任务中效果更好。一些HOG的实现中可以让你指定signed gradients。

下边是在这些8×8单元格中创建梯度直方图。直方图包含对应于角度0,20,40 ...... 160的9个区间。

下面这张图解释了这个过程。我们用了上一张图里面的那个网格的梯度幅值和方向。根据方向选择用哪个bin, 根据副值来确定这个bin的大小。先来看蓝色圈圈出来的像素点,它的角度是80,副值是2,所以它在第五个bin里面加了2,再来看红色的圈圈出来的像素点,它的角度是10,副值是4,因为角度10介于0-20度的中间(正好一半),所以把幅值一分为二地放到0和20两个bin里面去。

还有一个细节需要注意。如果角度大于160度,则介于160和180之间,我们知道角度0和180是一样的。因此,在下面的示例中,角度为165度的像素与0度箱和160度箱成比例。

这里按照比例,我自己的理解的计算:

bin为160的值:(1-(165-160)/20)*85

bin为0(180)的值:85*(165-160)

把这8*8的cell里面所有的像素点都分别加到这9个bin里面去,就构建了一个9-bin的直方图,上面的网格对应的直方图如下:

这里,在我们的表示中,Y轴是0度(从上往下)。你可以看到有很多值分布在0,180的bin里面,这其实也就是说明这个网格中的梯度方向很多都是要么朝上,要么朝下。

注:y轴是零度的解释——梯度是x方向的梯度处于y方向的梯度,y轴,则x没有变化,所以分子为零,所以梯度为零。

(4)16×16块归一化

在上一步中,我们创建了图像的方向梯度直方图。图像的梯度对整体照明敏感。如果通过将所有像素值除以2来使图像变暗,则梯度幅度将改变一半,因此直方图值将改变一半。理想情况下,我们希望描述符独立于光照变化。换句话说,我们希望“归一化”直方图,使它们不受光照变化的影响。

在解释直方图是如何规范化之前,让我们看看长度为3的向量是如何规范化的。

假设我们有一个RGB颜色矢量[128,64,32]。这个向量的长度是

这也称为向量的L2范数。将该向量的每个元素除以146.64得到归一化向量[0.87,0.43,0.22]。

现在考虑另一个向量,其中元素是第一个向量2 x [128,64,32] = [256,128,64]的值的两倍。归一化[256,128,64],得到归一化向量[0.87,0.43,0.22],这与原始RGB矢量的标准化版本相同。您可以看到归一化矢量会删除比例。

现在我们知道如何规范化矢量,你可能会想到在计算HOG时你可以简单地将9×1直方图归一化,就像我们对上面的3×1矢量进行归一化一样。这不是一个坏主意,但更好的想法是在更大尺寸的16×16块上进行标准化。16×16块具有4个直方图,它们可以连接形成36×1元素向量,并且可以按照3×1向量归一化的方式进行归一化。然后将窗口移动8个像素(参见如下动画),并在该窗口上计算归一化的36×1向量,并重复该过程。

(5)计算HOG特征向量

为了计算整个图像块的最终特征向量,将36×1向量连接成一个巨型向量。这个载体的大小是多少?让我们计算一下

  1. 我们有16×16块的多少个位置?有7个水平位置和15个垂直位置,总共有7 x 15 = 105个位置。

  2. 每个16×16块由36×1向量表示。因此,当我们将它们全部连接成一个gaint向量时,我们获得36×105 = 3780维向量。

(6)可视化HOG

通常HOG特征描述子是画出8*8网格中9*1归一化的直方图,见下图。你可以发现直方图的主要方向捕捉了这个人的外形,特别是躯干和腿。

MATLAB可视化HOG特征:

img = imread('1.png'); 
[featureVector,hogVisualization] = extractHOGFeatures(img); 
figure;imshow(img); 
hold on;
plot(hogVisualization);

参考:https://www.learnopencv.com/histogram-of-oriented-gradients/

END

加群交流

欢迎加入CV联盟群获取CV和ML等领域前沿资讯

扫描添加CV联盟微信拉你进群,备注:CV联盟

热文荐读

重磅!中国人工智能学会2019年度优秀博士学位论文终评名单公示

上海交通大学“土味”招生视频~闪瞎双眼--让你笑出猪叫...

人工智能领域的黄埔军校--中国科学技术大学!(科大讯飞、商汤、寒武纪、云从科技...)

CVPR 33篇:腾讯AI Lab实验室带你解读六大前沿方向!

【收藏】深度学习模型大合集-GitHub标星5K+趋势榜第一

点个在看支持一下吧

  • 5
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值