【OpenCV 例程 300篇】248. 特征描述之HOG描述符

news/2024/5/22 11:17:22/文章来源:https://blog.csdn.net/youcans/article/details/127970587

『youcans 的 OpenCV 例程300篇 - 总目录』


【youcans 的 OpenCV 例程 300篇】248. 特征描述之HOG描述符


1. 方向梯度直方图

方向梯度直方图(Histogram of Oriented Gradient, HOG)使用梯度方向的分布作为特征来构造描述符,应用非常广泛。
梯度的幅值是边缘和角点检测的基础,梯度的方向也包含着丰富的图像特征。HOG的基本思想,就是图像的局部特征可以用梯度幅值和方向的分布描述。HOG的基本方法是,将图像划分成多个单元格,计算单元格的方向梯度直方图,把每个单元格的直方图连接起来构造为HOG特征向量。
HOG描述符的向量维数不是固定不变的,取决于检测图像大小和单元格的大小。HOG描述符不具有尺度和旋转不变性,但具有有良好的几何和光学不变性,特别适合人体检测。

在这里插入图片描述


2. OpenCV 的 HOGDescriptor 类

OpenCV提供了cv::HOGDescriptor类实现HOG描述符。在Python语言中,OpenCV提供了HOG类的接口函数cv.HOGDescriptor。

函数原型

cv.HOGDescriptor(_winSize, _blockSize, _blockStride, _cellSize, _nbins) → retval
hog.compute(img[, _winStride=Size(), _padding=Size()]) → descriptors

参数说明
 winSize:检测窗口大小,形如(w,h)的元组,默认值(64,128)。
 blockSize:子块的大小,形如(w,h)的元组,默认值(16,16)。
 blockStride:子块的滑动步长,形如(w,h)的元组,默认值(8,8)。
 cellSize:单元格大小,形如(w,h)的元组,默认值(8,8)。
 nbins:直方图的条数,整数,默认值9。
 img:输入图像,单通道,数据类型CV_8U。
 winStride:窗口大小,可选项,必须是blockStride的整数倍。
 descriptors:HOG描述符,形为(lenHOG,)的Numpy 数组,数据类型CV_32F。

函数说明
⑴ 计算每个单元格cell的HOG:方向梯度的取值范围0~180度,等分为nbins个区间,单元格像素的梯度方向分配到nbins个扇形区间,累加每个区间内的像素数,得到nbins位的HOG向量。
⑵ 构造子块block的HOG:多个单元格cell组合为子块,子块的HOG描述符就是多个单元格HOG向量的串联,长度为nbins*blockSize/cellSize。
⑶ 整个检测窗口的HOG:子块block以步长blockStride在检测窗口内滑动,遍历检测窗口,检测窗口的HOG就是每个子块block的HOG的串联。
因此,检测窗口的HOG的向量维数是:

lenHOG = nbins * (blockSize[0]/cellSize[0]) * (blockSize[1]/cellSize[1])
* ((winSize[0]-blockSize[0])/blockStride[0] + 1)
* ((winSize[1]-blockSize[1])/blockStride[1] + 1)

注意问题

  • ⑴ 函数cv.HOGDescriptor实例化HOGDescriptor类,定义一个HOGDescriptor类对象。成员函数hog.compute计算给定图像的HOG描述符。
# 构造 HOG 检测器
winSize = (40, 40)
blockSize = (20, 20)
blockStride = (10, 10)
cellSize = (10, 10)
nbins = 8
hog = cv.HOGDescriptor(winSize, blockSize, blockStride, cellSize, nbins)
# hog = cv.HOGDescriptor(_winSize=(40,40), _blockSize=(20,20), 
#      _blockStride=(10,10), _cellSize=(10,10), _nbins=8)
  • ⑵ 检测窗口大小winSize是子块大小blockSize的整数倍,子块大小blockSize是单元格大小cellSize的整数倍,子块大小blockSize是滑动步长blockStride的整数倍。
  • ⑶ 函数中方向梯度的取值范围是0~180度,而不是0~360度。
  • ⑷ cv::HOGDescriptor类的功能丰富,参数和成员函数很多,例如可以实现尺度不变性检测。更多使用方法可以参见OpenCV官方文档 【链接1 】。

3. 例程:特征描述之HOG描述符

本例程示例HOG描述符的使用。为了便于解释HOG原理和绘图,例程中将检测窗口、子块和单元格设为相同的尺寸,实际应用时可以参考函数默认值来设置。

# 【1609】特征描述之 HOG 描述符
import cv2 as cv
import numpy as np
from matplotlib import pyplot as pltdef drawHOG(image, descriptors, cx, cy, rad):angles = np.arange(0, 180, 22.5).astype(np.float32)  # start, stop, stepnormGrad = descriptors/np.max(descriptors).astype(np.float32)gx, gy = cv.polarToCart(normGrad*rad, angles, angleInDegrees=True)for i in range(angles.shape[0]):px, py = int(cx+gx[i]), int(cy+gy[i])cv.arrowedLine(image, (cx,cy), (px, py), 0, tipLength=0.1)  # 黑色return imageif __name__ == '__main__':# (1) 读取样本图像,构造样本图像集合img = cv.imread("../images/Fig1101.png", flags=0)  # 灰度图像height, width, wCell, d = 200, 200, 20, 10img = cv.resize(img, (width, height))  # 调整为统一尺寸# (2) 构造 HOG 检测器winSize = (20, 20)blockSize = (20, 20)blockStride = (20, 20)cellSize = (20, 20)nbins = 8hog = cv.HOGDescriptor(winSize, blockSize, blockStride, cellSize, nbins)lenHOG = nbins * (blockSize[0]/cellSize[0]) * (blockSize[1]/cellSize[1]) \* ((winSize[0]-blockSize[0])/blockStride[0] + 1) \* ((winSize[1]-blockSize[1])/blockStride[1] + 1)print("length of descriptors:", lenHOG)# (3) 计算检测区域的 HOG 描述符xt, yt = 80, 80  # 检测区域位置cell = img[xt:xt+wCell, yt:yt+wCell]cellDes = hog.compute(cell)  # HOG 描述符,(8,)normGrad = cellDes/np.max(cellDes).astype(np.float32)print("shape of descriptors:{}".format(cellDes.shape))print(cellDes)# (4) 绘制方向梯度示意图imgGrad = cv.resize(cell, (wCell*10, wCell*10), interpolation=cv.INTER_AREA)Gx = cv.Sobel(img, cv.CV_32F, 1, 0, ksize=5)  # X 轴梯度 GxGy = cv.Sobel(img, cv.CV_32F, 0, 1, ksize=5)  # Y 轴梯度 GymagG, angG = cv.cartToPolar(Gx, Gy, angleInDegrees=True)  # 极坐标求幅值与方向 (0~360)print(magG.min(), magG.max(), angG.min(), angG.max())angCell = angG[xt:xt+wCell, yt:yt+wCell]box = np.zeros((4, 2), np.int32)  # 计算旋转矩形的顶点, (4, 2)for i in range(wCell):for j in range(wCell):cx, cy = i*10+d, j*10+drect = ((cx,cy), (8,1), angCell[i,j])  # 旋转矩形类box = np.int32(cv.boxPoints(rect))  # 计算旋转矩形的顶点, (4, 2)cv.drawContours(imgGrad, [box], 0, (0,0,0), -1)# (5) 绘制检测区域的方向梯度直方图cellHOG = np.ones((201,201), np.uint8)  # 白色cellHOG = drawHOG(cellHOG, cellDes, xt+d, yt+d, 40)# (6) 绘制图像的方向梯度直方图imgHOG = np.ones(img.shape, np.uint8)*255  # 白色for i in range(10):for j in range(10):xc, yc = 20*i, 20*jcell = img[xc:xc+wCell, yc:yc+wCell]descriptors = hog.compute(cell)  # HOG 描述符,(8,)imgHOG = drawHOG(imgHOG, descriptors, xc+d, yc+d, 8)imgWeight = cv.addWeighted(img, 0.5, imgHOG, 0.5, 0)plt.figure(figsize=(9, 6.2))plt.subplot(231), plt.title("1. Original")cv.rectangle(img, (xt,yt), (xt+wCell,yt+wCell), (0,0,0), 2)  # 绘制 blockplt.axis('off'), plt.imshow(img, cmap='gray')plt.subplot(232), plt.title("2. Oriented gradient")angNorm = np.uint8(cv.normalize(angG, None, 0, 255, cv.NORM_MINMAX))plt.axis('off'), plt.imshow(angNorm, cmap='gray')plt.subplot(233), plt.title("3. Image with HOG")cv.rectangle(imgWeight, (xt,yt), (xt+wCell,yt+wCell), (0,0,0), 2)  # 绘制 blockplt.axis('off'), plt.imshow(imgWeight, cmap='gray')plt.subplot(234), plt.title("4. Grad angle of cell")plt.axis('off'), plt.imshow(imgGrad, cmap='gray')plt.subplot(235), plt.title("5. HOG of cell")strAng = ("0", "22", "45", "67", "90", "112", "135", "157")plt.bar(strAng, cellDes*wCell*wCell)plt.subplot(236), plt.title("6. HOG diagram of cell")plt.axis('off'), plt.imshow(cellHOG, cmap='gray')
plt.tight_layout()
plt.show()

在这里插入图片描述

程序说明:

  • ⑴ 子图1是原始图像,图中黑色方框是一个单元格cell。子图2是原始图像的梯度方向图,像素值的大小反映梯度方向的角度。
  • ⑵ 子图4是子图1中方框位置单元格cell的梯度方向图,图中的线段表示像素点的梯度方向。注意例程中梯度方向的范围是0~180度。
  • ⑶ 子图5是对子图4单元格中的所有像素点,按8个方向区间绘制的方向梯度直方图。子图6是子图5的单元格方向梯度直方图的空间矢量表示。
  • ⑷ 子图3是整个图像的可视化方向梯度直方图.将图像划分为10*10个单元格,计算每个单元格的HOG,表示为如子图6的空间矢量形式。
  • ⑸ 虽然例程给出了HOG处理过程和结果的各种图像,这是为了便于理解HOG的思路和计算步骤。在实际应用中,检测图像的HOG是维数为lenHOG的特征向量,而不是二维图像。


在这里插入图片描述

参考文献:Navneet Dalal, Bill Triggs. Histograms of oriented gradients for human detection. In Computer Vision and Pattern Recognition, 2005. CVPR 2005. IEEE Computer Society Conference on, volume 1, pages 886–893. IEEE, 2005.

【本节完】

版权声明:
youcans@xupt 原创作品,转载必须标注原文链接:(https://blog.csdn.net/youcans/article/details/127970587)
Copyright 2022 youcans, XUPT
Crated:2022-11-20

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_224326.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

十万部冷知识:“澳大利亚”为什么属于亚洲球队?

在2022年卡塔尔世界杯上,总共有6支球队入围,他们分别是日本队,韩国队,沙特队,伊朗队,澳大利亚队,还有就是东道主卡塔尔队。但是我们知道,澳大利亚,并不是亚洲的国家&…

前端面试题(JS部分)

目录一, 数据类型1,什么是引用类型,值类型?2,哪些值类型3,哪些引用类型4,判断数据类型5,typeof判断6,instanceof7,construtor二,浅拷贝 / 深拷贝1…

在阿里云 ACK 上部署 EMQX MQTT 服务器集群

云进入以「应用为中心」的云原生阶段,Operator 模式的出现,则为 Kubernetes 中的自动化任务创建配置与管理提供了一套行之有效的标准规范。通过将运维知识固化成高级语言 Go/Java 代码,使得运维知识可以像普通软件一样交付,并能支…

Jmeter的使用说明

一、安装Jmeter工具 链接:https://pan.baidu.com/s/1ZYc15eq9DO-r0ChKHxMXlg?pwdckcd 提取码:ckcd --来自百度网盘超级会员V5的分享二、Jmeter的常用元器件说明 jmeter八大元件件:取样器,前置处理器,后置处理器&a…

MySQL的高阶学习:索引、B+树

1.索引 索引是一种数据结构,如果没有索引,查找一个数据就需要从第一页开始全局检索直至找到需要的数据,有了索引可以先在目录中根据拼音查找到该数据所在的页数,因此通过索引可以大大减少了查询时间。 索引有两种存储类型&#xf…

汽车安全气囊设计?Abaqus/Part特殊建模方法-附案例step-by-step教学

作者 | 邓怡超 Abaqus/Part基于特征的建模功能可以说非常齐全,基本能够满足一般的分析要求,更复杂的模型则可以通过与专业三维建模软件之间的接口来导入,今天要说的是部件的另外一种建模方法。 有一种类型的分析,部件自身的初始…

Linux基础8 - 网络配置

Linux基础8 - 网络配置 一、网络连接的三种方式 Vmware为我们提供了三种网络工作模式,它们分别是:Bridged(桥接模式)、NAT(网络地址转换模式)、Host-Only(仅主机模式)。 1、桥接模式…

zabbix日志监控:操作系统、业务系统、文件大小、多行日志

zabbix日志监控:操作系统、业务系统、文件大小、多行日志 目录1 监控操作系统日志2 监控业务系统日志具体要求:分析:操作:3 监控日志文件大小(1)在被管主机当中安装agent(2)在以下za…

Activity、Fragment之间的传值

1、Activity和Activity之间传值 1、使用Intent 2、使用Intent结合Bundle IntentBundle 3、传自定义对象实现(实现Serialzable接口,性能较差,系统自动处理) 传自定义对象 4、传自定义对象(实现Parcelable,性能较好…

操作系统复习【面试】

操作系统复习【面试】前言推荐操作系统复习第一章 操作系统引论 11.3 操作系统的基本特性 141.3.1 并发1.3.2 共享1.3.3 虚拟1.3.4 异步1.4 操作系统的主要功能 171.4.1 处理机管理功能1.4.2 存储器管理功能1.4.3 设备管理功能1.4.4 文件管理功能1.4.5 操作系统和用户之间的接口…

MySQL Hash Join前世今生

GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源。GreatSQL是MySQL的国产分支版本,使用上与MySQL一致。作者:nw MySQL Hash Join前世今生 因工作需要,对MySQL Hash Join的内部实现做了一些探索和实践&#x…

内部类_Java

作者:爱塔居的博客_CSDN博客-JavaSE领域博主 专栏:JavaSE 文章目录 目录 文章目录 一、内部类的概念 二、内部类的分类 1.静态内部类(被static修饰) 2.非静态内部类 3.局部内部类 4.匿名内部类 一、内部类的概念 当一个事物…

【微服务解耦之事件启动】Spring Boot 解耦之事件驱动

一、前言 简介: 在项目实际开发过程中,我们有很多这样的业务场景:一个事务中处理完一个业务逻辑后需要跟着处理另外一个业务逻辑,伪码大致如下: Service public class ProductServiceImpl {...public void saveProdu…

ggplot2 | 世界杯赛程的可视化就交给我吧!~

11. 写在前面 昨天卡塔尔🇶🇦输了比赛真是让人大跌眼镜啊😱,打破了世界杯东道主必胜的神律,也不知道王子们是怎么想的。🤣 今天是英格兰🏴󠁧󠁢󠁥&#xe006e…

WebRTC Pacer

目录 一. 前言 二. WebRTC Pacer 1. 数据包传入Pacer模块的队列 2. Pacer模块取出队列的包发送 (1)什么时候取出数据包发送 (2)每次发送多少数据量 (3)避免引入较大延时的处理方法 一. 前言 实时音视…

Android Studio实现一个点餐系统

点餐系统作业要求效果登录注册欢迎页用户管理菜品种类管理菜品管理订单查询点餐后厨助手源码导读手把手编写注册、用户管理板块新建实体类User新建User服务新建注册活动用户管理作业要求 功能: 1.数据管理 菜品类别:凉菜;热菜&…

在裸机上输出Hello,world! [rCore-lab1]

引言 非常简单的“Hello, world”应用程序,实际上有着多层硬件和软件工具和支撑环境隐藏在它背后,才让我们不必付出那么多努力就能够创造出功能强大的应用程序。生成应用程序二进制执行代码所依赖的是以 编译器 为主的开发环境;运行应用程序执行码所依赖…

[附源码]计算机毕业设计JAVA基于web旅游网站的设计与实现

[附源码]计算机毕业设计JAVA基于web旅游网站的设计与实现 项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: …

Linux终端上传、下载文件命令 lrzsz

一、什么是lrzsz? lrzsz是一款在linux里可代替ftp上传和下载的程序。 二、为什么要用它? 一般来说我们自然是用不着的,上传下载ftp工具都很方便,前提是你账户拥有最高权限,但如果你不是ROOT,做创建删除上传…

【Spring Cloud实战】Spring Cloud Bus消息总线

gitee地址:https://gitee.com/javaxiaobear/spring-cloud_study.git 在线阅读地址:https://javaxiaobear.gitee.io/ 1、概述 Spring Cloud Bus将分布式系统的节点与轻量级消息代理链接。这可以用于广播状态更改(例如配置更改)或其…