【计算机视觉】CV实战项目 - 深入解析基于HOG+SVM的行人检测系统:Pedestrian Detection
深入解析基于HOG+SVM的行人检测系统:从理论到实践
- 技术核心:HOG+SVM检测框架
- HOG特征原理
- SVM分类器
- 项目架构与数据准备
- INRIA Person数据集
- 目录结构
- 实战指南:从零构建检测系统
- 环境配置
- 完整训练流程
- 检测应用
- 关键技术问题与解决方案
- 1. 难例挖掘不收敛
- 2. 小尺寸检测效果差
- 3. 实时性不足
- 4. 常见编译错误
- 性能评估与优化方向
- 基准测试结果
- 进阶优化方案
- 学术演进与相关研究
- 项目扩展建议
- 总结
行人检测是计算机视觉领域的经典问题,也是智能监控、自动驾驶等应用的基础技术。本文将全面剖析GitHub上的Pedestrian_Detection项目,这是一个基于HOG(方向梯度直方图)特征和SVM(支持向量机)分类器的传统行人检测实现。我们将从技术原理、实现细节、实战指南到优化方案,全方位解读这一经典视觉检测系统。
技术核心:HOG+SVM检测框架
HOG特征原理
方向梯度直方图(Histogram of Oriented Gradients)是由Navneet Dalal和Bill Triggs在2005年CVPR会议上提出的特征描述子(《Histograms of Oriented Gradients for Human Detection》)。其核心思想是:
- 图像预处理:将图像转换为灰度并做Gamma校正
- 梯度计算:使用[-1,0,1]和[-1,0,1]^T滤波器计算水平和垂直梯度
- 细胞单元划分:将图像划分为8×8像素的细胞单元
- 方向直方图统计:每个细胞计算9-bin的梯度方向直方图
- 块归一化:将2×2的细胞单元组合成块,进行L2-Hys归一化
- 特征向量拼接:将所有块的特征串联形成最终特征向量
对于64×128的检测窗口,最终得到的HOG特征维度为7×15×36=3780维。
SVM分类器
支持向量机通过寻找最大间隔超平面来实现分类:
min 1/2||w||² + C∑ξ_i
s.t. y_i(w·x_i + b) ≥ 1-ξ_i, ξ_i ≥ 0
本项目使用OpenCV实现的SVM,核函数选择线性核,通过hard negative mining提升分类性能。
项目架构与数据准备
INRIA Person数据集
项目使用的基准数据集包含:
- 正样本:614张包含行人的图片(2416个标注行人)
- 负样本:1218张不包含行人的场景图片
- 图像尺寸:原始正样本为96×160,处理后统一为64×128
目录结构
Pedestrian_Detection/
├── dataset/ # 数据存储
│ ├── pos/ # 正样本
│ ├── neg/ # 负样本
│ └── HardExample/ # 难例样本
├── include/
│ └── dataset.h # 参数配置文件
├── src/ # 源代码
├── SVM_HOG.xml # 训练好的模型
└── README.md
实战指南:从零构建检测系统
环境配置
基础环境要求:
- Ubuntu 16.04(兼容18.04/20.04)
- OpenCV 2.4.13(兼容3.x版本)
- CMake 3.5+
- g++ 5.4+
推荐安装步骤:
# 安装OpenCV(Ubuntu)
sudo apt-get install libopencv-dev# 验证安装
pkg-config --modversion opencv # 应显示2.4.13或更高
完整训练流程
- 数据准备
# 下载并解压数据集
wget ftp://ftp.inrialpes.fr/pub/lear/douze/data/INRIAPerson.tar
tar -xvf INRIAPerson.tar# 创建目录结构
mkdir -p dataset/{pos,neg,HardExample}# 复制正样本
cp INRIAPerson/96X160H96/Train/pos/* dataset/pos/
- 编译项目
# CMake方式
mkdir build && cd build
cmake ..
make -j4# 或直接g++编译
g++ -o CropImage src/crop_image.cpp $(pkg-config opencv --cflags --libs)
- 负样本生成
./CropImage
实现原理:从1218张负样本图中每张随机裁剪10个64×128的patch,共生成12180个负样本。
- 初始训练
// 修改dataset.h
#define TRAIN true // 启用训练模式
make && ./SvmTrainUseHog
生成初始模型SVM_HOG.xml
,此时检测效果较差(AP约50%)。
- 难例挖掘(Hard Negative Mining)
./GetHardExample
算法过程:
- 用初始模型扫描负样本图像
- 将误检(False Positive)保存为HardExample
- 本步骤通常增加2000-5000个难例样本
- 最终训练
ls dataset/HardExample/ > HardExample_FromINRIA_NegList.txt
// 修改dataset.h
#define HardExampleNO 2538 // 实际难例数量
make && ./SvmTrainUseHog
最终模型AP可提升至70-80%。
检测应用
图片检测:
./ImageDetect test.jpg
参数调整:
hitThreshold
:控制检测灵敏度winStride
:影响检测速度和漏检率scale
:多尺度检测参数
视频检测:
./VideoDetect input.mp4 --scale=1.05
关键技术问题与解决方案
1. 难例挖掘不收敛
现象:反复挖掘难例但性能提升有限
解决:
// 修改src/find_save_HardExample.cpp
double hitThreshold = -0.8; // 放宽初始阈值
// 增加最大难例数量限制
if(hardExamples.size() > 5000) break;
2. 小尺寸检测效果差
优化方案:
- 修改图像金字塔参数:
// 在image_detect.cpp中
vector<double> scales{1.0, 1.05, 1.1, 1.2}; // 更密集的尺度
- 使用积分图加速HOG计算
3. 实时性不足
优化手段:
// 视频检测时跳帧处理
if(frameCount % 3 != 0) continue;// 使用OpenCV并行框架
setUseOptimized(true);
setNumThreads(4);
4. 常见编译错误
错误1:undefined reference to cv::HOGDescriptor
解决:确保链接正确的OpenCV版本
g++ -o PeopleDetect src/peopledetect.cpp -lopencv_objdetect -lopencv_highgui
错误2:Assertion failed (size.width>0)
原因:图像路径错误或OpenCV未正确读取
排查:
Mat img = imread(path);
if(img.empty()) { cerr << "Error loading: " << path << endl;continue;
}
性能评估与优化方向
基准测试结果
方法 | 准确率 | 速度(FPS) | 内存占用 |
---|---|---|---|
初始HOG+SVM | 62.3% | 8.2 | 450MB |
加入难例挖掘 | 78.1% | 6.5 | 500MB |
OpenCV默认 | 65.7% | 10.1 | 400MB |
进阶优化方案
- 特征融合:
// 结合LBP特征
HOGDescriptor hog;
vector<float> hogFeatures;
hog.compute(img, hogFeatures);Mat lbpFeatures = computeLBP(img);
hconcat(hogFeatures, lbpFeatures, totalFeatures);
- DPM改进:
实现可变形部件模型(Deformable Part Model):
score(p) = ∑_{i=1}^n (w_i · φ(HOG(p_i)) - ∑_{i,j} d_ij(p_i,p_j)
- 深度学习迁移:
# 使用PyTorch微调HOG特征
class HOG_CNN(nn.Module):def __init__(self):super().__init__()self.hog = HOGLayer()self.cnn = nn.Sequential(...)def forward(self, x):hog = self.hog(x)return self.cnn(hog)
学术演进与相关研究
-
里程碑工作:
- 《Histograms of Oriented Gradients for Human Detection》(Dalal & Triggs, 2005 CVPR)
- 《Object Detection with Discriminatively Trained Part-Based Models》(Felzenszwalb et al., 2010 PAMI)
-
后续发展:
- 《Integral Histogram of Oriented Gradients for Human Detection》(Wang et al., 2016)
- 《Fast Human Detection Using a Cascade of Histograms of Oriented Gradients》(Zhu et al., 2006)
-
SVM优化:
- 《Training Linear SVMs in Linear Time》(Joachims, 2006)
- 《A Dual Coordinate Descent Method for Large-scale Linear SVM》(Hsieh et al., 2008)
项目扩展建议
-
现代改进方向:
- 实现HOG+CNN混合检测器
- 加入运动信息(光流)提升视频检测
- 开发嵌入式版本(树莓派/Jetson)
-
工程化优化:
- 添加Python接口
- 实现多尺度并行检测
- 开发Web服务API
-
算法增强:
- 集成非极大值抑制(NMS)
- 添加跟踪算法(如KCF)
- 实现遮挡处理机制
总结
Pedestrian_Detection项目展示了传统计算机视觉方法的精髓,通过HOG特征和SVM分类器的组合,配合难例挖掘等技巧,构建了完整的行人检测流水线。虽然深度学习方法已在精度上超越传统方法,但该项目的价值在于:
- 教学价值:清晰展示特征工程和机器学习结合的完整流程
- 计算效率:在资源受限环境中仍具优势
- 可解释性:比黑盒的深度学习更易分析和调试
对于希望深入理解计算机视觉底层原理的开发者,该项目是绝佳的学习素材,也为后续转向深度学习检测器(如YOLO、Faster R-CNN)奠定了坚实基础。
相关文章:

【计算机视觉】CV实战项目 - 深入解析基于HOG+SVM的行人检测系统:Pedestrian Detection
深入解析基于HOGSVM的行人检测系统:从理论到实践 技术核心:HOGSVM检测框架HOG特征原理SVM分类器 项目架构与数据准备INRIA Person数据集目录结构 实战指南:从零构建检测系统环境配置完整训练流程检测应用 关键技术问题与解决方案1. 难例挖掘不…...
如何借助全球动态IP实现多平台账号的批量注册?
无论是社交网络、在线购物平台还是专业应用软件,账号的创建和使用都是必不可少的。然而,在面对不同平台各自的注册限制和策略时,如何高效、安全且合法地进行账号批量注册成为了亟待解决的问题。本文将探讨全球动态IP在这一过程中的作用及其如…...

PR第二课--混剪
1.音乐打点 1.1 手动打点 按钮(如图),或者,快捷键M(如果在已有打点处,再次按M键会进入对标记点的设置界面,如下下图) 1.2 插件打点 一段音乐中,有明显的鼓点时,可以使用打点插件,快捷打点;如果鼓点不明显的话,最好还是手动打点,用插件打点会打出大量的标记点,…...

网页不同渲染方式的应对与反爬机制的处理——python爬虫
文章目录 写在前面爬虫习惯web 网页渲染方式服务器渲染客户端渲染 反爬机制使用session对象使用cookie让请求头信息更丰富使用代理和随机延迟 写在前面 本文是对前两篇文章所介绍的内容的补充,在了解前两篇文章——《爬虫入门与requests库的使用》和《BeautifulSou…...

高级电影感户外街拍人像摄影后期Lr调色教程,手机滤镜PS+Lightroom预设下载!
调色介绍 高级电影感户外街拍人像摄影后期 Lr 调色,是运用 Adobe Lightroom 软件,对户外街拍的人像照片进行后期处理,以塑造出具有电影质感的独特视觉效果。此调色过程借助 Lr 丰富的工具与功能,从色彩、光影、对比度等多维度着手…...
JAVA设计模式——(三)桥接模式
JAVA设计模式——(三)桥接模式(Bridge Pattern) 介绍理解实现武器抽象类武器实现类涂装颜色的行为接口具体颜色的行为实现让行为影响武器修改武器抽象类修改实现类 测试 适用性 介绍 将抽象和实现解耦,使两者可以独立…...
类加载器与jvm的内存
1. 类加载器与内存的关系 类加载器的字节码放在方法区(元空间)中,同时类加载器加载类后类的信息(成员变量、成员方法及修饰符等)存放在方法区中。类的信息所占内存的回收要同时满足两个条件:类的实例被回收…...
docker 配置代理
说明:该方法仅对 docker 程序本身拉取镜像的时候有效,对命令行无效。 docker 配置代理有 2 中方法 1.Daemon configuration 直接在 /etc/docker/daemon.json 文件中配置 {"proxies": {"http-proxy": "http://proxy.example.…...

【硬核干货】JetBrains AI Assistant 干货笔记
快进来抄作业,小编呕心沥血整理的 JetBrains AI Assistant 超干货笔记! 原文链接:【硬核干货】JetBrains AI Assistant 干货笔记 关于晓数神州 晓数神州坚持以“客户为中心”的宗旨,为客户提供专业的解决方案和技术服务ÿ…...

Linux部署ragflow,从安装docker开始~
安装docker https://download.docker.com/linux/static/stable/x86_64/docker-28.0.1.tgz #首先创建一个文件夹,存放我们需要的各类文件,并切换到该目录 mkdir /project && cd /project #此时我们的工作目录已经切换到刚刚创建的文件夹下了,接…...
施磊老师基于muduo网络库的集群聊天服务器(七)
文章目录 数据表字符集问题支持中文和英文**为什么使用 utf8mb4?** 推荐 查看整个表, 再单独修改 客户端群组功能创建群组添加群组群组聊天接收在线群组消息接收离线群组消息补充服务器事件处理器补充服务器查询群组列表问题解决测试 目前报错总结目前为止最恶心的错…...

多态以及多态底层的实现原理
本章目标 1.多态的概念 2.多态的定义实现 3.虚函数 4.多态的原理 1.多态的概念 多态作为面对三大特性之一,它所指代的和它的名字一样,多种形态.但是这个多种形态更多的指代是函数的多种形态. 多态分为静态多态和动态多态. 静态多态在前面已经学习过了,就是函数重载以及模板,…...

使用Go语言实现轻量级消息队列
文章目录 一、引言1.1 消息队列的重要性1.2 为什么选择Go语言1.3 本文实现的轻量级消息队列特点 二、核心设计2.1 消息队列的基本概念2.1.1 消息类型定义2.1.2 消息结构设计 2.2 架构设计2.2.1 基于Go channel的实现方案2.2.2 单例模式的应用2.2.3 并发安全设计 2.3 消息发布与…...
Vue3后代组件多祖先通讯设计方案
在 Vue3 中,当需要设计一个被多个祖先组件使用的后代组件的通讯方式时,可以采用以下方案(根据场景优先级排序): 方案一:依赖注入(Provide/Inject) 响应式上下文 推荐场景ÿ…...

路由与OSPF学习
【路由是跨网段通讯的必要条件】 路由指的是在网络中,数据包从源主机传输到目的主机的路径选择过程。 路由通常涉及以下几个关键元素: 1.路由器:是一种网络设备,负责将数据包从一个网络传输到另一个网络。路由器根据路由表来决定…...

CUDA编程之Grid、Block、Thread线程模型
一、线程模型:Grid、Block、Thread概念 1. 层级定义 Thread(线程) CUDA中最基本的执行单元,对应GPU的单个CUDA核心(SP)。每个线程独立执行核函数指令,拥有独立的寄存器和局部内存空间。 Block(线程块) 由多个线程组成(通常为32的倍数),是逻辑上的并…...
postgres 导出导入(基于数据库,模式,表)
在 PostgreSQL 中,导出和导入数据库、模式(schema)或表的数据可以使用多种工具和方法。以下是常用的命令和步骤,分别介绍如何导出和导入整个数据库、特定的模式以及单个表的数据。 一、导出数据 1. 使用 pg_dump 导出整个数据库…...

小学数学出题器:自动化作业生成
小学数学出题器是专为教师、家长设计的自动化作业生成工具,通过预设参数快速生成符合教学要求的练习题,大幅降低备课与辅导压力。跨平台兼容:支持 Windows 系统免安装运行(解压即用)。免费无广告:永…...
systemctl 命令详解与常见问题解决
在 Linux 系统中,service 命令和 chkconfig 命令一直用于管理服务,但随着 systemd 的引入,systemctl 命令逐渐成为主流。systemctl 命令不仅功能强大,而且使用简单。本文将详细介绍 systemctl 命令的作用以及常见问题的解决方法。…...
12.桥接模式:思考与解读
原文地址:桥接模式:思考与解读 更多内容请关注:7.深入思考与解读设计模式 引言 在软件设计中,尤其是在处理复杂系统时,你是否遇到过这样的情况:你的系统中有多个功能模块,而这些功能模块需要与不同的平台…...

卷积神经网络迁移学习:原理与实践指南
引言 在深度学习领域,卷积神经网络(CNN)已经在计算机视觉任务中取得了巨大成功。然而,从头开始训练一个高性能的CNN模型需要大量标注数据和计算资源。迁移学习(Transfer Learning)技术为我们提供了一种高效解决方案,它能够将预训练模型的知识…...
Centos虚拟机远程连接缓慢
文章目录 Centos虚拟机远程连接缓慢1. 问题:SSH远程连接卡顿现象2. 原因:SSH服务端DNS检测机制3. 解决方案:禁用DNS检测与性能调优3.1 核心修复步骤3.2 辅助优化措施 4. 扩展认识:SSH协议的核心机制4.1 SSH工作原理4.2 关键配置文…...

Spark与Hadoop之间的联系和对比
(一)Spark概述 Apache Spark 是一个快速、通用、可扩展的大数据处理分析引擎。它最初由加州大学伯克利分校 AMPLab 开发,后成为 Apache 软件基金会的顶级项目。Spark 以其内存计算的特性而闻名,能够在内存中对数据进行快速处理&am…...
C++学习笔记(三十九)——STL之删除算法
STL 算法分类: 类别常见算法作用排序sort、stable_sort、partial_sort、nth_element等排序搜索find、find_if、count、count_if、binary_search等查找元素修改copy、replace、replace_if、swap、fill等修改容器内容删除remove、remove_if、unique等删除元素归约for…...
C++——Lambda表达式
在C中,Lambda表达式是一种匿名函数对象,它允许你在代码中直接定义一个函数,而不需要提前声明一个单独的函数。Lambda表达式是从C11标准开始引入的,它极大地增强了C语言的灵活性和表达能力,尤其在处理函数对象、回调函数…...

基于线性LDA算法对鸢尾花数据集进行分类
基于线性LDA算法对鸢尾花数据集进行分类 1、效果 2、流程 1、加载数据集 2、划分训练集、测试集 3、创建模型 4、训练模型 5、使用LDA算法 6、画图3、示例代码 # 基于线性LDA算法对鸢尾花数据集进行分类# 基于线性LDA算法对鸢尾花数据集进行分类 import numpy as np import …...

【Deepseek基础篇】--v3基本架构
目录 MOE参数 1.基本架构 1.1. Multi-Head Latent Attention多头潜在注意力 1.2.无辅助损失负载均衡的 DeepSeekMoE 2.多标记预测 2.1. MTP 模块 论文地址:https://arxiv.org/pdf/2412.19437 DeepSeek-V3 是一款采用 Mixture-of-Experts(MoE&…...
从爬楼梯到算法世界:动态规划与斐波那契的奇妙邂逅
从爬楼梯到算法世界:动态规划与斐波那契的奇妙邂逅 在算法学习的旅程中,总有一些经典问题让人印象深刻。“爬楼梯问题”就是其中之一,看似简单的题目,却蕴藏了动态规划与斐波那契数列的深刻联系。今天,我就以这个问题…...

centos7使用yum快速安装最新版本Jenkins-2.462.3
Jenkins支持多种安装方式:yum安装、war包安装、Docker安装等。 官方下载地址:https://www.jenkins.io/zh/download 本次实验使用yum方式安装Jenkins LTS长期支持版,版本为 2.462.3。 一、Jenkins基础环境的安装与配置 1.1:基本…...

【vue】【element-plus】 el-date-picker使用cell-class-name进行标记,type=year不生效解决方法
typedete,自定义cell-class-name打标记效果如下: 相关代码: <el-date-pickerv-model"date":clearable"false":editable"false":cell-class-name"cellClassName"type"date"format&quo…...