如何正确训练一个 SVM + HOG 行人检测器
这几个月一直在忙着做大论文,一个基于 SVM 的新的目标检测算法。为了做性能对比,我必须训练一个经典的 Dalal05 提出的行人检测器,我原以为这个任务很简单,但是我错了。
为了训练出一个性能达标的行人检测器,我花了半个月的时间,中间遇到各种 BUG 我就不提了,下面只说正确的步骤。(基于 MATLAB 环境,但是没有代码,请您自己写~)
步骤
1. 训练数据集及其它准备工作
训练检测器的正例(Positive examples)数据库最好采用“全图+标注”的形式,不要是那种切出来的行人小图片,这有助于后续的 bootstrap 操作(当然,在 Daimler 这样的数据库上似乎无法做到),初始的负例(Negative examples)采用一组不包含行人的场景图片。其实负例的选择并不重要,因为在 bootstrap 环节,真正影响性能的,靠近分类超平面的数据点会被自动找到。
大多数靠谱的数据库都有自带的标注读取工具库,或者遵循某种标注格式(例如 PASCAL),你也可以使用进一步封装的标注读取工具,例如 Dollar 的 toolbox。
为了计算 HOG 特征,你可以采用 VLFeat 的 HOG 计算函数,这个 HOG 是我见过的检测性能最好的之一(比 OpenCV 的 HOG 好很多,性能提高超过 5%)。
2. 训练
训练必须进行两轮:初始训练,以及 bootstrap 训练。下面的所说的“切图”操作,就是从某个位置切一个 128 * 64 的子图片的意思,当然,你也可以采用其他的切图尺寸。下面,谈一个很重要的问题,就是标注(ground truth)尺寸的归一化,以及标注的外边距(padding)对训练结果的影响。
由于数据库中的行人标注,并不是依照某种固定的长宽比,而 Dalal 检测器的输出是固定长宽比的,所以,在切图之前,必须将标注框(bounding box)的尺寸调整到统一比例。你也许会试图不调整标注框,而是按照原始标注框切出图片,然后再将图片缩放到 128 * 64,但是这样是不对的!检测结果会打折扣。
此外,Dalal 论文里还指出,如果将行人周围的一圈背景也包含到训练子图片里,那么检测器效果又会提升几个百分点,并且论文指出上下左右个加 16 像素的外边距(padding)效果最好,我做了一下实验,确实如此。
调整标注框可以采用 Dollar 工具箱里的 bbApply 函数。下面是我采用的标注框预处理策略:
- 计算不包含 padding 时的行人长宽比 r,即(128 - 32):(64 - 32)
- 使用 bbApply 将标注框的长宽比调整到 r
- 再使用 bbApply 将标注框的高度和宽度分别放大 128 / (128 - 32),以及 64 / (64 - 32) 倍。
经过上述步骤,所有标注框的比例都一致了,并且包含了 padding。
2.1 初始训练
正例直接从训练集中切出来,负例随机从场景图片中切取,假设我需要 9000 个负例,数据集中有 1000 个场景图片,那么平均每幅图片随机切九个即可。切负例时没必要考虑尺度,因为初始负例对整体训练而言没有显著影响,所以随便切即可,任性。
对切出来的数据提取特征,然后丢到 liblinear 里训练一个 SVM,参数:
-B 1 -c 0.01
其中-B 1是为了让 SVM 具有 bias term(就是 wx+b 中的那个 b),-c 0.01 是 Dalal 论文里的 C 参数(你可以试着调一下,不过我试了一下,的确 0.01 最好)。
于是,我们得到了一个初始的检测器。SVM 的支撑矢量个数大概在 1000 ~ 3000 个不等。
2.2 Bootstrap 训练
初始检测器是一个非常非常差的检测器,所以千万不要试图一次训练后就直接拿来用。我们需要新一轮 bootstrap 训练。
所谓 Bootstrap 训练,就是用初始检测器在训练数据集中进行检测,搜集所有的误检,将它们作为额外的新的负例加入先前的负例集合,然后再次训练一个 SVM。所谓误检,就是一个与所有标注位置重合都小于 50% 的检测结果,这个“重合”可以用 area(B1 & B2) / area(B1 | B2) 来计算,其中 B1 和 B2 都是矩形框,“与”运算符是矩形框的交叠,“或”运算符是两个矩形框覆盖的区域相加。
一般来说,初始检测器在训练集上能找到大量误检,例如,我在 INRIA 上训练时就有 2 万个误检,这是正常的(所以你一定要把电脑的虚拟内存调大,否则 MATLAB 会挂),bootstrap 训练后,得到的新的 SVM 的支撑矢量个数将达到 6000 个以上,这从一个侧面说明了,该轮训练找到的负例重新约束了分类超平面的位置。
3. 检测
前面我提到,训练时需要将标注框扩大,但是,扩大的标注框,将使检测结果也被扩大,这时,你需要按照与扩大框的步骤相反的方式,将检测结果框缩小。而且,为了使图片边缘的行人不被漏掉,你可以将输入图片的四周都加上 padding 后再进行检测。
4. 性能
按照这种策略训练出来的检测器,在 INRIA 上达到了 Precision:50%,Recall:71% 的性能,超过了 OpenCV 自带的 HOG Detector(其实没有可比性,因为我用了更好的 HOG 特征),如果您有更好的方案,请告诉我,谢谢。
如何正确训练一个 SVM + HOG 行人检测器的更多相关文章
- 自己训练SVM分类器进行HOG行人检测
正样本来源是INRIA数据集中的96*160大小的人体图片,使用时上下左右都去掉16个像素,截取中间的64*128大小的人体. 负样本是从不包含人体的图片中随机裁取的,大小同样是64*128(从完全不 ...
- Hog SVM 车辆 行人检测
HOG SVM 车辆检测 近期需要对卡口车辆的车脸进行检测,首先选用一个常规的检测方法即是hog特征与SVM,Hog特征是由dalal在2005年提出的用于道路中行人检测的方法,并且取的了不错的识别效 ...
- SVM+HOG特征训练分类器
#1,概念 在机器学习领域,支持向量机SVM(Support Vector Machine)是一个有监督的学习模型,通常用来进行模式识别.分类.以及回归分析. SVM的主要思想可以概括为两点:⑴它是针 ...
- 利用HOG+SVM实现行人检测
利用HOG+SVM实现行人检测 很久以前做的行人检测,现在稍加温习,上传记录一下. 首先解析视频,提取视频的每一帧形成图片存到磁盘.代码如下 import os import cv2 videos_s ...
- opencv学习笔记(七)SVM+HOG
opencv学习笔记(七)SVM+HOG 一.简介 方向梯度直方图(Histogram of Oriented Gradient,HOG)特征是一种在计算机视觉和图像处理中用来进行物体检测的特征描述子 ...
- 【PyTorch深度学习60分钟快速入门 】Part4:训练一个分类器
太棒啦!到目前为止,你已经了解了如何定义神经网络.计算损失,以及更新网络权重.不过,现在你可能会思考以下几个方面: 0x01 数据集 通常,当你需要处理图像.文本.音频或视频数据时,你可以使用标准 ...
- 深度学习笔记 (二) 在TensorFlow上训练一个多层卷积神经网络
上一篇笔记主要介绍了卷积神经网络相关的基础知识.在本篇笔记中,将参考TensorFlow官方文档使用mnist数据集,在TensorFlow上训练一个多层卷积神经网络. 下载并导入mnist数据集 首 ...
- PyTorch Tutorials 4 训练一个分类器
%matplotlib inline 训练一个分类器 上一讲中已经看到如何去定义一个神经网络,计算损失值和更新网络的权重. 你现在可能在想下一步. 关于数据? 一般情况下处理图像.文本.音频和视频数据 ...
- Fine-tuning Convolutional Neural Networks for Biomedical Image Analysis: Actively and Incrementally如何使用尽可能少的标注数据来训练一个效果有潜力的分类器
作者:AI研习社链接:https://www.zhihu.com/question/57523080/answer/236301363来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载 ...
随机推荐
- 深入理解java集合
集合 Java集合分为三大接口:①Collection ②Map ③Iterator
- LeetCode 116/117. 填充同一层的兄弟节点(Populating Next Right Pointers in Each Node)
题目描述 给定一个二叉树 struct TreeLinkNode { TreeLinkNode *left; TreeLinkNode *right; TreeLinkNode *next; } 填充 ...
- 【Spark机器学习速成宝典】模型篇07梯度提升树【Gradient-Boosted Trees】(Python版)
目录 梯度提升树原理 梯度提升树代码(Spark Python) 梯度提升树原理 待续... 返回目录 梯度提升树代码(Spark Python) 代码里数据:https://pan.baidu.co ...
- C# hook WndProc
在当前窗口里重载WndProc,只能捕获到当前WinForm窗口的消息 protected override void WndProc(ref Message m) { if (m.Msg == WM ...
- leetcode 56区间合并
class Solution { public: static bool cmp(vector<int> a,vector<int> b){ ]<b[]; } vecto ...
- 阶段3 2.Spring_02.程序间耦合_3 程序的耦合和解耦的思路分析1
编译时没有对应需要的jar包就报错.这特性就理解为程序的耦合 这种方式,它不是个错误而是个异常.编译的时候没有问题.运行时才会报错. 把注释的代码放开 程序可以正常运行 解决类之前依赖的思路 一个依赖 ...
- div 加滚动条 超过div宽度 自动换行 div居中
一.div 中加滚动条 一. <div style=" overflow:scroll; width:400px; height:400px;”></div> 记住宽 ...
- 数据测试002:利用Jmeter推送测试数据(上)
数据测试002:利用Jmeter推送测试数据(上) 刚才用Jmeter配置一下MySQL数据库花了点时间,好在最后都解决了,注意下面几个问题: 1)没有配置 “Cannot load JDBC dr ...
- Jmeter响应数据中文乱码|响应内容显示乱码
1.使用jmeter进行接口调用时出现返回数据乱码,如图示 原因是jmeter默认按照ISO-8859-1解析响应的数据. 2.所以需要修改bin目录下的jmeter.properties文件: 具体 ...
- Oracle 单实例安装篇
linux中启动网卡报错:Error: Connection activation failed: Connection 'eth0' is not available on the device e ...