热门标签 | HotTags
当前位置:  开发笔记 > 人工智能 > 正文

给OpenCV初学者的礼物——OpenCV人脸检测入门教程

作者:小月月牙编辑:王萌(深度学习冲鸭公众号)著作权归作者所有,本文仅作学术分享,若侵权,请联系后台删文处理前

作者:小月月牙

编辑:王萌(深度学习冲鸭公众号)

著作权归作者所有,本文仅作学术分享,若侵权,请联系后台删文处理

Mat img = imread("lena.jpg", IMREAD_GRAYSCALE);//以灰度形式读取图片文件

imshow("grayimage", img);//显示img的图像(它是灰度图)

反过来,一个Mat数据,也可以写入文件,这样就把图片给存起来了。举个例子,读取Lena的照片文件,然后存到一个叫out的文件里。

imwrite("image.jpg", M);//显示M的图像

Mat img = imread("lena.jpg", IMREAD_GRAYSCALE);//以灰度形式读取图片文件

imwrite("grayimage.jpg", img);//显示img的图像(它是灰度图)

一个人脸检测的例子

这个例子,需要引用3个OpenCV的头文件:

#include "opencv2/objdetect.hpp"

#include "opencv2/highgui.hpp"

#include "opencv2/imgproc.hpp"


当然,也可以一步到位,把所有的OpenCv库都引了

#include "opencv2/opencv.hpp"

应用iostream库,并使用命名空间来减少代码里面文字的输入量

#include

using namespace std;

using namespace cv;

定义两个分类器,分别用来检测脸和眼睛

CascadeClassifier face_cascade;

CascadeClassifier eyes_cascade;

加载已经训练好的分类器,其中face_cascade_name和eyes_cascade_name是xml格式的分类器文件名。(OpenCV的Github里有已经训练好的模型,可以免费下载)

face_cascade.load( face_cascade_name );

eyes_cascade.load( eyes_cascade_name );

定义一个检测人脸并显示检测结果的函数,函数的输入变量是Mat图像。

void detectAndDisplay( Mat frame )

输入的Mat变量frame是彩色的,色彩信息对检测没什么用。所以我们把它转成灰度图,并标准化。

Mat frame_gray;

cvtColor( frame, frame_gray, COLOR_BGR2GRAY );//转灰度

equalizeHist( frame_gray, frame_gray );//标准化

一张图里有可能会检测到多个人脸,我们可以把检测结果用一个叫faces的向量来存储。用分类器进行多尺度检测的函数叫detectMultiScale,这个函数有两个变量,第一个是输入的图像frame_gray,第二个是输出的结果faces。

std::vector faces;//准备要存入人脸检测结果的向量

face_cascade.detectMultiScale( frame_gray, faces );//检测

由于faces是把检测结果存成了一个向量,所以我们可以用size()函数得到这个向量的长度。下面这个代码循环遍历了每个结果,计算了每张脸的位置。

for ( size_t i = 0; i

{

Point center( faces[i].x + faces[i].width/2, faces[i].y + faces[i].height/2 );//获得每张脸部中心的xy像素坐标

ellipse( frame, center, Size( faces[i].width/2, faces[i].height/2 ), 0, 0, 360, Scalar( 255, 0, 255 ), 4 );//给每个脸画个圈圈框起来

}

上面这个循环里,还可以把检测到个每个脸的区域单独提取出来,再检测一下眼睛。然后嵌入一个用圈圈框出眼睛的循环。这一步,依然使用detectMultiScale函数进行检测。

Mat faceROI = frame_gray( faces[i] );//提取脸部区域

std::vector eyes;//准备要存入眼睛检测结果的向量

eyes_cascade.detectMultiScale( faceROI, eyes );//检测眼睛

for ( size_t j = 0; j

{

Point eye_center( faces[i].x + eyes[j].x + eyes[j].width/2, faces[i].y + eyes[j].y + eyes[j].height/2 );//获得每个眼睛的中心

int radius = cvRound( (eyes[j].width + eyes[j].height)*0.25 );

circle( frame, eye_center, radius, Scalar( 255, 0, 0 ), 4 );//把每个眼睛用圈圈框起来

}

接下来,我们把上面的内容整合一下,这个人脸检测并显示检测结果的函数

detectAndDisplay可以写成这样

void detectAndDisplay( Mat frame )

{

Mat frame_gray;

cvtColor( frame, frame_gray, COLOR_BGR2GRAY );

equalizeHist( frame_gray, frame_gray );

//-- Detect faces

std::vector faces;

face_cascade.detectMultiScale( frame_gray, faces );

for ( size_t i = 0; i

{

Point center( faces[i].x + faces[i].width/2, faces[i].y + faces[i].height/2 );

ellipse( frame, center, Size( faces[i].width/2, faces[i].height/2 ), 0, 0, 360, Scalar( 255, 0, 255 ), 4 );

Mat faceROI = frame_gray( faces[i] );

//-- In each face, detect eyes

std::vector eyes;

eyes_cascade.detectMultiScale( faceROI, eyes );

for ( size_t j = 0; j

{

Point eye_center( faces[i].x + eyes[j].x + eyes[j].width/2, faces[i].y + eyes[j].y + eyes[j].height/2 );

int radius = cvRound( (eyes[j].width + eyes[j].height)*0.25 );

circle( frame, eye_center, radius, Scalar( 255, 0, 0 ), 4 );

}

}

//-- Show what you got

imshow( "Capture - Face detection", frame );

}

实际中,循环读摄像头并用这个detectAndDisplay函数进行检测的代码可以这么写。

Mat frame;//存放摄像头捕获图像的frame变量,它是个Mat数据

while ( capture.read(frame) )//循环把摄像头图像放入frame变量

{

detectAndDisplay( frame );//检测人脸并显示结果

}

最后,我们来写一下主函数,把上面那个摄像头读取和人脸检测功能加上。

int main( int argc, const char** argv )

{

CommandLineParser parser(argc, argv,

"{help h||}"

"{face_cascade|../../data/haarcascades/haarcascade_frontalface_alt.xml|Path to face cascade.}"

"{eyes_cascade|../../data/haarcascades/haarcascade_eye_tree_eyeglasses.xml|Path to eyes cascade.}"

"{camera|0|Camera device number.}");

parser.about( "\nThis program demonstrates using the cv::CascadeClassifier class to detect objects (Face + eyes) in a video stream.\n"

"You can use Haar or LBP features.\n\n" );

parser.printMessage();

String face_cascade_name = parser.get("face_cascade");

String eyes_cascade_name = parser.get("eyes_cascade");

//-- 1. Load the cascades

if( !face_cascade.load( face_cascade_name ) )

{

cout <<"--(!)Error loading face cascade\n";

return -1;

};

if( !eyes_cascade.load( eyes_cascade_name ) )

{

cout <<"--(!)Error loading eyes cascade\n";

return -1;

};

int camera_device &#61; parser.get("camera");

VideoCapture capture;

//-- 2. Read the video stream

capture.open( camera_device );

if ( ! capture.isOpened() )

{

cout <<"--(!)Error opening video capture\n";

return -1;

}

Mat frame;

while ( capture.read(frame) )

{

if( frame.empty() )

{

cout <<"--(!) No captured frame -- Break!\n";

break;

}

//-- 3. Apply the classifier to the frame

detectAndDisplay( frame );

if( waitKey(10) &#61;&#61; 27 )

{

break; // escape

}

}

return 0;

}

人脸检测完整的代码可去下方下载

https://github.com/opencv/opencv/blob/master/samples/cpp/tutorial_code/objectDetection/objectDetection.cpp

已经训练好的分类器可去下方下载

https://github.com/opencv/opencv/tree/master/data/haarcascades

每天进步一丢丢

简要介绍下Tensorflow的计算图

Tensorflow是一个通过计算图的形式来表述计算的编程系统&#xff0c;计算图也叫数据流图&#xff0c;可以把计算图看做是一种有向图&#xff0c;Tensorflow中的每一个计算都是计算图上的一个节点&#xff0c;而节点之间的边描述了计算之间的依赖关系。


推荐阅读
  • 深入解析Java枚举及其高级特性
    本文详细介绍了Java枚举的概念、语法、使用规则和应用场景,并探讨了其在实际编程中的高级应用。所有相关内容已收录于GitHub仓库[JavaLearningmanual](https://github.com/Ziphtracks/JavaLearningmanual),欢迎Star并持续关注。 ... [详细]
  • 机器学习核心概念与技术
    本文系统梳理了机器学习的关键知识点,涵盖模型评估、正则化、线性模型、支持向量机、决策树及集成学习等内容,并深入探讨了各算法的原理和应用场景。 ... [详细]
  • 2017年人工智能领域的十大里程碑事件回顾
    随着2018年的临近,我们一同回顾过去一年中人工智能领域的重要进展。这一年,无论是政策层面的支持,还是技术上的突破,都显示了人工智能发展的迅猛势头。以下是精选的2017年人工智能领域最具影响力的事件。 ... [详细]
  • 多智能体深度强化学习中的分布式奖励估计
    本文探讨了在多智能体系统中应用分布式奖励估计技术,以解决由于环境和代理互动引起的奖励不确定性问题。通过设计多动作分支奖励估计和策略加权奖励聚合方法,本研究旨在提高多智能体强化学习(MARL)的有效性和稳定性。 ... [详细]
  • 本文精选了几所优秀的PHP实训和培训学校,为希望深入学习PHP编程的学员提供参考。 ... [详细]
  • 本文探讨了亚马逊Go如何通过技术创新推动零售业的发展,以及面临的市场和隐私挑战。同时,介绍了亚马逊最新的‘刷手支付’技术及其潜在影响。 ... [详细]
  • 浪潮AI服务器NF5488A5在MLPerf基准测试中刷新多项纪录
    近日,国际权威AI基准测试平台MLPerf发布了最新的推理测试结果,浪潮AI服务器NF5488A5在此次测试中创造了18项性能纪录,显著提升了数据中心AI推理性能。 ... [详细]
  • 图像分类算法的优化策略与实践
    本文探讨了《Bag of Tricks for Image Classification with Convolutional Neural Networks》论文中的多项技术,旨在通过具体实例和实验验证,提高卷积神经网络在图像分类任务中的性能。文章详细介绍了从模型训练加速、网络结构调整到训练参数优化等多个方面的改进方法。 ... [详细]
  • 随着5G、云计算、人工智能、大数据等新技术的广泛应用,人们的生活生产方式发生了深刻变化。从人际互联到万物互联,数据存储与处理需求激增,推动了数据与算力设施的发展。 ... [详细]
  • 吴恩达推出TensorFlow实践课程,Python基础即可入门,四个月掌握核心技能
    量子位报道,deeplearning.ai最新发布了TensorFlow实践课程,适合希望使用TensorFlow开发AI应用的学习者。该课程涵盖机器学习模型构建、图像识别、自然语言处理及时间序列预测等多个方面。 ... [详细]
  • 强人工智能时代,区块链的角色与前景
    随着强人工智能的崛起,区块链技术在新的技术生态中扮演着怎样的角色?本文探讨了区块链与强人工智能之间的互补关系及其在未来技术发展中的重要性。 ... [详细]
  • 本文探讨了图像标签的多种分类场景及其在以图搜图技术中的应用,涵盖了从基础理论到实际项目实施的全面解析。 ... [详细]
  • 京东AI创新之路:周伯文解析京东AI战略的独特之处
    2018年4月15日,京东在北京举办了人工智能创新峰会,会上首次公开了京东AI的整体布局和发展方向。此次峰会不仅展示了京东在AI领域的最新成果,还标志着京东AI团队的首次集体亮相。本文将深入探讨京东AI的发展策略及其与BAT等公司的不同之处。 ... [详细]
  • 如何用GPU服务器运行Python
    如何用GPU服务器运行Python-目录前言一、服务器登录1.1下载安装putty1.2putty远程登录 1.3查看GPU、显卡常用命令1.4Linux常用命令二、 ... [详细]
  • 4000名‘数学基础薄弱’的程序员逆袭成功!揭秘如何学好AI与算法
    对于那些数学基础较差的程序员来说,数学在编程中的重要性往往在工作中才逐渐显现。通过两个实际案例,我们可以深入了解数学如何帮助程序员更好地理解和优化代码。 ... [详细]
author-avatar
mobiledu2502856013
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有