您现在的位置是:首页 >技术杂谈 >opencv实践项目-人脸检测网站首页技术杂谈
opencv实践项目-人脸检测
简介opencv实践项目-人脸检测
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 << "
This program demonstrates the cascade recognizer. Now you can use Haar or LBP features.
"
"This classifier can recognize many kinds of rigid objects, once the appropriate classifier is trained.
"
"It's most known use is for faces.
"
"Usage:
"
"./ufacedetect [--cascade=<cascade_path> this is the primary trained classifier such as frontal face]
"
" [--nested-cascade[=nested_cascade_path this an optional secondary classifier such as eyes]]
"
" [--scale=<image scale greater or equal to 1, try 1.3 for example>]
"
" [--try-flip]
"
" [filename|camera_index]
"
"see facedetect.cmd for one call:
"
"./ufacedetect --cascade="../../data/haarcascades/haarcascade_frontalface_alt.xml" --nested-cascade="../../data/haarcascades/haarcascade_eye_tree_eyeglasses.xml" --scale=1.3
"
"During execution:
Hit any key to quit.
"
" Using OpenCV version " << CV_VERSION << "
" << 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 the
list 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] = '