当前位置:网站首页>人脸识别示例代码解析(二)——人脸识别解析
人脸识别示例代码解析(二)——人脸识别解析
2022-08-09 14:56:00 【LayeZhao】
上一篇我们初步分析了下示例代码facedetector的程序参数解析部分。其中参数解析的过程如下:
其中第4步黄色标注的部分cascadeName,是我们人脸识别分类器的主要参数。
在openCV中,实现了著名的haar特征检测算法,而依托该算法分类器,我们可以实现人脸识别、定位。
该算法基于特征模板的滑动计算图像特征,从而区分物体的显著轮廓。
这些特征模板形似以下图像:
试想用这些黑白二值图像”蒙”在你的图像或部分图像上,然后你原来的图像被分成“黑”“白”两类区域,最后用黑色区域和白色区域的像素进行简单的加减运算,便能得到图像的基本特征。
例如,我们将模板窗口(3)“蒙”在鼻子部位,便能得到相契合的特征,将模板窗口(4)放在双眼部位,同样能得到与双眼部位契合的特征。

但是如何根据不同图像来确定特征模板窗口的大小,和它们应该放置的位置呢。比如上图,我们怎么知道将特定大小的“上黑下白”特征模板固定在图像的高度3/4上?
答案就是,我们让不知劳累的计算机,测试各种位置和大小。
这是一个巨大的工作量,首先我们如果确定具体特征模板窗口大小为24,24。那么我们就得将待检测图像分为若干个24,24大小区域,试图分别用不同特征模板检测*区域图像是否“匹配”某特征,那么单单一个窗口匹配次数是大于160000,这依然将是一个巨大的工作量。

但如果引入级联分类器——Cascade Classifiers,那么工作量就会极大的缩减。
拿人脸检测来讲,先用一些特征,确定该区域图像“有脸”以及“无脸“,丢掉”无脸“部分,然后再用其他特征检测,来进一步确定特征的是否存在,以及确定其特征位置。
这个过程使得我们匹配特征的过程产生一个“级联“的工作模式,每往下走一层,就会”丢掉“一些无关的区域,这样特征就越来越精确。

从上述过程当中我们可以看到,单独一个特征不能确定最终结果,而是多个特征的级联联合使得最终我们能够做出一个精确的判断。
我们把单个特征的检测叫做弱分类器(因为它不能单独确定最终结果),而把这些弱分类器级联成的最终分类器成为强分类器。可见最终的强分类器是在集成算法的基础上构建的。
好吧,言归正传,openCV实现了这个强分类器,用CascadeClassifier类封装该分类器。你可以实例化该类对象,并设计一个训练计划,来训练想要的特征检测器。
对与人脸检测来说,openCV已经帮我们训练好了分类器,该分类器的参数数据保存在一个xml文件中。

在实际使用过程中,这个文件的路径将作为重要的参数和被检测图像一起传给CascadeClassifier对象,接着对被检测图像中人脸进行定位。
而上一篇中,解析出的参数cascadeName,正是这个文件路径
我们接着上一篇,继续往下做,得到cascadeName后,构造CascadeClassifier对象”cascade”。
然后利用classifier对被检测图像进行人脸预测。
同样,我们简化源代码,此次只对单张图像进行检测。
//根据分类器模板路径cascadeName构造级联分类器(CascadeClassifier)对象"cascade"
cv::CascadeClassifier cascade(cascadeName);
//读入被检测图像
Mat image = imread("D:/试验/test/baby.png");
//定义灰度图像,用于暂存原图像对应的灰度图。
Mat gray;
//将原被检测图像从真彩色图像转换为灰度图
cvtColor(image, gray, cv::COLOR_BGR2GRAY);
//定义一个向量(数组),用于存放所检测出的人脸位置(注意:可能并不只有一个人脸)
vector<Rect> faces;
//启动检测
cascade.detectMultiScale(gray,faces);
//用红色矩形绘制人脸位置结果
for (int i = 0; i < faces.size(); i++)
{
cv::rectangle(image, faces[i], Scalar(255, 0, 0));
}
//显示最终被“标记”的图像
imshow("检测人脸", image);
//等待用户输入任意键结束程序
waitKey();
运行结果:

最后发下关于类CasadeClassifier的官方文档解释,本篇博文多是对该文档的总结https://docs.opencv.org/3.4/db/d28/tutorial_cascade_classifier.html
边栏推荐
- Server运维:设置.htaccess按IP和UA禁止访问
- WebGL探索——抉择:实践方向(twgl.js、Filament、Claygl、BabylonJS、ThreeJS、LayaboxJS、SceneJS、ThinkJS、ThingJS)
- Why learn the principles of compiling
- Inverted order at the beginning of the C language 】 【 string (type I like Beijing. Output Beijing. Like I)
- It is deeply recognized that the compiler can cause differences in the compilation results
- 抱抱脸(hugging face)教程-中文翻译-模型概要
- stream去重相同属性对象
- 路由的懒加载与接口的封装
- crontab失效怎么解决
- 抱抱脸(hugging face)教程-中文翻译-基于pipeline的推理
猜你喜欢
随机推荐
抱抱脸(hugging face)教程-中文翻译-预处理
简单记录下offsetof和container_of
Example of file operations - downloading and merging streaming video files
Introduction to OpenCV and build the environment
抱抱脸(hugging face)教程-中文翻译-QA问答(Question Answering)
WebGL:BabylonJS入门——初探:数据展示
微信小程序封装api
名词概念总结(不定期更新~~)
Simple analysis of regularization principle (L1 / L2 regularization)
C写菜单指令的快捷方法
The difference between show and exec in Qt dialog
《身体是革命的本钱,该注意时还是要注意!》
桥接模式下虚拟机连接不上网络的解决方法(WIFI)
关于初级程序员职场如何提升技能的几点建议?
回收站一直显示未清空的图标问题
WebGL:BabylonJS入门——初探:注入活力
抱抱脸(hugging face)教程-中文翻译-使用 AutoClass 加载预训练的实例
Analysis of the common methods and scopes of the three servlet containers
NoUniqueBeanDefinitionException和JSON乱码处理出现异常
升职加薪之SQL索引








