这几个月一直在忙着做大论文,一个基于 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. Mac-连接Windows远程桌面软件

    链接:https://download.csdn.net/download/ab601026460/9885775 https://blog.csdn.net/ab601026460/article/ ...

  2. vue的周期函数

    beforeCreate(创建前) created(创建后) beforeMount(载入前) mounted(载入后) beforeUpdate(更新前) updated(更新后) beforeDe ...

  3. 使用django-cors-headers 来解决跨域问题

    在settting里面这样配置 ALLOWED_HOSTS = ["*"] # Application definition INSTALLED_APPS = [ 'django. ...

  4. json -- fastjson如何序列化@Transient的字段

    今天把fastjson包改成了1.2.58,发现@Transient标注的字段序列化后不见了,但是项目需要把@Transient字段序列化,处理方法: 原文:https://github.com/al ...

  5. Selenium 2自动化测试实战1(1-2章节重点笔记)

    1.黑盒测试 黑盒测试,指的是把被测的软件看做一个黑盒子,不去关心盒子里面的结构是什么样子的,只关心软件的输入数据和输出结果. 2.白盒测试白盒测试,指的是把盒子打开,去研究里面的源代码和程序执行结果 ...

  6. Python 解决八皇后问题

    问题介绍 八皇后问题是一个以国际象棋为背景的问题:如何能够在 \(8\times8\) 的国际象棋棋盘上放置八个皇后,使得任何一个皇后都无法直接吃掉其他的皇后?为了达到此目的,任两个皇后都不能处于同一 ...

  7. CoverflowJS

    coverflow是苹果首创的将多首歌曲的封面以3D界面的形式显示出来的方式 GitHub地址:[https://github.com/coverflowjs/coverflow] 下载地址:[htt ...

  8. 错误:expected initializer before "***"

    今天写了一个程序,编译时报了一个错误:expected initializer before "***"报错的语句只是程序开头的一个变量定义语句,怎么会有这样的错误呢,琢磨了半天也 ...

  9. Python学习之数据库初识

    9 数据库 9.1 数据库的初识 ​ 数据库是可以独立运行的,并且可以对数据的增删改查提供高效便捷方式的工具. 数据库解决的问题: ​ 解决了操作文件的效率和便捷问题 ​ 解决了多个服务同时使用数据时 ...

  10. 【Ruby on Rails 学习三】Ruby 基本数据类型(类、类的实例、对象)

    数字.文本.范围.符合.True.False.Nil 1为什么是一个类的对象,使用methods方法可以查看一个对象的所有函数(方法) $ irb irb(main)::> => irb( ...