行人检测HOG+SVM:综述、INRIADATA数据集、线性SVM

目录

1. 行人检测算法研究综述

2. 基于机器学习的方法:人工特征+分类器

2.1 HOG+SVM

2.2 HOG+Adaboost

2.3 ICF+AdaBoost

2.4 DPM+ latent SVM

3. HOG+SVM环境配置

3.1 数据集INRIADATA

3.2 算法原理

3.2.1 HOG梯度方向直方图 Histogram of Oriented Gradients

3.2.2 使用线性SVM进行训练

3.3.3 代码

4. 环境配置:Matlab安装libsvm

5. 行人检测方面的数据集

 1. HOG+SVM使用的行人识别数据集

2. 红外行人数据集:KAIST Multispectral Pedestrain Detection Benchmark

3. 南方科技大学的红外数据集:SCUT_FIR_Pedestrian_Dataset

6. 在自己的数据集上分析和优化

1. 如何学习怎么查找模型问题所在?

1.1 SVM深入理解

1.3 SVM中解决泛化问题

2. Matlab svm训练的模型如何在C++中使用

7. 分析和优化模型

当前状态:

2.其他的一些疑问 

3. 红外数据集

Dataset 01: OSU Thermal Pedestrian Database

Dataset 03: OSU Color-Thermal Database

8. 指标方面

 1. 图像指标对应 

2. 正负样本的问题

2.1 样本的数量

2.2 负样本

2.3 应该把脸部的局部部位作为负样本吗?如眼睛或鼻子

2.4 该怎么收集负样本信息?

2.5 在步骤4中。

2.6 探测器的最后增强步骤

2.7 real numbers

3. 负样本的concerns

3.1 不同环境下的负样本

3.2 不同尺度(距离)下的负样本

4、目标检测——降低误检测率:负样本制作、增强、训练

为什么要训练负样本?

如何收集负样本?

怎么消除误检测?

5、评价指标

6、大规模训练结果



1. 行人检测算法研究综述

  • 参考资料https://zhuanlan.zhihu.com/p/51438953
  • 要解决的问题:找出图像或视频帧中所有的行人,包括位置和大小,一般用矩形框表示。
  • 主要难题: 外观差异大,遮挡问题,背景复杂,检测速度。
  • 行人数据库: INRIA 数据库、Caltech 数据库和 TUD 行人数据库。

目标检测现在主要分为以下几个方向:

  • (1)基于运动检测的算法——背景建模。只利用像素级的信息,没有利用图像中更高层的语义信息。利用背景建模方法,提取出前景运动的目标,在目标区域内进行特征提取,然后利用分类器进行分类,判断是否包含行人;
    • 只能检测运动目标,不处理静止目标
    • 受光照变化、阴影影响大
    • 目标伪装色造成漏检和断裂
    • 受恶劣天气,雨雪,以及树叶摇晃等干扰物的影响
    • 多目标粘连,重叠,则无法处理。
  • (2)基于机器学习的方法(现阶段行人检测算法的主流),也是目前行人检测最常用的方法,根据大量的样本构建行人检测分类器。提取的特征主要有目标的灰度、边缘、纹理、颜色、梯度直方图等信息。分类器主要包括神经网络、SVM、adaboost以及现在被计算机视觉视为宠儿的深度学习。
    • 人工特征(括颜色,边缘,纹理等)+分类器(有神经网络,线性SVM,AdaBoost,随机森林等计算机视觉领域常用的算法)

统计机器学习目前存在的难点

      • 行人的姿态、服饰各不相同、复杂的背景、不同的行人尺度以及不同的光照环境。
      • 提取的特征在特征空间中的分布不够紧凑;
      • 分类器的性能受训练样本的影响较大;
      • 离线训练时的负样本无法涵盖所有真实应用场景的情况;

目前的行人检测基本上都是基于法国研究人员Dalal在2005的CVPR发表的HOG+SVM的行人检测算法(Histograms of Oriented Gradients for Human Detection, Navneet Dalel,Bill Triggs, CVPR2005)。HOG+SVM作为经典算法也集成到opencv里面去了,可以直接调用实现行人检测。

为了解决速度问题可以采用背景差分法的统计学习行人检测,前提是背景建模的方法足够有效(即效果好速度快),目前获得比较好的检测效果的方法通常采用多特征融合的方法以及级联分类器。(常用的特征有Harry-like、Hog特征、LBP特征、Edgelet特征、CSS特征、COV特征、积分通道特征以及CENTRIST特征)。

https://blog.csdn.net/SIGAI_CSDN/article/details/80693322的内容提要如下:

2. 基于机器学习的方法:人工特征+分类器

2.1 HOG+SVM

人体有自身的外观特征,我们可以手工设计出特征,然后用这种特征来训练分类器用于区分行人和背景。这些特征包括颜色,边缘,纹理等机器学习中常用的特征,采用的分类器有神经网络,SVM,AdaBoost,随机森林等计算机视觉领域常用的算法。由于是检测问题,因此一般采用滑动窗口的技术,这在SIGAI之前的公众号文章“人脸检测算法综述”,“基于深度学习的目标检测算法综述”中已经介绍过了。

行人检测第一个有里程碑意义的成果是Navneet Dalal在2005的CVPR中提出的基于HOG + SVM的行人检测算法[5]。Navneet Dalal是行人检测中之前经常使用的INRIA数据集的缔造者。 

梯度方向直方图(HOG)是一种边缘特征,它利用了边缘的朝向和强度信息,后来被广泛应用于车辆检测,车牌检测等视觉目标检测问题。HOG的做法是固定大小的图像先计算梯度然后进行网格划分计算每个点处的梯度朝向和强度,然后形成网格内的所有像素的梯度方向分布直方图,最后汇总起来,形成整个直方图特征

这一特征很好的描述了行人的形状、外观信息,比Haar特征更为强大,另外,该特征对光照变化和小量的空间平移不敏感。下图为用HOG特征进行行人检测的流程:

得到候选区域的HOG特征后,需要利用分类器对该区域进行分类,确定是行人还是背景区域。在实现时,使用了线性支持向量机,这是因为采用非线性核的支持向量机在预测时的计算量太大,与支持向量的个数成正比。如果读者对这一问题感兴趣,可以阅读SIGAI之前关于SVM的文章。

目前OpenCV中的行人检测算法支持HOG+SVM以及HOG+Cascade两种,二者都采用了滑动窗口技术,用固定大小的窗口扫描整个图像,然后对每一个窗口进行前景和背景的二分类。为了检测不同大小的行人,还需要对图像进行缩放。

  • HOG计算梯度方向和强度->梯度直方图,比Haar特征更为强大,且对光照变化和小量空间平移不敏感。
  • 得到HOG特征后,使用分类器进行分类。线性SVM,非线性SVM计算量太大。
  • OpenCV支持HOG+SVM和HOG+Cascade,都采用滑动窗口技术。

2.2 HOG+Adaboost

由于HOG + SVM的方案计算量太大,为了提高速度,后面有研究者参考了VJ[6]在人脸检测中的分类器设计思路,AdaBoost分类器级联的策略应用到了人体检测中,只是将Haar特征替换成HOG特征,因为Haar特征过于简单,无法描述人体这种复杂形状的目标。下图为基于级联Cascade分类器的检测流程:

图中每一级中的分类器都是利用AdaBoost算法学习到的一个强分类器,处于前面的几个强分类器由于在分类器训练的时候会优先选择弱分类器,可以把最好的几个弱分类器进行集成,所有只需要很少的几个就可以达到预期效果,计算会非常简单,速度很快,大部分背景窗口很快会被排除掉,剩下很少一部分候选区域或通过后续的几级分类器进行判别,最终整体的检测速度有了很大的提升,相同条件下的预测时间只有基于SVM方法的十分之一。

2.3 ICF+AdaBoost

HOG特征只关注了物体的边缘和形状信息,对目标的表观信息并没有有效记录,所以很难处理遮挡问题,而且由于梯度的性质,该特征对噪点敏感。针对这些问题后面有人提出了积分通道特征(ICF[7],积分通道特征包括10个通道:

6 个方向的梯度直方图,3 个LUV 颜色通道和1 梯度幅值,见下图,这些通道可以高效计算并且捕获输入图像不同的信息。

在这篇文章里,AdaBoost分类器采用了soft cascade的级联方式。为了检测不同大小的行人,作者并没有进行图像缩放然后用固定大小的分类器扫描,而是训练了几个典型尺度大小的分类器,对于其他尺度大小的行人,采用这些典型尺度分类器的预测结果进行插值来逼近,这样就不用对图像进行缩放。因为近处的行人和远处的行人在外观上有很大的差异,因此这样做比直接对图像进行缩放精度更高。这一思想在后面的文章中还得到了借鉴。通过用GPU加速,这一算法达到了实时,并且有很高的精度,是当时的巅峰之作。

2.4 DPM+ latent SVM

行人检测中的一大难题是遮挡问题,为了解决这一问题,出现了采用部件检测的方法,把人体分为头肩,躯干,四肢等部分,对这些部分分别进行检测,然后将结果组合起来,使用的典型特征依然是HOG,采用的分类器有SVM和AdaBoost针对密集和遮挡场景下的行人检测算法可以阅读文献[15]。

DPM(Deformable Parts Models)算法在SIGAI在之前的文章“基于深度学习的目标检测算法综述”已经提到过。这是是一种基于组件的检测算法,DPM检测中使用的特征是HOG,针对目标物不同部位的组建进行独立建模。DPM中根模型和部分模型的作用,根模型(Root-Filter)主要是对物体潜在区域进行定位,获取可能存在物体的位置,但是是否真的存在我们期望的物体,还需要结合组件模型(Part-Filter)进行计算后进一步确认,DPM的算法流程如下:

DPM算法在人体检测中取得取得了很好的效果,主要得益于以下几个原因:

  1. 基于方向梯度直方图(HOG)的低级特征(具有较强的描述能力)
  2. 基于可变形组件模型的高效匹配算法
  3. 采用了鉴别能力很强的latent-SVM分类器

DPM算法同时存在明显的局限性,首先DPM特征计算复杂计算速度慢(论文[8]中针对DPM提出了多个加速的策略,有兴趣的读者可以参考);其次,人工特征对于旋转、拉伸、视角变化的物体检测效果差。这些弊端很大程度上限制了算法的应用场景,这一点也是基于人工特征+分类器的通病。

采用经典机器学习的算法虽然取得了不错的成绩,但依然存在下面的问题

1.对于外观,视角,姿态各异的行人检测精度还是不高

2.提取的特征在特征空间中的分布不够紧凑

3.分类器的性能受训练样本的影响较大

4.离线训练时的负样本无法涵盖所有真实应用场景的情况

基于机器学习的更多方法以参考综述文章[10][18][19]。文献[10]对常见的16种行人检测算法进行了简单描述,并在6个公开测试库上进行测试,给出了各种方法的优缺点及适用情况。

文献[18]提出了Caltech数据集,相比之前的数据集,它的规模大了2个数量级。作者在这个数据集上比较了当时的主要算法,分析了一些失败的的原因,为后续的研究指出了方向。

文献[19]也比较了10年以来的行人检测算法,总结了各种改进措施,并支持了以后的研究方向。

3. HOG+SVM环境配置

3.1 数据集INRIADATA

来自HOG+SVM的论文,论文中使用的图片是归一化之后的。

训练和测试的时候有几种选择方式:

用normalized_images目录下的图片做训练,或者用original_images目录下的图片+annotations获取行人区域做训练;测试则都在original_images/test/pos上测试。

这个数据集来自于 github搜索关键字:HOG+SVM ,或者github搜索关键字:HOG+SVM行人检测,后者star最多的的 https://github.com/icsfy/Pedestrian_Detection,找不到原作者了。反正就是作者已经分好了如下的数据集:

3.2 算法原理

资料:https://blog.csdn.net/hongbin_xu/article/details/79810544 HOG特征检测学习笔记,MATLAB code求HOG。

3.2.1 HOG梯度方向直方图 Histogram of Oriented Gradients

  • 特征描述子:特征向量作为SVM的输入很重要,选取怎样的特征决定了分类的准确率。
  • 哪些特征是有用的呢?哪些特征冗余?特征需要有很好的区分能力。
  • HOG特征描述子,选用梯度方向的分布作为特征。梯度是描述边缘信息的。

如何计算HOG梯度方向直方图呢?

  • 图像需要保持固定的长宽比,如1:2。从原始图像得到小的切片。如得到64*128的切片
  • 再把64*128的切片分成8*8的Cell。用特征描述子描述图像的一小块,用更细微的方式刻画了原图像。
  • 梯度方向图+梯度强度图,方向在[0,180],经验表明:无符号的梯度比有符号梯度效果更好。
  • 计算梯度方向直方图:每个bin是按照梯度方向选出来的。一般是9个bin
  • 总结:8*8的cell用9*1的直方图表示,4个cell组成一个block,block为16*16。所以一个block有4*9*1=36*1的列向量表示HOG特征。那么对于一个64*128的图像而言,其特征的维度为:7*15*36=3780。

梯度方向直方图Histogram of Oriented Gradients (HOG) 这篇文章详细描述了HOG特征是如何提取和计算的,超级棒!

关键的几张图示如下:

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

其他资料:

https://blog.csdn.net/carson2005/article/details/8316835   CSDN 266

https://blog.csdn.net/hongbin_xu/article/details/79845290  CSDN 3081 code

https://blog.csdn.net/qq_37753409/article/details/79047063    CSDN C++ code

https://www.cnblogs.com/heleifz/p/train-hog-svm-detector.html

  • Vlfeat有一个HOG的实现,比OpenCV的实现要好。
  • 按照这种策略训练出来的检测器,在 INRIA 上达到了 Precision:50%,Recall:71% 的性能,超过了 OpenCV 自带的 HOG Detector(其实没有可比性,因为我用了更好的 HOG 特征),如果您有更好的方案,请告诉我,谢谢。

https://blog.csdn.net/Young__Fan/article/details/85000200   HOG+SVM参考资料大合集

3.2.2 使用线性SVM进行训练

提取特征+分类器,提取了好的特征,那么用什么样的分类器都能得到不错的结果。

为什么使用线性SVM?

另外一个问题什么时候选择SVM或逻辑回归?如图:
1. 特征维度n很大:
使用逻辑回归和线性SVM.
2. 特征维度n小,样本数量m中等:
使用高斯核SVM。
3. 特征维度n小,且样本数量m巨大:
- 可以创建新的特征
- 然后使用逻辑回归和无核SVM

什么是线性SVM?

左图就是线性SVM,就是不使用核函数,将\theta^TX送入SVM,形成一个大间距分类器。后者使用了高斯核函数,可以得到复杂的曲线边界。

image

  • 核函数:为了得到非线性的拟合

假设函数hθ(x)=θ0+θ1f1+θ2f2+θ3f3+⋯(用f代替x的参数)这个函数为新的假设函数。

我们设置f函数,衡量标记点和原先样本点的相似性。 为fi=similarity(x^{(i))},l^{(i)})=exp(-\frac{\left \| x^{(i))}-l^{(i)}\right \|^2}{2\sigma^2})

即设计一些landmarks li,这些landmarks对于得到非线性的边界十分重要,计算xi和li的相似度fi,并将fi作为特征输入:

hθ(x)=θ0+θ1f1+θ2f2+θ3f3+⋯,就可以得到非线性的分类边界!

  • 如何得到参数θ呢?

    • 输入X,y,C等参数,经过svmTrain后得到模型model,得到参数w和b,由于是线性的,所以y=(w^Tx+b)

    • 则:w^Tx+b>1为正样本,w^Tx+b<-1为负样本。

model = svmTrain(X, y, C, @linearKernel, 1e-3, 20);

function visualizeBoundaryLinear(X, y, model)
%VISUALIZEBOUNDARYLINEAR plots a linear decision boundary learned by the
%SVM
%   VISUALIZEBOUNDARYLINEAR(X, y, model) plots a linear decision boundary 
%   learned by the SVM and overlays the data on it

w = model.w;
b = model.b;
xp = linspace(min(X(:,1)), max(X(:,1)), 100);
yp = - (w(1)*xp + b)/w(2);
plotData(X, y);
hold on;
plot(xp, yp, '-b'); 
hold off

end

3.3.3 代码

4. 环境配置:Matlab安装libsvm

 资料:


  • 1. 下载libsvm,下载地址为:https://www.csie.ntu.edu.tw/~cjlin/libsvm/找到这个download LIBSVM 下载
  • 2. 下载得到的libsvm-3.24文件夹复制到E:\Program Files\matlab r2018\toolbox下
  • 3. 在matlab的主页栏找到 设置路径 ,添加 E:\Program Files\matlab r2018\toolbox\libsvm-3.24\matlab 到 matlab的路径中

  • 4. 在MATLAB命令窗口输入mex –setup C++ ,

  • 5. matlab目录切换到E:\Program Files\matlab r2018\toolbox\libsvm-3.24\matlab 文件下,并执行make

  • 5.解决办法:——之前没有解决这个问题,好像是权限导致的,使用管理员方式打开matlab
  • 6. 不明所以,直接找matlab的 安装MinGW-w64,转向了matlab file exchange,登录matlab账号进行下载,得到
  • 直接将这个文件拖到matlab的命令行,然后就是漫长的等待安装下载

参考 Matlab选择mingw编译器 进行安装。

寻找新办法

https://blog.csdn.net/SKY_yiyi_9/article/details/88140283 如何在Matlab2018a中配置MinGW-w64 C/C++ 编译器

无奈放弃,让别人跑的,生成.mex64给我,哎!

  • 猜测我是vs2013,别人的时vs2015,哎!
  • 然后要添加文件夹,添加libsvm的很多文件夹到当前路径下面
  • 然后使用的时候为了与matlab自带的函数冲突,使用libsvmtrain等。使用的时候也用libsvmtrian即可。解决问题

5. 行人检测方面的数据集

https://blog.csdn.net/haronchou/article/details/106120804 其他数据集

 1. HOG+SVM使用的行人识别数据集

  • (1) INRIA Person Dataset(INRIA行人数据库)——可见光数据集,样本大小128*64

2. 红外行人数据集:KAIST Multispectral Pedestrain Detection Benchmark

  • github地址:https://github.com/SoonminHwang/rgbt-ped-detection 
  • 这个是多光谱图像:对齐的RGB+热像仪图像,640×480像素,手动注释所有人,骑自行车的人。注释包括边界框(如Caltech Pedestrian Dataset)之间的时间对应。
  • 许多人也在努力提高我们的基准行人检测性能,如:
  • 其他研究人员也采用多模态的方法,Also, another researches to employ multi-modality are presented.

    • Image-to-image translation [Arxiv '17]
    • Calibrations

3. 南方科技大学的红外数据集:SCUT_FIR_Pedestrian_Dataset

  • 执行之前,先运行一下starup,将所有的文件夹加入当前路径,才能方便的调用其他函数
  •  extract_img_anno_scut
  • dbExtract_scut 从数据库seq提取images,同时提取annotations到Txt files
  • 从pth的annatation里面load ground truth,即annatations文件夹要放在pth的路径下面
  • 然后将提取到的Images放在tDir的images文件夹下面
  • seq文件要放在pth的videos文件夹下面。
  • 然后运行 extract_img_anno_scut函数即可

得到的结果如下:

import cv2
import os
import sys
import glob
from PIL import Image

# VEDAI 图像存储位置
src_img_dir = "F:\\pedestrain detection benchmark\\SCUT_FIR_Pedestrian_Dataset-master\\train02\\images\\"
# VEDAI 图像的 ground truth 的 txt 文件存放位置
src_txt_dir = "F:\\pedestrain detection benchmark\\SCUT_FIR_Pedestrian_Dataset-master\\train02\\annotations\\"
# 所有的图像名称
img_Lists = glob.glob(src_img_dir + '/*.jpg')

img_basenames = []  # e.g. 100.jpg
for item in img_Lists:
    img_basenames.append(os.path.basename(item))

img_names = []  # e.g. 100
for item in img_basenames:
    temp1, temp2 = os.path.splitext(item)
    img_names.append(temp1)

for img in img_names:
    # open the crospronding txt file
    with open(src_txt_dir + '/' + img + '.txt',"r") as f:
        line_count = 0
        for line in f.readlines():
            if line_count == 0:
                line_count += 1
                continue
            line = line.strip('\n')
            spt = line.split(' ')
            cat_name = str(spt[0])
            x_min = int(spt[1])
            y_min = int(spt[2])
            bbox_wid = int(spt[3])
            bbox_hei = int(spt[4])

            if cat_name == "people" or cat_name == "walk person":
                if bbox_hei >= 10 and bbox_hei <= 30:
                    bbox_hei_new = 2*bbox_wid
                    if y_min+bbox_hei > 576:
                        y_min = 576-bbox_hei_new
                    else:
                        y_min = y_min-(bbox_hei_new-bbox_hei)/2

                    # 确保尺寸为1:2,扩充为原来的1.5倍
                    '''
                    bbox_wid_new = int(bbox_wid)
                    bbox_hei_new = int(2 * bbox_wid_new)
                    # 防止越界
                    if y_min >= 0.25*bbox_hei and y_min + bbox_hei_new< 576:
                        y_min = y_min - 0.25*bbox_hei
                    elif y_min < 0.25*bbox_hei:
                        y_min = 0
                    else:
                        y_min = 576 - bbox_hei_new

                    if x_min >= 0.25 * bbox_wid and x_min + bbox_wid_new < 720:
                        x_min = x_min - 0.25 * bbox_wid
                    elif y_min < 0.25 * bbox_wid:
                        x_min = 0
                    else:
                        x_min = 720 - bbox_wid_new
                    '''

                    # 读入图像
                    img_data = cv2.imread((src_img_dir + '/' + img + '.jpg'), cv2.IMREAD_UNCHANGED)
                    cropped = img_data[int(y_min):int(y_min+bbox_hei_new),int(x_min):int(x_min+bbox_wid)]  # y为高度,x为宽度
                    cv2.imwrite("G:\\scut_pedestrain_crop\\train\\" + "test_" + str(img) + ".jpg", cropped)
                    # cv2.rectangle(img_data, (x_min, y_min), (x_min+bbox_wid, y_min+bbox_hei), (255, 0, 0), 2)
                    # cv2.imshow('label', img_data)
                    # cv2.waitKey(0)


        '''
    # gt = open(src_txt_dir + '/gt_' + img + '.txt').read().splitlines()

    # write the region of image on xml file
    for img_each_label in gt:
        spt = img_each_label.split(' ')  # 这里如果txt里面是以逗号‘,’隔开的,那么就改为spt = img_each_label.split(',')。


        xml_file.write('        <name>' + str(spt[4]) + '</name>\n')
        xml_file.write('        <pose>Unspecified</pose>\n')
        xml_file.write('        <truncated>0</truncated>\n')
        xml_file.write('        <difficult>0</difficult>\n')
        xml_file.write('        <bndbox>\n')
        xml_file.write('            <xmin>' + str(spt[0]) + '</xmin>\n')
        xml_file.write('            <ymin>' + str(spt[1]) + '</ymin>\n')
        xml_file.write('            <xmax>' + str(spt[2]) + '</xmax>\n')
        xml_file.write('            <ymax>' + str(spt[3]) + '</ymax>\n')
        xml_file.write('        </bndbox>\n')
        xml_file.write('    </object>\n')


# 获取路径下的所有txt格式的文件名
def file_name(file_dir):
    File_Name=[]
    img_dir = "F:\\pedestrain detection benchmark\\SCUT_FIR_Pedestrian_Dataset-master\\train02\\images\\"
    for files in os.listdir(file_dir):
        if os.path.splitext(files)[1] == '.txt':
            img_dir += files[:-3]+"jpg"
            # File_Name.append(files)
            # 以原格式读入图像,原图像为灰度图
            img = cv2.imread(img_dir,cv2.IMREAD_UNCHANGED)
            # 需要读入标签信息



    return File_Name
txt_file_name=file_name("F:\\pedestrain detection benchmark\\SCUT_FIR_Pedestrian_Dataset-master\\train02\\annotations\\")
print("txt_file_name",txt_file_name)
        '''

6. 在自己的数据集上分析和优化

背景:由于HOG+SVM行人检测在自己的数据集上出现了问题,如下:

  • 正样本召回率95%,负样本召回率59%——导致Recall=95%,Precision=59%,F1=0.6
  • 需要对模型进行分析,到底是哪里出了问题,导致了现在的情况?
  • 初步认为借助:学习曲线等一系列诊断工具可以分析出是特征不够?不具有区分性?还是样本不够?还是样本的结构不太好?
    • (1)现象:模型对样本没有任何区分性,即对负样本的预测上没有任何趋势
    • (2)原因:未知
    • (3)怎么办?:暂时准备给出一些clean干净的负样本数据,降低负样本识别的难度。——临时措施
      • 目的1:仅仅是为了测试当前模型对于easy task场景能否胜任
      • 目的2:若easy场景可以适用,则写入工程中测试初步的效果,然后出第一版
    • (4)下一步优化目的:要加入midum task,主要是midum的负样本,如何提高负样本的识别率。
    • (5)下一步优化方向:肯定是要优化HOG,主要是分析问题出在特征的哪个环节,后者负样本数据集结构不合理的哪个环节,以及数据尺寸问题的哪个环节这部分复杂又重要,特征的选择、分析、优化决定了一切!

后记:坑爹的原因是读图的路径设置的有问题,导致读入的仅仅是文件名,没有加入绝对路径,导致读的图是错误的,才出现了上述问题。我也是醉了!!!以后要避免这种低级错误。

当然,模型的分析和优化技能也是相当重要的,是后期最重要的技能。所以还是要掌握的!

2020/05/15 update:

  • 当前问题:样本太少太少。项目数据量在200+左右,且需要识别400m左右的人,<200m的行人。

1. 如何学习怎么查找模型问题所在?

  • 参考学习别人的资料:《机器学习实战》chap6-SVM支持向量机的代码学习,学习如何使用python的numpy等计算包
  • 参考《机器学习实战》chap6如何计算SVM的训练误差和测试误差的,然后计算学习曲线等诊断模型
  • 模型诊断的手段和方法有待学习!!!!

《机器学习实战》中英文电子书+源码下载:https://redstonewill.com/1884/

1.1 SVM深入理解

资料:Python3《机器学习实战》学习笔记(八):支持向量机原理篇之手撕线性SVM,SVM原理详解,公式推导等

  • 线性可分:棍子;非线性可分:kerneling;trick: Optimization
  • 哪个分类器更好?:拥有更大分类间隔的分类器更鲁棒!有左右两个极限位置:越过该位置就会错分
  • 具有最大间隔的决策面就是SVM寻找的最优解。
  • 两侧虚线所穿过的样本点,就是SVM中的支持样本点,称为”支持向量

最优化过程的数学建模:

  • (1)目标函数——分类间隔最宽;希望什么东西的什么指标达到最好

  • (2)优化对象——通过移动决策面。期望通过改变哪些因素来使得目标函数达到最优

对上述两个对象进行建模,“决策面方程”w^TX+b=0,分类间隔方程:|w^TX+b|=1

目的是找出一个分类效果好的超平面作为分类器,分类间隔越大,这个超平面的分类效果越好。所以变成了求解分类间隔d最大的分类器。

  • (3)约束条件:虽然有了目标函数的数学形式,为了求解最大的d,仍有如下问题:即我们的要优化的变量d受到下面条件的限制和约束:
    • 如何判断超平面将样本点正确分类?
    • 向求距离d的最大值,首先要找到支持向量上的点,怎么在众多的点中选出支持向量上的点呢?

针对问题1,假设决策面在间隔区域的中轴线上,且支持向量的样本点到决策面的距离为d,约束公式如下:

第三个公式同时处以了d,也就是说样本点到决策面的距离>d,才预测为1 or -1.

(1)(2)(3)

  • (4)线性SVM优化问题描述

目的是使得d最大化(最大间隔的分类器),d的表达式如下。支持向量又满足如下式子:

我们只关心支持向量上的点,因此我们的目标函数简化为:d=\frac{1}{\left \| w \right \|},那么求max{d}变成了求min{||w||},进一步为min{||w||^2}。等价于支持向量所在的分类间隔要最大!所以d的分子才能为1,这里做了一个概念上的等价替换!

那么就有如下的目标函数和约束条件:分类间距最大,同时满足分类的约束条件:

上述带有不等式约束的优化式子常用的方法是KKT条件。把所有的等式、不等式约束与目标函数f(x)写成一个式子,即拉格朗日乘数法。通过KKT条件,可以求出最优值。KKT条件是可以取得最优值的必要条件。

随后,人们又发现,使用拉格朗日获得的函数,使用求导的方法求解依然困难。进而,需要对问题再进行一次转换,即使用一个数学技巧:拉格朗日对偶

所以,显而易见的是,我们在拉格朗日优化我们的问题这个道路上,需要进行下面二个步骤

  • 将有约束的原始目标函数转换为无约束的新构造的拉格朗日目标函数
  • 使用拉格朗日对偶性,将不易求解的优化问题转化为易求解的优化

将上面的有约束的目标函数转为如下的无约束的拉格朗日目标函数为:

其中αi是拉格朗日乘子,αi大于等于0,是我们构造新目标函数时引入的系数变量(我们自己设置)。现在我们令:

\theta(w)=max_{\alpha_i\geqslant 0}(\frac{1}{2}\left \| w \right \|^2-\sum_{i=1}^{n}\alpha_i(y_i(w^Tx_i+b)-1))

每一个样本都作为约束条件加上去!

这部分的内容要详细推到,一直到SMO怎么求解的,关于SVM的深入分析和理解。暂时放在这里。我当前需要了解如何优化模型,如何分析特征,如何评价和诊断模型。

机器学习——支持向量机SVM(Support Vector Machine)(下)

SVM训练的模型的复杂度由支持向量的个数决定的,而不是数据的维度决定。SVM不太容易过拟合。

SVM训练出的模型完全依赖于支持向量。

一个SVM如果训练得到的支持向量个数比较少,则泛化能力越强。

1.3 SVM中解决泛化问题

机器学习模型的泛化能力不足,有什么改进思路?

2. Matlab svm训练的模型如何在C++中使用

参考网址:http://www.jeepxie.net/article/646115.html

  • 失败,放弃!决定将代码移植到C++中​​​​​​​

7. 分析和优化模型

当前状态:

  • 算法使用HOG+SVM对检测的结果进行了二分类。算法选择上:运动目标建模形成切片+HOG-SVM二分类
  • 训练集:正样本为400m左右的行人251张,负样本100张为检测里面的其他部分,包括误检等
  • 验证集:92张正样本,109张负样本
    • 当前唯一实现是:训练集和验证集是绝对的不重合,不存在重叠元素。且来自同一分布。分别从相同场景下提取的前景目标。
    • 最大问题是:数据量过小,明显的训练集过拟合了,模型泛化能力不行。
    • 最大问题:验证集的设计太小,且不合理。

  • 吴恩达深度学习中表明:数据量<1W的,Train/Dev/Test的比例在60%、20%、20%,即6K训练集,2k验证集和2k测试集
  • Train和Dev,Test的数据源于同一分布。即将所有的数据重新洗牌,放入验证集和测试集。
  • 基于大量数据的简单模型 > 基于少量数据的复杂模型
  • 更多的数据 胜于 聪明的算法
  • 好的数据 胜于 多的数据

  • 数据集数据量不够是一个比较大的问题,有哪些办法可以解决呢?​​
    • (1)多采集一些数据量
    • (2)去公开的红外数据集爬取一些可用的数据集
    • (3)利用别的数据集来训练,用自己的数据集测试。也许迁移学习是可以的哦???当然保持训练集和验证集分布一致是最好的了。
  • 如果已经获得了足够的数据,又该怎么办呢?进行模型优化四部曲
    • (1)训练集指标:过拟合 or 欠拟合?
    • (2)验证集指标:泛化能力不好?增大训练集的正则化?增大训练集的样本数?
    • (3)测试集指标:泛化能力不好,验证集数据增加,或者...
    • (4)Real Life表现:回去改变验证集或代价函数。

2.其他的一些疑问 

  • (1)把验证集里面不通过的hard example直接丢进训练集再训练一遍?
    • 嘿,这不是自欺欺人嘛。选择验证集的目的就是为了测试算法效果,你这样的话还用验证集有什么用呢?不就没用了嘛。所以大多数比赛的测试集都是不公开的啊
  • (2)更多的数据 > 聪明的算法,好的数据 > 多的数据
    • 对于红外数据而言,数据冗余是否是一个问题因为本来目标就小,姿态什么的多样性就比较少!一个人换来换去就那几个姿势和形态,都放进去吗?会不会数据冗余?
      • 这个应该就属于是否是好的数据了,如果冗余的数据不多的话,那么就会是好的数据!
    • 那怎么能够具有区分性呢?现在是靠hog去提取行人的特征,提取到的特征到底是怎么样的,也没有去看?

3. 红外数据集

https://blog.csdn.net/hunnzi/article/details/103445059

(1)KAIST——用于行人检测任务

  • 双光系统,长波红外+可见光。长波红外相机:320*256像素,FLIR-A35。可见光相机:640*480,帧率20fps。
  • 75%的行人输入Medium尺度,在[40,128]pixel;10.38%的行人<20pixel;13.67%的行人>128pixel
  • 有四种标签:person(好分辨);people(难分辨);cyclist(骑车的人);person?(人工不能分辨)。
  • 共计95,328个可见光-红外图像对,总数为103,128个标注,1182个人。

获取地址:https://blog.csdn.net/Lcd_2018_7_18/article/details/103064150 

1. 红外数据集

http://vcipl-okstate.org/pbvs/bench/ OTCBVS数据集里面有用的部分

Dataset 01: OSU Thermal Pedestrian Database

Topic of Interest:
Person detection in thermal imagery. 热成像行人检测 75mm镜头,8楼的房顶拍摄,10个序列共284张图,8-bit灰度图,360*240像素,有ground-truth的txt以及matlab程序可以画bounding box,不包含遮挡的行人,50%可见的行人才进入ground-truth中

Sensor Details:
Raytheon 300D thermal sensor core
75 mm lens 
Camera mounted on rooftop of 8-story building
Gain/focus on manual control

Data Details:
Pedestrian intersection on the Ohio State University campus
Number of sequences = 10
Total number of images = 284
Format of images = 8-bit grayscale bitmap
Image size = 360 x 240 pixels
Sampling rate = non-uniform, less than 30Hz
Environmental information for each sequence provided in subdirectories
Ground truth provided in subdirectories as list of bounding boxes (with approximately same aspect ratio) around people.
For the ground truth data, we selected only those people that were at least 50% visible in the image (i.e., highly occluded people were not selected).

Dataset 03: OSU Color-Thermal Database

彩色和热成像的双光系统,双光融合的目标检测。红外23mm镜头。6个视频序列共17089张图像,8-bit灰度图,320*240pixe的红外图像。还有跟踪的result的文件。

Fusion of color and thermal imagery,
Fusion-based object detection in color and thermal imagery

Sensor Details:
Thermal Sensor: Raytheon PalmIR 250D, 25 mm lens
Color Sensor: Sony TRV87 Handycam

Cameras mounted adjacent to each other on tripod at two locations approximately 3 stories above ground
Gain/focus on manual control

Data Details:
Busy pathway intersections on the Ohio State University campus
Number of color/thermal sequences = 6 (3 at each location)
Total number of images = 17089
Format of images = Thermal: 8-bit grayscale bitmap, Color: 24-bit color bitmap
Image size = 320 x 240 pixels
Sampling rate = approx. 30Hz
Color/Thermal images registered using homography with manually-selected points
Files containing tracking results on the dataset are provided by Alex Leykin

8. 指标方面

 1. 图像指标对应 

为了明确图像指标上的对应,给出如下图示。

  • flir的行人<30pixel的与我们的工程数据<30pixel的不一样
  • 同样height都是30pixel,flir的人看着要近一些。应该是flir的分辨率比1280的要小些。
  • flir只有<30pixel的数据才有意义,因为对应着300m的行人
  • 20pixel height以下的数据就很难识别了,具有轮廓信息还是非常重要的。
  • 300m-30pixel, 400m-20pixel, 500m-16pixel 且降低误识别才是最重要的!
  • 先做<30pixel height的行人识别,重点在于降低误检率!验证集很重要!
% 行人高度、镜头、距离对应得到的Pixel

height = 1.6;%m
distance = 700;%m

f = 55;%55mm镜头
size_p = 12*0.001;%12um像元尺寸12um*10e-3=0.012mm

pixel = f*height / (size_p * distance);
fprintf("距离=%d m \t pixel_height=%f\n",distance,pixel);

 

理论计算距离与pixel的对应 

300m                      400m                                  500m     


2. 正负样本的问题

以下来自:https://stackoverflow.com/questions/25598335/collect-negative-samples-of-adaboost-algorithm-for-face-detection

  • 负样本的选取与问题场景有关。不能是所研究问题毫不相关的场景图片,这样的负样本没有意义
  • 如果不知道应用环境,那就尽量采集多种环境下的图像。
  • 负样本之间不能有太多的相关性
  • 负样本的尺寸应该跟正样本对齐
  • 如果老对一些负样本误识别,可以将这样的负样本丢进训练集再训练一次
  • 负样本的尺寸要一样大。所有的正样本和负样本都要resize到相同的尺寸,resize to exact resolution,same format.
  • 负样本每个stage以两倍的数量递增!负样本为:1k,2k,4k,8k,16k,...,512k,这就是10个stage,累计就是1,024k=102.4W的样本。

分类问题中的正负样本问题,如人脸识别中的例子。负样本的选取与问题场景相关,具体而言,如果你要进行教室中学生的人脸识别,那么负样本就是教室的窗子、墙等等,也就是说,不能是与你要研究的问题毫不相关的乱七八糟的场景图片,这样的负样本并没有意义,还有一个比较好的网址是(http://www.doc.ic.ac.uk/~sgc/teaching/pre2012/v231/lecture10.html)

2.1 样本的数量

训练一个检测器时,每个stage应该要有几千张正负样本。通常一个检测器会有10~20个stage。每个stage会依次递减负样本的数量为上个stage的一半。所以你大概需要3k-10k的正样本,5,000,000~100million的负样本(500万-10亿)。

2.2 负样本

负样本与环境相关,如果你要进行教室中学生的人脸识别,那么负样本就是教室的窗子、墙等等,也就是说,不能是与你要研究的问题毫不相关的乱七八糟的场景图片,这样的负样本并没有意义。如果你不知道你对应用环境,那就尽量采取多种可能的不同的环境图像。

2.3 应该把脸部的局部部位作为负样本吗?如眼睛或鼻子

你可以把眼睛和鼻子作为负样本,但是只将这些作为负样本远远不够。一个探测器的real strength真正韧劲will come from negative images which represent the typical background of the faces。一个探测器的真正韧劲来源于负样本,这些负样本代表了人脸的典型背景

2.4 该怎么收集负样本信息?

你其实并不需要很多负样本,你可以采取1000张图像,然后从中产生10,000,000张负样本。假设你有一张汽车的图片,像素为1k×1k pixels。假设你的人脸识别检测器工作在20×20pixel进行检测,如OpenCV就是这样的。那么你可以将1k×1k的汽车图片剪切成20×20的切片。你也可以获得2500个切片(50×50)。

2.5 在步骤4中。

我必须提醒你注意,负样本之间不能有太多相关性,所以我不建议只从一张图片中截取和产生1百万个负样本。create a library of 1000 images 或从google随机下载数据,确定所有的负样本都不包含人脸。从每个图像中crop截取10,000个负样本,这样得到了大约10million的负样本。训练你的检测器。下一步你可以将每一张图像cut到~50,000张部分重叠的pieces,这样就将负样本扩大到50millions。这样你就会有很好的结果了。

2.6 探测器的最后增强步骤

当你最后已经有一个很好的探测器之后,那么在更多的图像上运行试一下。它会产生误识别。收集所有这些误识别的检测图像,然后将他们加到你的负样本中。然后将检测器再训练一遍。这样的迭代次数越多,你的检测器会更鲁棒。

2.7 real numbers

今天最好的face detectors(如Facebooks)使用了hundreds of millions几百个million(1亿)的正样本,billions10亿负样本。正样本不仅仅是正面的脸,还有各个方向的脸,各种表情的脸,各种年龄的脸,各种性别的脸,各种种族的脸。带着眼镜/帽子/太阳镜/化妆的脸等。你不必要跟最好的比,所以miss掉一些faces时不要get angry。

3. 负样本的concerns

3.1 不同环境下的负样本

  • 如何考虑到不同环境下的使用情况?不同对比度下的~
  • 还是根据用户场景,定制一套流程,进行负样本收集等?

3.2 不同尺度(距离)下的负样本

<100m,200m,300m,400m下的负样本问题,不同距离的负样本的尺度也是不一样的,比如车?比如误检测?

4、目标检测——降低误检测率:负样本制作、增强、训练

目标检测——降低误检测率:负样本制作、增强、训练

如何从负样本的角度去提高模型的识别精度呢?解释如下:

为什么要训练负样本?

  • 训练负样本的目的是为了降低误检测率、误识别率,提高网络模型的泛化能力。通俗地讲就是告诉检测器,这些“不是你要检测的目标”。
  • 负样本的核心目的是:增强泛化能力!

如何收集负样本?

可以通过下面两种方式收集负样本:

  • 采用本任务场景的不包含目标物体的背景图像,例如你的目标是识别某园区内的行人,那么所有本园区内不包含行人的图片都视作负样本。不要使用不属于本任务场景的负图像,因为其对检测器的性能影响不大。
  • 测试图像中被识别错误的目标所在区域。(通常对原图像进行裁剪,使得裁剪下来的图像只包含误识别的物体,而不包含目标)
  • 正负样本必须放在一起训练,不能单独训练负样本,否则经过训练,网络会把所有的图像都识别为背景。
  • 正负样本的比例最好为1:1到1:2左右,数量差距不能太悬殊,特别是正样本数量本来就不太多的情况下。

怎么消除误检测?

  把使用正样本训练好的模型拿来进行测试,此时会得到一些被错误识别的图片。把这些图片收集起来作为负样本加入到正样本集(如果图片中同时包含误识别物体和目标,可以将图像裁剪,裁剪后的图像包含误识别物体而不包含目标并尽量覆盖原图大部分区域,然后再将其分辨率resize回原图大小),组成新的训练集,送入模型进行训练。

       如果负样本的来源只有误识别的图片,那么由于误识别的图片往往占少数,可以利用图像增强(如高斯滤波、对比度增强、锐化、平滑等)的方法扩充负图像数量至和正样本数量相同,并组合在一起。将这样得到的训练集送入模型进行训练,经过若干个epoch当Loss收敛到稳定值时,再次测试原来的出现误识别的图像你会发现误识别现象基本消失了,并且类似原来误识别的场景将会被正确识别。

5、评价指标

虚警概率:false positive / (false positive + true positive),就是1-precision=false alarm。

6、大规模训练结果

  • (1)多采集项目的数据,制作样本切片,达到1k-2k
  • (2)特别是负样本的制作,为正样本的2倍,考虑环境和其他目标。剔除<10pixel的数据。
  • (3)然后再考虑是否进行特征和调参
  • 12
    点赞
  • 92
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值