这几个月一直在忙着做大论文,一个基于 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 函数。下面是我采用的标注框预处理策略:

  1. 计算不包含 padding 时的行人长宽比 r,即(128 - 32):(64 - 32)
  2. 使用 bbApply 将标注框的长宽比调整到 r
  3. 再使用 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 行人检测器的更多相关文章

  1. 自己训练SVM分类器进行HOG行人检测

    正样本来源是INRIA数据集中的96*160大小的人体图片,使用时上下左右都去掉16个像素,截取中间的64*128大小的人体. 负样本是从不包含人体的图片中随机裁取的,大小同样是64*128(从完全不 ...

  2. Hog SVM 车辆 行人检测

    HOG SVM 车辆检测 近期需要对卡口车辆的车脸进行检测,首先选用一个常规的检测方法即是hog特征与SVM,Hog特征是由dalal在2005年提出的用于道路中行人检测的方法,并且取的了不错的识别效 ...

  3. SVM+HOG特征训练分类器

    #1,概念 在机器学习领域,支持向量机SVM(Support Vector Machine)是一个有监督的学习模型,通常用来进行模式识别.分类.以及回归分析. SVM的主要思想可以概括为两点:⑴它是针 ...

  4. 利用HOG+SVM实现行人检测

    利用HOG+SVM实现行人检测 很久以前做的行人检测,现在稍加温习,上传记录一下. 首先解析视频,提取视频的每一帧形成图片存到磁盘.代码如下 import os import cv2 videos_s ...

  5. opencv学习笔记(七)SVM+HOG

    opencv学习笔记(七)SVM+HOG 一.简介 方向梯度直方图(Histogram of Oriented Gradient,HOG)特征是一种在计算机视觉和图像处理中用来进行物体检测的特征描述子 ...

  6. 【PyTorch深度学习60分钟快速入门 】Part4:训练一个分类器

      太棒啦!到目前为止,你已经了解了如何定义神经网络.计算损失,以及更新网络权重.不过,现在你可能会思考以下几个方面: 0x01 数据集 通常,当你需要处理图像.文本.音频或视频数据时,你可以使用标准 ...

  7. 深度学习笔记 (二) 在TensorFlow上训练一个多层卷积神经网络

    上一篇笔记主要介绍了卷积神经网络相关的基础知识.在本篇笔记中,将参考TensorFlow官方文档使用mnist数据集,在TensorFlow上训练一个多层卷积神经网络. 下载并导入mnist数据集 首 ...

  8. PyTorch Tutorials 4 训练一个分类器

    %matplotlib inline 训练一个分类器 上一讲中已经看到如何去定义一个神经网络,计算损失值和更新网络的权重. 你现在可能在想下一步. 关于数据? 一般情况下处理图像.文本.音频和视频数据 ...

  9. Fine-tuning Convolutional Neural Networks for Biomedical Image Analysis: Actively and Incrementally如何使用尽可能少的标注数据来训练一个效果有潜力的分类器

    作者:AI研习社链接:https://www.zhihu.com/question/57523080/answer/236301363来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载 ...

随机推荐

  1. 获取<a>标签值</a>的标签值及更改

    html代码: <a id="catelogue_div1_h5" onclick="catelogue_div1(event)">隐藏</a ...

  2. linux查询端口被哪个程序使用了

    使用如下命令查询8000端口被哪个程序使用 netstat -tunlp|

  3. MSTest/NUnit 单元测试 代码覆盖率试用 OpenCover 和ReportGenerator

    VS自带是单元测试代码覆盖率(VS自带这个是最佳选择)需要企业版才有.很蛋疼...... 1.下载安装OpenCover 和ReportGenerator. 关于这2个是干啥的百度下.简单说就是可以分 ...

  4. Jquery退出循环

    返回falsh即可 return false; 如果return true; 则进入下一次循环

  5. 阶段3 2.Spring_03.Spring的 IOC 和 DI_9 spring的依赖注入

    新建工程 改成jar包 加入spring的依赖 复制之前的工程代码 再复制配置文件 fac factory整个删除 构造函数也删除.删除后的代码.如下 配置文件中的注释都删除掉 spring中的依赖注 ...

  6. Elasticsearch 6.2.3版本 Windows环境 简单操作

    背景描述 Elasticsearch是一个基于Apache Lucene(TM)的开源搜索引擎.无论在开源还是专有领域,Lucene可以被认为是迄今为止最先进.性能最好的.功能最全的搜索引擎库. El ...

  7. Report List 报表开发

    1. Report List的输出定义 * ...NO STANDARD PAGE HEADING: 输出的报表不包含表头: * ...LINE-SIZE col : 输出的报表不包含表头: * .. ...

  8. java:多线程(代理模式,Thread中的方法,Timer,生产者和消费者)

    *进程:一个正在运行的程序,进程是操作系统分配资源的基本单位,每个进行有独立的内存空间,进程之间切换开销较大. *线程:一个轻量级的进程,线程是任务调度的基本单位,一个进程可以有多个线程, * 系统没 ...

  9. 【VS开发】DLL和ocx的区别

    ActiveX,OLE是基于COM的一种应用,其文件后缀一般以dll和ocx结尾:ocx作为一种特殊的dll文件,具有一定的用户界面和事件响应,而dll文件只是方法和属性的集合. 一.关于DLL的介绍 ...

  10. linux是什么与如何学习(三)

     1.1Linux是什么 Linux是在计算机上面运作的,所以说是一组软件. 1.2 Linux是什么?操作系统还是应用程序? 计算机主机是由一套硬件所组成的,为了有效的控制这些硬件资源,于是就有了操 ...