harr特征加级联分类器的目标检测系统

推测由于渲染引擎问题,部分公式渲染不正常,公式完整版请移步个人博客

1.识别系统架构

harr_system.png

以上是Harr特征+级联分类器的识别系统架构图,系统分为以下几个部分:

  • 滑动框:固定大小的在原图上滑动的框,用于获取子图
  • Harr特征提取器:在子图上提取指定的四种Harr特征(获取的特征非常多)
  • 级联分类器:基于选定的一些特征,进行分类,筛选出正例

对于该目标识别器,将目标检测问题转换为目标分类问题:滑动框在原图上滑动,识别部分识别每一个滑动子图,判断是否为需要识别的目标。

1.1.Harr特征

Harr特征是一类非常简单的特征,如下图所示有四个框,这四个框的大小是可变的,使用黑色部分覆盖的像素之和减去白色部分覆盖的像素之和即为Harr特征:
Harr(x) = \sum pic_{black}(x) - \sum pic_{white}(x)

harr.png

例如以下图片示意:

harr_example.png

取第一个4x4的区域数据计算第二种harr特征,被黑色覆盖的区域和为3,被白色区域覆盖的和为2,因此可获得基于第二种模板下滑动框的harr特征为3-2=1。对于基于某一个模板,一个候选框可取多个特征,例如对于24x24的滑动框,基于第一种模板(对角线模板),可以在2x2,3x3,...,24x24等多个尺寸取特征,对于2x2的特征而言,也可以在24x24的框内取23x23个特征,因此,每个滑动框的harr特征数量都是海量的,在原论文中,使用20x20的滑动框,每个滑动框有约18k个特征值。

1.2.级联分类器

由于Harr特征数量过多,已经几乎超过任何一种机器学习算法的输入特征数量极限(2001年),因此直接训练一个分类器是不现实的,于是使用多个弱分类器组成一个强分类器的方法训练。在本系统中,每一个弱分类器只针对一个单独的特征:
h_j(x) = \begin{cases} 1 & f_j(x) < \theta_j \\ 0 & other \end{cases}
该级联分类器使用AdaBoost方法训练,训练分类器的同时也筛选特征,最终分类器的级数与使用的特征数量相同(每个分类器只使用一个特征)。最终的分类器为:
h(x) = \begin{cases} 1 & \sum_\limits{t=1}^{T}a_th_t(x) \geq \frac{1}{2}\sum\limits^T_{t=1}a_t \\ 0 & other \end{cases}
T为级联分类器的数量,同时也是选择特征的数量,级联分类器不使用的特征在计算Harr特征时可以不计算以减少计算量;a_t为单个分类器的权重,在训练过程中得到。

2.训练方法

需要训练的部分为级联分类器,由于每个弱分类器仅使用一个特征,因此每个弱分类器的参数为阈值\theta_j。训练算法如下图所示:

harr_train.PNG

首先,初始化样本权值w_{1,i} = \begin{cases}\frac{1}{2m} & y_i = 0 \\ \frac{1}{2l} & y_i = 1\end{cases},其中y_i为当前样本的标签,1表示正例;m和l为反例和正例的数量。进入训练循环后,对于每次迭代:

  1. 首先标准化样本权值w_{t,i} = \cfrac{w_{t,i}}{\sum^n_{j=1}w_{t,j}}
  2. 根据每个特征训练弱分类器h(x),训练过程中,代价函数与样本权值有关,代价函数为\epsilon_j = \sum_iw_i|h_j(x_i)-y_i|
  3. 所有特征对应的弱分类器训练完成后,选择代价函数最低的分类器和对应特征,同时该特征从待选则特征中移除。
  4. 最后更新样本权值:w_{t+1,i} = w_{t,i}\beta_t^{1-e_i},其中e_i = \begin{cases}1 & classifid \ correctly \\ 0 & otherwise \end{cases}\beta_t = \cfrac{\epsilon_t }{1-\epsilon_t}

最终获得分类器h(x)和每个分类器的权值a_t = log\cfrac{1}{\beta_t}

3.加速方法

为了达到较快的检测速度,该系统分别对计算Harr特征和级联分类器提出了加速方案

3.1.积分图

积分图用于加速计算Harr特征,其方法是生成一个与原图片大小相同的图,使用以下公式:
ii(x) = \sum\limits_{x' \leq x,y' \leq y}{i(x',y')}
如下图所示,积分图的数据为以图片对应位置和图片左上角连线为对角线的矩形覆盖的所有像素的和。在按行生成计算图的过程中,每个位置的值可以由计算图上方的数据和这一行之前的累加与该位置的值相加得到,因此计算图的生成比较简单。

harr_in.png

在计算harr特征时,需要计算大量的一定面积像素和,基于积分图,若要计算以下计算区域的和,仅需要计算:A-B-C+D即可,其中ABCD分别为积分图对应位置的值,因此任何一个矩形区域的求和都可以用3次加减法计算完成,有效的加速了Harr特征的提取速度。

harr_compute_im.png

3.2.级联计算

在基本级联分类器需要计算全部所需要的Harr特征,尽管已经使用学习算法筛选过,特征数量仍然较多,基于大部分子图中没有需要识别的物品,提出了级联的方法:

  • 在训练筛选分类器时,不选择误差最小的分类器,而是选择最少的将正例划分为反例的分类器,即召回率最高的分类器。且下一次计算的样本集合为使用该分类器剔除反例的样本集合。
  • 运行时,顺序计算特征-分类,当样本被一个分类器识别为反例时,直接拒绝该样本,后续的特征和分类都可以不被计算。

4.代码实践

4.1.使用自带级联分类器

OpenCV自带了一些级联分类器,可以用于识别人脸,五官和人体等等,在Python下使用方法如下:

face_cascade = cv2.CascadeClassifier("./haarcascades/haarcascade_frontalface_alt2.xml")
faces = face_cascade.detectMultiScale(
        gray, scaleFactor=1.3, minNeighbors=2, minSize=(60, 60), maxSize=(300, 300))

首先调用cv2.CascadeClassifier()打开一个级联分类器,这里载入的xml为OpenCV自带的人脸识别级联分类器,随后调用.detectMultiScale()方法进行识别,参数含义为:

  • 第一个参数image:待识别图片,必须是灰度图片(channel=1)
  • scaleFactor:被检测对象的尺度变化,合理范围1.1~1.4,该参数越大检测越细致,速度越慢
  • minNeighbors:每个候选框需要保持多少个领域,该参数越大,一个候选框被接受越困难
  • minSize和maxSize:目标的最小尺寸和最大尺寸,当目标超过这一范围时无法识别

该函数返回一个list,其中每个元素为一个有4个元素的list,分别是[x,y,w,h],可直接用于绘制矩形框。

4.2.训练级联分类器

选择FDDB数据集训练针对人脸的级联分类器

4.2.1.处理标签

FDDB的标注方式是椭圆形标注,提供椭圆形的中心,长短轴和角度信息,原label为<major_axis_radius minor_axis_radius angle center_x center_y detection_score>,先要将label转为<left_x top_y width height>的格式。考虑简便,使用以下公式:
left\_x = clamp(center\_x - minor\_axis\_radius,0,-1) \\ top\_y = clamp(center\_y - major\_axis\_radius,0,-1) \\ width = 2 \times minor\_axis\_radius \\ height = 2 \times major\_axis\_radius
该公式简单的将椭圆转为矩形,clamp为钳位函数,将输入限制在0~-1,-1表示不限制。同时限制矩形的范围一定在图片范围中。代码如下:

def FDDB2label(source_path, target_path):
    source_list = read_ellipseList(source_path)     //读取原有label文件
    target_list = change_label(source_list)         //转换label格式
    save_rec_label(target_list, target_path)        //保存label格式

转换label的部分如下:

def change_label(source):
    """source:list[[path,label],...],label:[major_axis_radius minor_axis_radius angle center_x center_y detection_score]"""
    result = []
    for name, label in source:
        name = name + ".jpg"
        data = [float(x) for x in label.replace("  ", ' ').split(' ')]
        data = [int(data[3] - data[1]), int(data[4] - data[0]),
                int(data[1] * 2), int(data[0] * 2)]
        data = check_label(name, data, root="../FDDB-folds/")
        result.append(
            [name, data])
    return result

检查部分如下:

def check_label(name, data, root=""):
    img_shape = cv2.imread(os.path.join(root, name)).shape
    if data[0] < 0:
        data[0] = 0
    if data[1] < 0:
        data[1] = 0
    if data[0] + data[2] > img_shape[1]:
        data[2] = img_shape[1] - data[0] - 1
    if data[1] + data[3] > img_shape[0]:
        data[3] = img_shape[0] - data[1] - 1
    return data

共检查两种情况:

  • 物品左上角坐标小于0
  • 物品右下角坐标超过图片限制

4.2.2.准备文件

训练前需要准备数据,包括正例和反例。

4.2.2.1.准备正例

正例使用opencv自带的opencv_createsamples.exe生成,注意该exe文件不可独立运行,因此不能拷贝出来使用,其依赖OpenCV的其他文件,因此必须从OpenCV中调用(opencv\build\x64\vc14\bin\opencv_createsamples.exe),该工具将正例转为.vec文件,主要有以下命令行参数:

  • -vec:输出vec文件的路径
  • -info:正例描述文件路径
  • -num:生成的正例数量
  • -w-h:正例图片的长宽

使用之前,需要准备一个描述正例文件的文件info.dat,其格式如下:

FDDB-folds\2002\08\11\big\img_591.jpg 1 184 38 171 247 
FDDB-folds\2002\07\19\big\img_423.jpg 1 196 46 118 174 
FDDB-folds\2002\08\24\big\img_490.jpg 1 110 23 70 109 
<相对路径> <目标数量n> <目标1的x,y,w,h> ... <目标n的x,y,w,h>

随后使用该工具,生成正例文件pos.vec。

.\opencv\build\x64\vc14\bin\opencv_createsamples.exe -vec .\pos.vec -info info.dat -num 178 -w 40 -h 40

4.2.2.2.准备反例

对于反例,反例只需要准备一个文件列表neg_list.dat即可:

.\dataset\negtive\neg_img2698.jpg
.\dataset\negtive\neg_img2699.jpg
.\dataset\negtive\neg_img2700.jpg
<相对路径>

4.2.3.模型训练

模型训练使用OpenCV的opencv_traincascade.exe,主要的参数如下:

  • -data:最终保存分类器文件的位置
  • -vec:正例vec文件的路径
  • -bg:反例文件列表的路径
  • -numPos-numNeg:正例和反例的数量
  • -numStages:多层分类器的层数
  • -w-h:正例文件的长宽,必须和生成样本时填入的对应长宽相同

本次使用的命令行参数如下图所示:

.\opencv\build\x64\vc14\bin\opencv_traincascade.exe -data . -vec .\pos
.vec -bg .\neg_list.dat -numPos 178 -numNeg 200 -numStages 10 -w 40 -h 40

最终训练的模型会保存在-data/cascade.xml中。

4.2.4.模型测试

可以使用官方提供的测试工具opencv_visualisation.exe测试,该工具会可视化测试过程并打印使用的分类器的类型,命令行参数如下:

  • --image:用于测试的图片路径
  • --model:用于测试的模型(.xml文件)
  • --data:保存测试结果的路径(可选)

官方给出的例子如下:

.\opencv\build\x64\vc14\bin\opencv_visualisation --image=\data\object.png --model=\
data\model.xml --data=\data\result\

参考文献

理论部分:Viola P, Jones M. Rapid object detection using a boosted cascade of simple features[C]// IEEE Computer Society Conference on Computer Vision & Pattern Recognition. IEEE Computer Society, 2001:511.

实践部分:OpenCV官方教程——训练级联分类器

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容