特征描述子(Feature Descriptor)

特征描述子就是图像的表示,抽取了有用的信息,丢掉了不相关的信息。通常特征描述子会把一个w*h*3(宽高3,3个channel)的图像转换成一个长度为n的向量/矩阵。比如一副64*128*3的图像,经过转换后输出的图像向量长度可以是3780。

什么样子的特征是有用的呢?假设我们想要预测一张图片里面衣服上面的扣子,扣子通常是圆的,而且上面有几个洞,那你就可以用边缘检测(edge detector),把图片变成只有边缘的图像,然后就可以很容易的分辨了,那么对于这张图边缘信息就是有用的,颜色信息就是没有用的。而且好的特征应该能够区分纽扣和其它圆形的东西的区别。

方向梯度直方图(HOG)中,梯度的方向分布被用作特征。沿着一张图片X和Y轴的方向上的梯度是很有用的,因为在边缘和角点的梯度值是很大的,我们知道边缘和角点包含了很多物体的形状信息。

(HOG特征描述子可以不局限于一个长度,也可以用很多其他的长度,这里只记录一种计算方法。)

怎么计算方向梯度直方图呢?

我们会先用图像的一个patch来解释。

第一步:预处理

Patch可以是任意的尺寸,但是有一个固定的比例,比如当patch长宽比1:2,那patch大小可以是100*200, 128*256或者1000*2000但不可以是101*205。

这里有张图是720*475的,我们选100*200大小的patch来计算HOG特征,把这个patch从图片里面抠出来,然后再把大小调整成64*128。

hog_preprocess

第二步:计算梯度图像

首先我们计算水平和垂直方向的梯度,再来计算梯度的直方图。可以用下面的两个kernel来计算,也可以直接用OpenCV里面的kernel大小为1的Sobel算子来计算。

horizontal_vertical_gradient_kernel

调用OpenCV代码如下:

// 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 imageim = 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)

接着,用下面的公式来计算梯度的幅值g和方向theta:

gradient_direction_formula

可以用OpenCV的cartToPolar函数来计算:

// C++ Calculate gradient magnitude and direction (in degrees)
Mat mag, angle;
cartToPolar(gx, gy, mag, angle, 1);
# Python Calculate gradient magnitude and direction ( in degrees )
mag, angle = cv2.cartToPolar(gx, gy, angleInDegrees=True)

计算得到的gradient图如下:

左边:x轴的梯度绝对值 中间:y轴的梯度绝对值 右边:梯度幅值

从上面的图像中可以看到x轴方向的梯度主要凸显了垂直方向的线条,y轴方向的梯度凸显了水平方向的梯度,梯度幅值凸显了像素值有剧烈变化的地方。(注意:图像的原点是图片的左上角,x轴是水平的,y轴是垂直的)

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

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

第三步:在8*8的网格中计算梯度直方图

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

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

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

直方图是有9个bin的向量,代表的是角度0,20,40,60.....160。

我们先来看看每个8*8的cell的梯度都是什么样子:

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

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

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

下一步就是为这些8*8的网格创建直方图,直方图包含了9个bin来对应0,20,40,...160这些角度。

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

梯度直方图

这里有个细节要注意,如果一个角度大于160度,也就是在160-180度之间,我们知道这里角度0,180度是一样的,所以在下面这个例子里,像素的角度为165度的时候,要把幅值按照比例放到0和160的bin里面去。

角度大于160的情况

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

8*8网格直方图

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

第四步: 16*16块归一化

上面的步骤中,我们创建了基于图片的梯度直方图,但是一个图片的梯度对于整张图片的光线会很敏感。如果你把所有的像素点都除以2,那么梯度的幅值也会减半,那么直方图里面的值也会减半,所以这样并不能消除光线的影响。所以理想情况下,我们希望我们的特征描述子可以和光线变换无关,所以我们就想让我们的直方图归一化从而不受光线变化影响。

先考虑对向量用l2归一化的步骤是:
v = [128, 64, 32]
[(128^2) + (64^2) + (32^2) ]^0.5=146.64
把v中每一个元素除以146.64得到[0.87,0.43,0.22]
考虑另一个向量2*v,归一化后可以得到向量依旧是[0.87, 0.43, 0.22]。你可以明白归一化是把scale给移除了。

你也许想到直接在我们得到的9*1的直方图上面做归一化,这也可以,但是更好的方法是从一个16*16的块上做归一化,也就是4个9*1的直方图组合成一个36*1的向量,然后做归一化,接着,窗口再朝后面挪8个像素(看动图)。重复这个过程把整张图遍历一遍。

hog-16x16-block-normalization

第五步:计算HOG特征向量

为了计算这整个patch的特征向量,需要把36*1的向量全部合并组成一个巨大的向量。向量的大小可以这么计算:

  1. 我们有多少个16*16的块?水平7个,垂直15个,总共有7*15=105次移动。

  2. 每个16*16的块代表了36*1的向量。所以把他们放在一起也就是36*105=3780维向量。

可视化HOG

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

visualizing_histogram

====================================分割线================================

本文作者:思颖

本文转自雷锋网禁止二次转载,原文链接

图像学习之如何理解方向梯度直方图(Histogram Of Gradient)相关推荐

  1. 图像学习之如何理解方向梯度直方图HOG(Histogram Of Gradient)

    本文转自:雷锋网,作者:思颖.连接:https://yq.aliyun.com/articles/176607,https://www.leiphone.com/news/201708/ZKsGd2J ...

  2. OpenCV学习之六: 使用方向梯度直方图估计图像旋转角度

    OpenCV学习之六: 使用方向梯度直方图估计图像旋转角度 原文:http://blog.csdn.net/zhjm07054115/article/details/26964275 下面的代码通过计 ...

  3. OpenCV 使用方向梯度直方图估计图像旋转角度

    人工智能研究网  www.studyai.cn 下面的代码通过计算图像中给定区域的方向梯度直方图来估计图像的旋转角度 主要内容包括: 一.计算局部图像块方向梯度直方图的函数 二.把给定图像按照给定的角 ...

  4. Histogram of Oriented Gridients(HOG) 方向梯度直方图

    from: Histogram of Oriented Gridients(HOG) 方向梯度直方图 Histogram of Oriented Gridients,缩写为HOG,是目前计算机视觉.模 ...

  5. 【计算机视觉】Histogram of Oriented Gridients(HOG) 方向梯度直方图

    Histogram of Oriented Gridients(HOG) 方向梯度直方图 Histogram of Oriented Gridients,缩写为HOG,是目前计算机视觉.模式识别领域很 ...

  6. 深度学习----CNN的图像学习之HOG(方向梯度直方图)详解

    一.原理 二.参数的理解 2.1.灰度值 2.2.归一化 2.3.细胞 2.4.窗口 2.5.类型 2.6.Gamma标准化 2.7.图像梯度及梯度算子 2.8.直方图 2.9.高斯空域加窗 三.步骤 ...

  7. 【图像特征提取1】方向梯度直方图HOG---从理论到实践------附带积分图像的解析

    (一)特征检测算法的综述 计算机视觉理论中的特征描述是常见的目标分析技术之一,关键点的检测和关键点的提取是目标分析的重要手段和重要步骤之一.局部图像特征描述的核心问题是不变性和可分析性,不变性是基于特 ...

  8. 图像特征提取算法:方向梯度直方图HOG

    1.基本介绍 HOG,全称是方向梯度直方图(Histogram Of Gradient),是目前计算机视觉.模式识别领域很常用的一种描述图像局部纹理的特征.这个特征名字起的也很直白,就是说先计算图片某 ...

  9. 图像特征:方向梯度直方图 HOG

    文章目录 参考资料 简介 算法流程 灰度化和gamma校正 计算梯度 统计cell的梯度方向直方图 Block 块内归一化(重点) 组合为HOG特征 HOG特征与可视化 OpenCV 算法实现 参考资 ...

最新文章

  1. 关于ajax访问本地json文件报错404的问题
  2. UA STAT687 线性模型II 最小二乘理论3 广义最小二乘
  3. Kubernetes存储之Secret
  4. go和python计算字节数组sha1
  5. cli2弃用了吗 vue_vue-cli 3 和 vue-cli 2的区别
  6. 《ASP.NET Core 微服务实战》-- 读书笔记(第1章 、第2章)
  7. Keras 学习笔记
  8. c#2.0语法新关键字 partial
  9. 使用Java语言借助Quartz jar包实现定时器的方法
  10. 发电机机房设计规范_柴油发电机房设计规范.docx
  11. 0基础入门VTD-实操静态道路建模4
  12. 新疆职称英语和职称计算机,职称计算机考试题库
  13. 搜狗站群排名优化之搜狗批量推送工具
  14. 张亮:Sharding-Sphere成长记
  15. 洛谷 P3987 我永远喜欢珂朵莉~(Splay+BIT+无限卡常)
  16. 图像压缩-《Learned Image Compression with Discretized Gaussian Mixture Likelihoods and Attention Modules》
  17. php代码访问记录系统,对某PHP发卡系统代码审计记录
  18. Exchange Server2010系列之六:监控用户邮件
  19. Linux 配置本地域名项目
  20. android5.0+电视,当Android 5.0搭载在电视上,是一种怎样的体验?

热门文章

  1. android wait函数使用,Android Sleep/Wait/Delay函数
  2. #SpringMVC:转发、重定向(关键字方式) #forward、redirect关键字 @FDDLC
  3. 计算机内存存取时间和存储周期,在计算机中什么是内存存取时间和存储周期?...
  4. UE4 UE4 C++ Gameplay Abilities 的AttributeSet和GameplayEffect
  5. 京沪高铁沪宁城铁昆山南站效果图
  6. 医疗信息系统等保定级备案教程
  7. 【正点原子FPGA连载】第三十二章RTC实时时钟LCD显示实验 -摘自【正点原子】新起点之FPGA开发指南_V2.1
  8. 1000日本版式设计速查手册
  9. 教育硕士专业学位(教育管理)研究生阅读书目或期刊目录
  10. Python遥感图像处理基础篇(二):arcpy遥感图像裁剪批量处理