目录

  • 1. opencv CascadeClassifier人脸检测步骤
  • 2. CascadeClassifier分类器简介
    • 2.1 从文件中加载级联分类器
    • 2.2 目标检测方法
  • 3. 代码实现

1. opencv CascadeClassifier人脸检测步骤

  • 从文件加载级联分类器
  • 读取图片并灰度化
  • resize灰度图
  • 直方图均衡化,得到对比度更强的输出图像
  • detectMultiScale检测

2. CascadeClassifier分类器简介

分类器是判别某个事物是否属于某种分类的器件,其结果要么是,要么不是,级联分类器,可以理解为将 N 个单类的分类器串联起来,如果一个事物能属于这一系列串联起来的的所有分类器,则最终结果就成立,若有一项不符,则判定为不成立。比如人脸,它有很多属性,我们将每个属性做一成个分类器,如果一个模型符合了我们定义的人脸的所有属性,则我们人为这个模型就是一个人脸,比如人脸需要有两条眉毛,两只眼睛,一个鼻子,一张嘴,一个大概 U 形状的下巴或者是轮廓等等。

常用方法:

2.1 从文件中加载级联分类器

CV_WRAP bool load( const String& filename );

也可用于判断级联分类器是否加载成功

2.2 目标检测方法

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

功能:检测输入图像中不同大小的对象。检测到的对象以矩形列表的形式保存
参数:
image: 包含检测对象的图像的 CV_8U 类型矩阵
objects: 矩形的向量,其中每个矩形包含被检测的对象,矩形可以部分位于原始图像之外
scaleFactor: 指定在每个图像缩放时的缩放比例
minNeighbors:指定每个候选矩形需要保留多少个相邻矩形
flags:含义与函数 cvHaarDetectObjects 中的旧级联相同,一般是 0,它不用于新的级联
minSize:对象最小大小,小于该值的对象被忽略
maxSize:最大可能的对象大小,大于这个值的对象被忽略
返回值:无

3. 代码实现

#include "opencv2/objdetect.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/core/ocl.hpp"
#include <iostream>using namespace std;
using namespace cv;static void help()
{cout << "\nThis program demonstrates the cascade recognizer. Now you can use Haar or LBP features.\n""This classifier can recognize many kinds of rigid objects, once the appropriate classifier is trained.\n""It's most known use is for faces.\n""Usage:\n""./ufacedetect [--cascade=<cascade_path> this is the primary trained classifier such as frontal face]\n""   [--nested-cascade[=nested_cascade_path this an optional secondary classifier such as eyes]]\n""   [--scale=<image scale greater or equal to 1, try 1.3 for example>]\n""   [--try-flip]\n""   [filename|camera_index]\n\n""see facedetect.cmd for one call:\n""./ufacedetect --cascade=\"../../data/haarcascades/haarcascade_frontalface_alt.xml\" --nested-cascade=\"../../data/haarcascades/haarcascade_eye_tree_eyeglasses.xml\" --scale=1.3\n\n""During execution:\n\tHit any key to quit.\n""\tUsing OpenCV version " << CV_VERSION << "\n" << endl;
}void detectAndDraw( UMat& img, Mat& canvas, CascadeClassifier& cascade,CascadeClassifier& nestedCascade,double scale, bool tryflip );int main( int argc, const char** argv )
{VideoCapture capture;UMat frame, image;Mat canvas;string inputName;bool tryflip;CascadeClassifier cascade, nestedCascade;double scale;cv::CommandLineParser parser(argc, argv,"{cascade|data/haarcascades/haarcascade_frontalface_alt.xml|}""{nested-cascade|data/haarcascades/haarcascade_eye_tree_eyeglasses.xml|}""{help h ||}{scale|1|}{try-flip||}{@filename||}");if (parser.has("help")){help();return 0;}string cascadeName = samples::findFile(parser.get<string>("cascade"));string nestedCascadeName = samples::findFileOrKeep(parser.get<string>("nested-cascade"));scale = parser.get<double>("scale");tryflip = parser.has("try-flip");inputName = parser.get<string>("@filename");if ( !parser.check()){parser.printErrors();help();return -1;}if ( !nestedCascade.load( nestedCascadeName ) )cerr << "WARNING: Could not load classifier cascade for nested objects: " << nestedCascadeName << endl;if( !cascade.load( cascadeName ) ){cerr << "ERROR: Could not load classifier cascade: " << cascadeName << endl;help();return -1;}cout << "old cascade: " << (cascade.isOldFormatCascade() ? "TRUE" : "FALSE") << endl;if( inputName.empty() || (isdigit(inputName[0]) && inputName.size() == 1) ){int camera = inputName.empty() ? 0 : inputName[0] - '0';if(!capture.open(camera))cout << "Capture from camera #" <<  camera << " didn't work" << endl;}else{inputName = samples::findFileOrKeep(inputName);imread(inputName, IMREAD_COLOR).copyTo(image);if( image.empty() ){if(!capture.open( inputName ))cout << "Could not read " << inputName << endl;}}if( capture.isOpened() ){cout << "Video capturing has been started ..." << endl;for(;;){capture >> frame;if( frame.empty() )break;detectAndDraw( frame, canvas, cascade, nestedCascade, scale, tryflip );char c = (char)waitKey(10);if( c == 27 || c == 'q' || c == 'Q' )break;}}else{cout << "Detecting face(s) in " << inputName << endl;if( !image.empty() ){detectAndDraw( image, canvas, cascade, nestedCascade, scale, tryflip );waitKey(0);}else if( !inputName.empty() ){/* assume it is a text file containing thelist of the image filenames to be processed - one per line */FILE* f = fopen( inputName.c_str(), "rt" );if( f ){char buf[1000+1];while( fgets( buf, 1000, f ) ){int len = (int)strlen(buf);while( len > 0 && isspace(buf[len-1]) )len--;buf[len] = '\0';cout << "file " << buf << endl;imread(samples::findFile(buf), IMREAD_COLOR).copyTo(image);if( !image.empty() ){detectAndDraw( image, canvas, cascade, nestedCascade, scale, tryflip );char c = (char)waitKey(0);if( c == 27 || c == 'q' || c == 'Q' )break;}else{cerr << "Aw snap, couldn't read image " << buf << endl;}}fclose(f);}}}return 0;
}void detectAndDraw( UMat& img, Mat& canvas, CascadeClassifier& cascade,CascadeClassifier& nestedCascade,double scale, bool tryflip )
{double t = 0;vector<Rect> faces, faces2;const static Scalar colors[] ={Scalar(255,0,0),Scalar(255,128,0),Scalar(255,255,0),Scalar(0,255,0),Scalar(0,128,255),Scalar(0,255,255),Scalar(0,0,255),Scalar(255,0,255)};static UMat gray, smallImg;t = (double)getTickCount();cvtColor( img, gray, COLOR_BGR2GRAY );double fx = 1 / scale;resize( gray, smallImg, Size(), fx, fx, INTER_LINEAR_EXACT );equalizeHist( smallImg, smallImg );cascade.detectMultiScale( smallImg, faces,1.1, 3, 0//|CASCADE_FIND_BIGGEST_OBJECT//|CASCADE_DO_ROUGH_SEARCH|CASCADE_SCALE_IMAGE,Size(30, 30) );if( tryflip ){flip(smallImg, smallImg, 1);cascade.detectMultiScale( smallImg, faces2,1.1, 2, 0//|CASCADE_FIND_BIGGEST_OBJECT//|CASCADE_DO_ROUGH_SEARCH|CASCADE_SCALE_IMAGE,Size(30, 30) );for( vector<Rect>::const_iterator r = faces2.begin(); r != faces2.end(); ++r ){faces.push_back(Rect(smallImg.cols - r->x - r->width, r->y, r->width, r->height));}}t = (double)getTickCount() - t;img.copyTo(canvas);double fps = getTickFrequency()/t;static double avgfps = 0;static int nframes = 0;nframes++;double alpha = nframes > 50 ? 0.01 : 1./nframes;avgfps = avgfps*(1-alpha) + fps*alpha;putText(canvas, format("OpenCL: %s, fps: %.1f", ocl::useOpenCL() ? "ON" : "OFF", avgfps), Point(50, 30),FONT_HERSHEY_SIMPLEX, 0.8, Scalar(0,255,0), 2);for ( size_t i = 0; i < faces.size(); i++ ){Rect r = faces[i];vector<Rect> nestedObjects;Point center;Scalar color = colors[i%8];int radius;double aspect_ratio = (double)r.width/r.height;if( 0.75 < aspect_ratio && aspect_ratio < 1.3 ){center.x = cvRound((r.x + r.width*0.5)*scale);center.y = cvRound((r.y + r.height*0.5)*scale);radius = cvRound((r.width + r.height)*0.25*scale);circle( canvas, center, radius, color, 3, 8, 0 );}elserectangle( canvas, Point(cvRound(r.x*scale), cvRound(r.y*scale)),Point(cvRound((r.x + r.width-1)*scale), cvRound((r.y + r.height-1)*scale)),color, 3, 8, 0);if( nestedCascade.empty() )continue;UMat smallImgROI = smallImg(r);nestedCascade.detectMultiScale( smallImgROI, nestedObjects,1.1, 2, 0//|CASCADE_FIND_BIGGEST_OBJECT//|CASCADE_DO_ROUGH_SEARCH//|CASCADE_DO_CANNY_PRUNING|CASCADE_SCALE_IMAGE,Size(30, 30) );for ( size_t j = 0; j < nestedObjects.size(); j++ ){Rect nr = nestedObjects[j];center.x = cvRound((r.x + nr.x + nr.width*0.5)*scale);center.y = cvRound((r.y + nr.y + nr.height*0.5)*scale);radius = cvRound((nr.width + nr.height)*0.25*scale);circle( canvas, center, radius, color, 3, 8, 0 );}}imshow( "result", canvas );
}

该代码为官方示例代码,基本调用方法如下:

example_tapi_ufacedetect --cascade=D:\wyw\opencv\opencv-4.5.0\data\haarcascades\haarcascade_frontalface_alt.xml --nested-cascade=D:\wyw\opencv\opencv-4.5.0\data\haarcascades\haarcascade_eye_tree_eyeglasses.xml --scale=1 --try-flip=true E:\code\other\SeetaFaceDetector\FaceDetector\x64\Release\6.jpg

本文部分引用:https://zhuanlan.zhihu.com/p/159013461

opencv实践项目-人脸检测相关推荐

  1. opencv 美白磨皮人脸检测转

    1. 简介 这学期的计算机视觉课,我们组的课程项目为"照片自动美化",其中我负责的模块为人脸检测与自动磨皮. 功能为:用户上传一张照片,自动检测并定位出照片中的人脸,将照片中所有的 ...

  2. OpenCV + python 实现人脸检测(基于照片和视频进行检测)

    OpenCV + python 实现人脸检测(基于照片和视频进行检测) Haar-like 通俗的来讲,就是作为人脸特征即可. Haar特征值反映了图像的灰度变化情况.例如:脸部的一些特征能由矩形特征 ...

  3. OpenCV OMZ MTCNN人脸检测的实例(附完整代码)

    OpenCV OMZ MTCNN人脸检测的实例 OpenCV OMZ MTCNN人脸检测的实例 OpenCV OMZ MTCNN人脸检测的实例 #include <algorithm> # ...

  4. OpenCV cv::CascadeClassifier人脸检测的实例(附完整代码)

    OpenCV cv::CascadeClassifier人脸检测的实例 OpenCV cv::CascadeClassifier人脸检测的实例 OpenCV cv::CascadeClassifier ...

  5. [Python图像处理] 二十八.OpenCV快速实现人脸检测及视频中的人脸

    该系列文章是讲解Python OpenCV图像处理知识,前期主要讲解图像入门.OpenCV基础用法,中期讲解图像处理的各种算法,包括图像锐化算子.图像增强技术.图像分割等,后期结合深度学习研究图像识别 ...

  6. OpenCV实现视频人脸检测

    利用OpenCV实现视频人脸检测,包含眼部检测.首先,将人脸检测和眼部检测需要的模型文件haarcascade_eye.xml和haarcascade_frontalface_default.xml放 ...

  7. OpenCV vs Dlib 人脸检测比较分析

    点击我爱计算机视觉标星,更快获取CVML新技术 人脸检测是计算机视觉最典型的应用之一,早期OpenCV的logo就是Haar人脸检测的示意图. 很多人的第一个OpenCV学习目标就是跑通Haar级联人 ...

  8. python+opencv+dlib实现人脸检测与表情识别

    python+opencv+dlib实现人脸检测与表情识别 一,dlib简单介绍:Dlib包含广泛的机器学习算法.所有的设计都是高度模块化的,快速执行,并且通过一个干净而现代的C ++ API,使用起 ...

  9. opencv联合dlib人脸检测例子二(加快检测)

    本篇博客是在opencv联合dlib人脸检测例子的基础上改进了下,加快检测流程 观察了下,opencv利用haar级联分类器检测人脸区域的速度要稍快于dlib的frontal_face_detecto ...

最新文章

  1. 操作系统的进程状态变迁图_1.操作系统是干什么的?
  2. kettle从入门到精通_数据分析师的全景职业规划,入门、转行都先看这篇
  3. android studio 初次使用Kotlin(环境准备篇)
  4. java basic类似的地方_java – Shiro使用HTTP Basic Auth或匿名访问相同的URI
  5. rollup学习小记
  6. IoT SaaS加速器——助力阿尔茨海默病人护理
  7. linux代码_Sonar代码走查的配置(linux)
  8. Fedora Linux中配置JDK5或JDK6环境变量
  9. 计算机桌面图标教案,计算机教案模板
  10. 网络故障排除连载之四:OSPF故障排除
  11. Word 特殊符号的插入
  12. android banner无限轮播,LoopBanner - 可以自动轮播的无限循环banner
  13. Android RecyclerView实现类似于老虎机抽奖,数字滚动等动画效果
  14. 加拿大低龄高中留学规划与过程管理三个关键点
  15. 明日风尚杂志明日风尚杂志社明日风尚编辑部2022年第8期目录
  16. Netbeans 7.0 安装 Python 插件的方法
  17. Edge兼容IE,Edge关闭弹窗阻止
  18. 客户管理是企业利润的根本,企业如何进行客户管理呢?
  19. (HBuilder X) 从下载HBuilderX到生成app.apk
  20. MySQL的启动方式

热门文章

  1. Odoo与浪潮合资研发PS Cloud之如何导入带有类别和变体的产品
  2. 2022年5月份面试题集合
  3. 杰理之芯片名字【篇】
  4. 拼多多店铺排名想名列前茅?6招帮你搞定!
  5. c语言输出度为1 的节点,计算机国家二级考试中的度为1和度为2是什么意思?老师说:总结点=叶子节点数+度为1+度为2,都是什么意思?...
  6. js 图片格式转换为jpg_如何将图像转换为JPG格式
  7. 我的新浪博客-软件测试
  8. GitHub是个啥?咋用?
  9. RafyA PS合成作品欣赏(2)
  10. 2、接口固定的修饰符可省略