算法优化二——如何提高人脸检测正确率

零、检测

  接上篇博文继续探讨人脸检测的相关内容,本文会给出Opencv中自带的人脸检测的相关对比以及Opnev检测中常用的标注等相关操作。人脸检测是一个非常经典的问题,但是还是有一些常见的问题出现在实际使用当中:   (1)误检(把非人脸的物体当作人脸)较多,非人脸图像当作人脸送入后续算法,会引起一系列不良后果。   (2)漏检问题,例如戴墨镜、大胡子、逆光条件、黑种人、倾斜姿态较大的脸无法检测到。

一、人脸检测分类器对比

序号

级联分类器的类型

XML文件名

1

人脸检测器(默认)

haarcascade_frontalface_default.xml

2

人脸检测器(快速的Haar)

haarcascade_frontalface_alt2.xml

3

人脸检测器(快速的LBP)

lbpcascade_frontalface.xml

4

人脸检测器(Tree)

haarcascade_frontalface_alt_tree.xml

5

人脸检测器(Haar_1)

haarcascade_frontalface_alt.xml

Haar特征,毫无疑问Haar特征用在人脸检测里具有里程碑式的意义。博主针对正面人脸分类器进行了实验,总共有4个,alt、alt2、alt_tree、default。对比下来发现alt和alt2的效果比较好,alt_tree耗时较长,default是一个轻量级的,经常出现误检测。针对alt和alt2两者,在同一个视频的对比中检测部分alt要略微好于alt2。接下来是一些具体的对比:

(1)检测时间上对比

图像

Haar_alt

Haar_alt2

lbp

复杂背景图像

2054

2309

948

简单背景图像

912

964

326

(2)检测结果上对比:

图像

Haar_alt

Haar_alt2

lbp

复杂背景图像

70

70

69

简单背景图像

277

283

292

二、detectMultiScale函数

  选择最终的人脸分类器后,若想在这个基础上继续优化,那就试试这个detectMultiScale函数。具体可以查看Opencv源码,下面给出这个函数的讲解:

void detectMultiScale(   
    const Mat& image,   
    CV_OUT vector<Rect>& objects,   
    double scaleFactor = 1.1,   
    int minNeighbors = 3,    
    int flags = 0,   
    Size minSize = Size(),   
    Size maxSize = Size()   
); 

函数介绍: 参数1:image–待检测图片,一般为灰度图像加快检测速度; 参数2:objects–被检测物体的矩形框向量组; 参数3:scaleFactor–表示在前后两次相继的扫描中,搜索窗口的比例系数。默认为1.1即每次搜索窗口依次扩大10%; 参数4:minNeighbors–表示构成检测目标的相邻矩形的最小个数(默认为3个)。 如果组成检测目标的小矩形的个数和小于 min_neighbors - 1 都会被排除。如果min_neighbors 为 0, 则函数不做任何操作就返回所有的被检候选矩形框; 参数5:flags–要么使用默认值,要么使用CV_HAAR_DO_CANNY_PRUNING,函数将会使用Canny边缘检测来排除边缘过多或过少的区域, 因为这些区域通常不会是人脸所在区域; 参数6、7:minSize和maxSize用来限制得到的目标区域的范围。如果视频中误检到很多无用的小方框,那么就把minSize的尺寸改大一些,默认的为30*30。

三、视频标注

  视频标注中必不可少的就是画框和文字标注:

//视频画框
for (vector<Rect>::const_iterator r = faces.begin(); r != faces.end(); r++)
        rectangle(img, cvPoint(r->x, r->y), cvPoint(r->x + r->width - 1, r->y + r->height - 1), Scalar(255, 0, 255), 3, 8, 0);

//文字标注
putText(imgForShow, p.first, Point(BBox.x, BBox.y), FONT_HERSHEY_PLAIN, 2, Scalar(255, 0, 0));

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏java闲聊

JDK1.8 ArrayList 源码解析

当运行 ArrayList<Integer> list = new ArrayList<>() ; ,因为它没有指定初始容量,所以它调用的是它的无参构造

1242
来自专栏项勇

笔记68 | 切换fragmengt的replace和add方法笔记

1524
来自专栏xingoo, 一个梦想做发明家的程序员

20120918-向量实现《数据结构与算法分析》

#include <iostream> #include <list> #include <string> #include <vector> #include...

1856
来自专栏Java Edge

AbstractList源码解析1 实现的方法2 两种内部迭代器3 两种内部类3 SubList 源码分析4 RandomAccessSubList 源码:AbstractList 作为 Lis

它实现了 List 的一些位置相关操作(比如 get,set,add,remove),是第一个实现随机访问方法的集合类,但不支持添加和替换

622
来自专栏刘君君

JDK8的HashMap源码学习笔记

3298
来自专栏计算机视觉与深度学习基础

Leetcode 114 Flatten Binary Tree to Linked List

Given a binary tree, flatten it to a linked list in-place. For example, Given...

2098
来自专栏Hongten

ArrayList VS Vector(ArrayList和Vector的区别)_面试的时候经常出现

2232
来自专栏Phoenix的Android之旅

Java 集合 Vector

List有三种实现,ArrayList, LinkedList, Vector, 它们的区别在于, ArrayList是非线程安全的, Vector则是线程安全...

692
来自专栏聊聊技术

原 初学图论-Kahn拓扑排序算法(Kah

2998
来自专栏xingoo, 一个梦想做发明家的程序员

Spark踩坑——java.lang.AbstractMethodError

百度了一下说是版本不一致导致的。于是重新检查各个jar包,发现spark-sql-kafka的版本是2.2,而spark的版本是2.3,修改spark-sql-...

1260

扫码关注云+社区