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

news2025/1/11 8:58:22

『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 plt

def drawHOG(image, descriptors, cx, cy, rad):
    angles = np.arange(0, 180, 22.5).astype(np.float32)  # start, stop, step
    normGrad = 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 image

if __name__ == '__main__':
    # (1) 读取样本图像,构造样本图像集合
    img = cv.imread("../images/Fig1101.png", flags=0)  # 灰度图像
    height, width, wCell, d = 200, 200, 20, 10
    img = cv.resize(img, (width, height))  # 调整为统一尺寸

    # (2) 构造 HOG 检测器
    winSize = (20, 20)
    blockSize = (20, 20)
    blockStride = (20, 20)
    cellSize = (20, 20)
    nbins = 8
    hog = 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 轴梯度 Gx
    Gy = cv.Sobel(img, cv.CV_32F, 0, 1, ksize=5)  # Y 轴梯度 Gy
    magG, 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+d
            rect = ((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*j
            cell = 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)  # 绘制 block
    plt.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)  # 绘制 block
    plt.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.coloradmin.cn/o/25083.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

07-HTTPS双向认证及Java案例

1.双向认证流程 客户端发起建立HTTPS连接请求,将SSL协议版本的信息发送给服务端;服务器端将本机的公钥证书(server.crt)发送给客户端;客户端读取公钥证书(server.crt),取出了服务端公…

wordpress的手工迁移

我的场景 将某个在阿里云服务器(windows操作系统)上apache容器下的wordpress服务迁移到另一个linux主机上的apache上。 迁移要点 1、迁移源主机下的wordpress文件夹,在apache容器下的htdocs文件夹中 2、迁移数据库 3、根据目标&#xff0…

表弟大学毕业要学前端,我给他制定了一份亲属自学计划

表弟也终于到了马上要大学毕业的时间,然后听说我在做前端开发工作,就想着能不能和我一起搞一搞。 我说这又不是小时候一起去地里抓兔子,说走就一起走,拿上工具一起走了,这得学啊。看着表弟期待的眼神,他问了…

Scientific Reports|比较转录组分析揭示了杀菌剂氰烯菌酯对尖孢镰刀菌的抗性调控机制和杀菌活性

TITLE:Comparative transcriptome analysis reveals the resistance regulation mechanism and fungicidal activity of the fungicide phenamacril in Fusarium oxysporum 译名:比较转录组分析揭示了杀菌剂氰烯菌酯对尖孢镰刀菌的抗性调控机制和杀菌活性…

Java代码审计——文件操作漏洞

目录 (一)、 文件操作漏洞简介 (二) 、漏洞发现与修复案例 2.1 文件包含漏洞 2.2 文件上传漏洞 (三) 文件下载/读取漏洞 (四).文件写入漏洞 (五&…

Arcgis建筑面shp由DSM和DEM获取高度拉伸并可视化

效果 1、准备数据 DEM、DSM数据精度尽量高一些 1)DEM 2)DSM 3)建筑shp 所有数据坐标统一,而且加载后位置能对上,DEM和DSM具有相同的像元大小 2、准备数据前的一些操作 1)矢量shp裁剪

C#实现最大公约数和最小公倍数

最大公约数: 最大公因数,也称最大公约数、最大公因子,指两个或多个整数共有约数中最大的一个。a,b的最大公约数记为(a,b),同样的,a,b,c的最大公约…

net.sf.json.JSONObject 类的日常使用,非阿里巴巴的JSONObject,附上作者的jsonDemo

文章目录Json介绍作者的Demo项目地址常见的转化使用测试json的添加属性,打印bean与json互转deepBean与json互转list与json互转map与json互转demo所用到的实体类StudentGrade个人使用的依赖常用方法其他参考文档Json介绍 1、JSONObject只是一种数据结构,可…

DJYGUI系列文章七:GDD窗口系统

目录 1 窗口分类及关系 2 窗口的客户区与非客户区 3 坐标系统 4 窗口句柄与窗口ID的作用与区别 5 窗口的关闭、销毁、退出过程 6 API说明 6.1 ScreenToClient: 屏幕坐标转换为客户区坐标 6.2 ClientToScreen: 客户区坐标转换为屏幕坐标 6.3 Scre…

linux篇【11】:linux下的线程

目录 一.linux下的线程 1.linux下的线程概念 (1)教材上粗略的 线程 定义 (2)线程的引入 (3)线程真正定义 以及 示意图 (4)linux 和 windows等其他操作系统的线程对比 2.重新定…

22-python异常

异常一. 了解异常二. 异常的写法2.1 语法2.2 快速体验2.3 捕获指定异常2.3.1 语法2.3.2 体验2.3.3 捕获多个指定异常2.3.4 捕获异常描述信息2.3.5 捕获所有异常2.4 异常的else2.5 异常的finally三. 异常的传递四. 自定义异常五. 总结一. 了解异常 当检测到一个错误时&#xff…

Hibernate多表的关联关系、懒加载

一、一对多关系:插入: “一”的一方为主表,“多”的一方为副表,主表关联副表,应该在主表中加入副表对象作为属性。 根据顾客ID插入顾客信息 (一) ,同时将顾客名下所有订单插入 &…

Python实现人脸识别检测,对主播进行颜值排行

前言 嗨嗨,我亲爱的家人们 今天来整点不一样的,嘿嘿 用Python简单实现对人脸识别的检测,对某平台主播照片进行评分排名 应该对女主播这个词不陌生吧,怎么说应该还是蛮多人看过一些女主播吧 我无聊的时候也会看看,…

2009年数学二真题复盘

选择题: 间断点的判断的前置芝士: 间断点的定义 设函数f(x)在点的去心领域内有定义,若f(x)满足以下条件之一: 在x=没有定义在x=有定义,但是不存在,或者存在,但是极限值不等于函数值。 类型定义 相关概念第一类间断点

CMS垃圾回收器

概述 CMS(Concurrent Mark-Sweep)是以牺牲吞吐量为代价来获得最短回收停顿时间的垃圾回收器。对于要求服务器响应速度的应用上,这种垃圾回收器非常适合。在启动JVM参数加上-XX:UseConcMarkSweepGC,这个参数表示对于老年代的回收采用CMS。CMS采用的基础算…

SpringBoot SpringBoot 开发实用篇 5 整合第三方技术 5.13 j2cache 相关配置

SpringBoot 【黑马程序员SpringBoot2全套视频教程,springboot零基础到项目实战(spring boot2完整版)】 SpringBoot 开发实用篇 文章目录SpringBootSpringBoot 开发实用篇5 整合第三方技术5.13 j2cache 相关配置5.13.1 j2cache 相关配置5.13…

直播绿幕抠图的例子(绿幕抠图直播实例参考)

阿酷TONY / 2022-11-21 / 长沙 什么是绿幕抠图: 设定绿幕或绿布,做直播软件抠图,这时绿幕绿布就可以被实时的抠掉,绿色就变成透明了,只剩下绿幕外的人物,此时添加上直播的背景画质,就实现了绿…

Git——Git常用命令

目录 常用命令概览 1. 设置用户签名 2. 初始化本地库 2.1 初始化本地库 2.2 查看文件 2.3 查看隐藏文件 2.4 进入到下一个目录 3. 查看本地库状态 4.添加暂存区 4.1 删除文件 5. 提交本地库 5.1 将暂存区的文件提交到本地库 6. 查看版本信息的命令 7.修改文件 8. 历史版本…

【Python入门指北】服务器信息清洗

服务器信息清洗 文章目录服务器信息清洗一、 subprocess 执行本机命令二、 获取服务器的硬件基础信息1. 基础信息2. 厂家和产品信息3. CPU 信息3.1 查看物理CPU型号3.2 查看物理CPU颗数3.3 查看每颗物理 CPU 的核心数4. 内存信息练习内存处理参考代码一、 subprocess 执行本机命…

智云通CRM:如何提前识别哪些客户爱说“不”?

有人说,做业务是最好的锻炼意志力方法,因为做业务的人经常会被客户拒绝甚至会扫地出门。被拒绝时,业务员一定要擦亮眼睛,善于察言观色,洞察客户的心理活动。透过观察了解客户为什么说“不”,客户拒绝情况有…