OpenCV 4.x 中请别再用HAAR级联检测器检测人脸!有更好更准的方法
点击我爱计算机视觉标星,更快获取CVML新技术
本文转载自OpenCV学堂。
引言
我写这篇文章是因为我很久以前写过一些文章,用了人脸检测,我当时用的都是HAAR级联检测器,导致最近几个人问我说这个HAAR级联不太准,我跟他们都解释了一下,OpenCV2.4.x跟OpenCV3.0的时候人脸检测都是基于HAAR没错,但是都2020年啦,OpenCV4发布以来,官方支持的人脸检测方法已经转换为基于深度学习的快狠准的方法了。就连HAAR级联训练的工具在OpenCV4中都被除名了。所以与时俱进很重要,希望这篇文章能帮大家厘清OpenCV现在使用的人脸检测技术。
HAAR级联检测器方法
OpenCV3.3之前,一直是OpenCV对象检测在用的,该方法需要使用者有很强的图像处理基础知识,特别要重视预处理跟后处理技术,OpenCV支持该方法的函数为:
void cv::CascadeClassifier::detectMultiScale(InputArray image,std::vector< Rect > & objects,double scaleFactor = 1.1,int minNeighbors = 3,int flags = 0,Size minSize = Size(),Size maxSize = Size()
)
各个参数解释如下:
image:输入图像
objects 人脸框
scaleFactor 放缩比率
minNeighbors 表示最低相邻矩形框
flags 标志项OpenCV3.x以后不用啦,
minSize 可以检测的最小人脸
maxSize 可以检测的最大人脸
简单的代码演示如下:
#include <opencv2/opencv.hpp>
#include <iostream>using namespace cv;
using namespace std;
CascadeClassifier faceDetector;
String haar_data_file = "D:/opencv-4.2.0/opencv/build/etc/haarcascades/haarcascade_frontalface_alt_tree.xml";
int main(int artc, char** argv) {Mat frame, gray;vector<Rect> faces;VideoCapture capture(0);faceDetector.load(haar_data_file);namedWindow("frame", WINDOW_AUTOSIZE);while (true) {capture.read(frame);cvtColor(frame, gray, COLOR_BGR2GRAY);equalizeHist(gray, gray);faceDetector.detectMultiScale(gray, faces, 1.2, 1, 0, Size(30, 30), Size(400, 400));for (size_t t = 0; t < faces.size(); t++) {rectangle(frame, faces[t], Scalar(0, 0, 255), 2, 8, 0);}char c = waitKey(10);if (c == 27) {break;}imshow("frame", frame);}waitKey(0);return 0;
}
OpenCV4 DNN人脸检测
在OpenCV的\sources\samples\dnn\face_detector目录下,有一个download_weights.py脚本文件,首先运行一下,下载模型文件。下载的模型文件分别为:
Caffe模型
res10_300x300_ssd_iter_140000_fp16.caffemodel
deploy.prototxt
tensorflow模型
opencv_face_detector_uint8.pb
opencv_face_detector.pbtxt
其中tensorflow的模型OpenCV官方对它进行了量化处理,大小只有2MB左右,非常适合在各种场景下使用,运行效果如下:
演示代码:
#include <opencv2/dnn.hpp>
#include <opencv2/opencv.hpp>using namespace cv;
using namespace cv::dnn;#include <iostream>
#include <cstdlib>
using namespace std;const size_t inWidth = 300;
const size_t inHeight = 300;
const double inScaleFactor = 1.0;
const Scalar meanVal(104.0, 177.0, 123.0);
const float confidenceThreshold = 0.7;
void face_detect_dnn();
void mtcnn_demo();
int main(int argc, char** argv)
{face_detect_dnn();waitKey(0);return 0;
}void face_detect_dnn() {//String modelDesc = "D:/projects/opencv_tutorial/data/models/resnet/deploy.prototxt";// String modelBinary = "D:/projects/opencv_tutorial/data/models/resnet/res10_300x300_ssd_iter_140000.caffemodel";String modelBinary = "D:/opencv-4.2.0/opencv/sources/samples/dnn/face_detector/opencv_face_detector_uint8.pb";String modelDesc = "D:/opencv-4.2.0/opencv/sources/samples/dnn/face_detector/opencv_face_detector.pbtxt";// 初始化网络// dnn::Net net = readNetFromCaffe(modelDesc, modelBinary);dnn::Net net = readNetFromTensorflow(modelBinary, modelDesc);net.setPreferableBackend(DNN_BACKEND_OPENCV);net.setPreferableTarget(DNN_TARGET_CPU);if (net.empty()){printf("could not load net...\n");return;}// 打开摄像头// VideoCapture capture(0);VideoCapture capture("D:/images/video/Boogie_Up.mp4");if (!capture.isOpened()) {printf("could not load camera...\n");return;}Mat frame;int count=0;while (capture.read(frame)) {int64 start = getTickCount();if (frame.empty()){break;}// 水平镜像调整// flip(frame, frame, 1);imshow("input", frame);if (frame.channels() == 4)cvtColor(frame, frame, COLOR_BGRA2BGR);// 输入数据调整Mat inputBlob = blobFromImage(frame, inScaleFactor,Size(inWidth, inHeight), meanVal, false, false);net.setInput(inputBlob, "data");// 人脸检测Mat detection = net.forward("detection_out");vector<double> layersTimings;double freq = getTickFrequency() / 1000;double time = net.getPerfProfile(layersTimings) / freq;Mat detectionMat(detection.size[2], detection.size[3], CV_32F, detection.ptr<float>());ostringstream ss;for (int i = 0; i < detectionMat.rows; i++){// 置信度 0~1之间float confidence = detectionMat.at<float>(i, 2);if (confidence > confidenceThreshold){count++;int xLeftBottom = static_cast<int>(detectionMat.at<float>(i, 3) * frame.cols);int yLeftBottom = static_cast<int>(detectionMat.at<float>(i, 4) * frame.rows);int xRightTop = static_cast<int>(detectionMat.at<float>(i, 5) * frame.cols);int yRightTop = static_cast<int>(detectionMat.at<float>(i, 6) * frame.rows);Rect object((int)xLeftBottom, (int)yLeftBottom,(int)(xRightTop - xLeftBottom),(int)(yRightTop - yLeftBottom));rectangle(frame, object, Scalar(0, 255, 0));ss << confidence;String conf(ss.str());String label = "Face: " + conf;int baseLine = 0;Size labelSize = getTextSize(label, FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseLine);rectangle(frame, Rect(Point(xLeftBottom, yLeftBottom - labelSize.height),Size(labelSize.width, labelSize.height + baseLine)),Scalar(255, 255, 255), FILLED);putText(frame, label, Point(xLeftBottom, yLeftBottom),FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 0, 0));}}float fps = getTickFrequency() / (getTickCount() - start);ss.str("");ss << "FPS: " << fps << " ; inference time: " << time << " ms";putText(frame, ss.str(), Point(20, 20), 0, 0.75, Scalar(0, 0, 255), 2, 8);imshow("dnn_face_detection", frame);if (waitKey(1) >= 0) break;}printf("total face: %d\n", count);
}
对比总结
1080P的视频文件,两种方法运行检测速度跟总人脸检测数目对比如下(Windows 10 64位,纯CPU运行):
OpenCV4 DNN中的人脸检测吊打HAAR级联检测器人脸检测方法,HAAR级联检测器人脸检测已经凉凉了,建议不要再花太多时间学习,纯属浪费时间而已!
推荐阅读:
目前最强开源人脸检测算法RetinaFace
人脸交流群
关注最新最前沿的人脸检测、识别、配准、重建技术,扫码添加CV君拉你入群,(如已为CV君其他账号好友请直接私信)
(请务必注明:人脸)
喜欢在QQ交流的童鞋,可以加52CV官方QQ群:805388940。
(不会时时在线,如果没能及时通过验证还请见谅)
长按关注我爱计算机视觉
OpenCV 4.x 中请别再用HAAR级联检测器检测人脸!有更好更准的方法相关推荐
- 使用OpenCV,Haar级联检测器进行面部、眼睛、嘴部检测
使用OpenCV,Haar级联检测器进行面部.眼睛.嘴部检测 1. 效果图 2. 原理 2.1 Haar级联是什么? 2.2 Haar级联的问题与局限性 2.3 Haar级联预训练的模型 3. 源码 ...
- 使用 OpenCV与 HAAR 级联算法进行人脸检测和人脸识别
AI人脸识别是一种从数字图像或视频帧中识别或验证人脸的技术.人类可以毫不费力地快速识别面部.这对我们来说是一项轻松的任务,但对计算机来说却是一项艰巨的任务.因为存在各种复杂性,例如低分辨率.遮挡.光照 ...
- OpenCV——Haar级联人眼检测数据
Haar级联 由于灯光.视角.视距.摄像头抖动以及数字噪声的变化,一个图像的细节可能会变得不稳定.但是人们在分类时却不会受这些物理细节方面差异的影响.因此,提取出图像的细节对产生稳定分类结果和跟踪结果 ...
- Python中请不要再用re.compile了
这篇文章主要给大家介绍了关于Python中为何不要再用re.compile的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用python具有一定的参考学习价值,需要的朋友们下面来一起学习学 ...
- 使用Python,dlib中新型、更快、更小的5点面部标志检测器检测人脸、眼睛、鼻子
这篇博客将介绍一个新的dlib面部标志检测器--5点人脸标志模型,它比原始版本更快(提高了8-10%),效率更高,模型更小(降低了10倍). 该5点面部标志检测器被认为是最初随dlib库一起分发的68 ...
- python+opencv选出视频中一帧再利用鼠标回调实现图像上画矩形框
最近因为要实现模板匹配,需要在视频中选中一个目标,然后框出(即作为模板),对其利用模板匹配的方法进行检测.于是需要首先选出视频中的一帧,但是在利用摄像头读视频的过程中我唯一能想到的方法就是: 1.在视 ...
- opencv画框显示python_python+opencv选出视频中一帧再利用鼠标回调实现图像上画矩形框...
最近因为要实现模板匹配,需要在视频中选中一个目标,然后框出(即作为模板),对其利用模板匹配的方法进行检测.于是需要首先选出视频中的一帧,但是在利用摄像头读视频的过程中我唯一能想到的方法就是: 1.在视 ...
- 剑灵私服服务器维护中请稍后再试,玩家惊曝:《剑灵》竟已有中文私服
[17173专稿,未经授权禁止转载] 今日,一些玩家向17173记者爆料称,<剑灵>在国外已有私服可试玩,并支持中文补丁.记者立即进入该私服网站求证,发现该私服确实在运营,但尚未发现任何收 ...
- OpenCV开发笔记(五十四):红胖子8分钟带你深入了解Haar级联分类器进行人脸检测(图文并茂+浅显易懂+程序源码)
若该文为原创文章,未经允许不得转载 原博主博客地址:https://blog.csdn.net/qq21497936 原博主博客导航:https://blog.csdn.net/qq21497936/ ...
最新文章
- 使用autoconf完成编译配置
- Objective-C KVC
- HTMLCSS学习笔记(四)----浮动原理及清浮动
- 多元统计分析-概率,期望,方差,正态分布
- 远程桌面服务怎么测试_快速的远程服务测试
- mvc ajax返回整个页面跳转,在springmvc中的ajax发布调用之后,有什么方法可以将我的页面(jsp)重定向到另一个页面(jsp)...
- Linux操作系统下软件的安装与卸载
- oracle外部结合,浅谈Oracle外部文件
- 5. CopyOnWriteArrayList 的适用场景
- 冒泡排序bubbleSort
- 【软件工程】山东大学软件工程复习提纲
- Windows下的Neo4j下载与安装
- WiFi信道频率对照表
- 涂抹mysql 完整_涂抹MYSQL-跟着三思一步一步学MySQL
- 【Python数据分析学习实例】计算某个函数的一阶导数、二阶导数,并绘出图像
- MEDICI仿真NMOS器件晶体管语法笔记
- linux shell脚本攻略 第三章 以文件之名 find,chmod,touch,head,tail,tree,wc
- 前端面试官常问javaScript编程题,隔壁王大爷看了都会了
- NRF24L01的使用
- icloud安装错误怎么办_怎么办?iCloud云备份失败该如何解决?
热门文章
- Android编译系统简要介绍和学习计划
- python正弦波和等腰三角波_51proteus仿真:生成方波、正弦波、锯齿波和三角波
- HTML是万维网核心语言的第几代,Html5相关的知识点总结
- eclips图片为什么显示不了_为什么要定制工业平板电脑?定制工业平板电脑的七大理由...
- 【tool】将虚拟机从 VMware workstation 转到 vsphere
- android wear 处理器,联发科推Android Wear平台可穿戴处理器
- Ubuntu:查询计算机软硬件信息
- Opencv3 形态学操作
- 【做题】CF119D. String Transformation——KMP
- 俩层判断,判断button是否可以点击