步骤:
1、利用Opencv自带的分类器检测人脸
预备知识:Haar特征分类器
Haar特征分类器就是一个XML文件,该文件中会描述人体各个部位的Haar特征值。包括人脸、眼睛、嘴唇等等。
Haar特征分类器存放地址:
(找自己的安装目录)
1、D:\opencv\opencv4.0\opencv4.0.0\sources\data\haarcascades
2、D:\opencv\opencv4.0\opencv4.0.0\build\etc\haarcascades
总览一下:
haarcascade_eye.xml ;仅可以检测睁开的眼睛
haarcascade_eye_tree_eyeglasses.xml;仅在带被检测者戴眼镜时方可检测
haarcascade_frontalcatface.xml
haarcascade_frontalcatface_extended.xml
haarcascade_frontalface_alt.xml
haarcascade_frontalface_alt_tree.xml
haarcascade_frontalface_alt2.xml;个人感觉这个好用点
haarcascade_frontalface_default.xml
haarcascade_fullbody.xml
haarcascade_lefteye_2splits.xml
haarcascade_licence_plate_rus_16stages.xml
haarcascade_lowerbody.xml
haarcascade_profileface.xml
haarcascade_righteye_2splits.xml
haarcascade_russian_plate_number.xml
haarcascade_smile.xml
haarcascade_upperbody.xml
detectMultiScale函数详解
void detectMultiScale(
const Mat& image,
CV_OUT vector<Rect>& objects,
double scaleFactor = 1.1,
int minNeighbors = 3,
int flags = 0,
Size minSize = Size(),
Size maxSize = Size()
);
函数介绍:
参数1:image–待检测图片,一般为灰度图像加快检测速度;
参数2:objects–被检测物体的矩形框向量组;
参数3:scaleFactor–表示在前后两次相继的扫描中,搜索窗口的比例系数。默认为1.1即每次搜索窗口依次扩大10%;
参数4:minNeighbors–表示构成检测目标的相邻矩形的最小个数(默认为3个)。
如果组成检测目标的小矩形的个数和小于 min_neighbors - 1 都会被排除。
如果min_neighbors 为 0, 则函数不做任何操作就返回所有的被检候选矩形框,
这种设定值一般用在用户自定义对检测结果的组合程序上;
参数5:flags–要么使用默认值,要么使用CV_HAAR_DO_CANNY_PRUNING,如果设置为
CV_HAAR_DO_CANNY_PRUNING,那么函数将会使用Canny边缘检测来排除边缘过多或过少的区域,
因此这些区域通常不会是人脸所在区域;
参数6、7:minSize和maxSize用来限制得到的目标区域的范围。
代码实现:
#include <opencv2/opencv.hpp>
#include <iostream>
#include "windows.h"
#include <stdio.h>
#include "My_ImageProssing_base.h"
using namespace cv;
using namespace std;
//训练文件路径
string xmlPath = "D:\\opencv\\opencv4.0\\opencv4.0.0\\build\\etc\\haarcascades\\haarcascade_frontalface_alt2.xml";
int main(int argc, char** atgv) {
Mat img = imread("D:\\opencv_picture_test\\beauty\\裴佳欣.png",0);
//Mat img = imread("D:\\opencv_picture_test\\新垣结衣\\test2.jpg");
imshow("input image", img);
//【1】加载分类器
CascadeClassifier detector;
detector.load(xmlPath);
if (!detector.load(xmlPath)) //加载训练文件
{
cout << "不能加载指定的xml文件" << endl;
return -1;
}
//【2】检测人脸,将信息存储到矩形类faces中
vector<Rect> faces;
//OpenCV的Rect矩形类用法
//如果创建一个Rect对象rect那么rect会有以下几个功能:
//rect.area(); //返回rect的面积
//rect.size(); //返回rect的尺寸
//rect.tl(); //返回rect的左上顶点的坐标
//rect.br(); //返回rect的右下顶点的坐标
//rect.width(); //返回rect的宽度
//rect.height(); //返回rect的高度
//rect.contains(Point(x, y)); //返回布尔变量,判断rect是否包含Point(x, y)点
detector.detectMultiScale(img,faces, 1.1, 3, 0);//分类器对象调用
//【3】框出人脸
for (size_t t = 0; t < faces.size(); t++) {
rectangle(img, faces[t], Scalar(0, 0, 255), 2, 8);
//faces[t]表示第t个的face的矩形类
//2代表线条宽度8是线型,默认取8
}
namedWindow("Result", WINDOW_NORMAL); //定义窗口显示属性
imshow("Result", img);
waitKey(0);
return 0;
}
2、对人脸矩形框内进行一些处理(这里只对灰度图进行处理)
1、打马赛克(这里我们使用均值滤波)
//打马赛克函数
void mosaic(Mat& srcImage, Mat& dstImage, int times)
{
blur(srcImage,dstImage, Size(times*2+1, times * 2 + 1));
}
2、换成其他图片(使用resize,根据人脸区域进行大小改变)//变身乔碧萝
void paste(Mat& srcImage, Mat& dstImage)
{
resize(srcImage,dstImage, dstImage.size());
}
3、美颜磨皮(双边滤波)
void clearFreckle(Mat& srcImage, Mat& dstImage, int times)
{
bilateralFilter(srcImage, dstImage,times, times*2, times/2);
}
4、视频处理
(模板)
VideoCapture capture(0);
//VideoCapture capture("D:\\opencv_picture_test\\videos\\脸.avi");
while (1)
{
Mat img;
capture >> img; //读取当前帧
//imshow("原视频", img); //显示当前帧
cvtColor(img,img, COLOR_BGR2GRAY); //转化为灰度图
Mat dstImage = img.clone();
//【2】检测人脸,将信息存储到矩形类faces中
vector<Rect> faces;
detector.detectMultiScale(img, faces, 1.1, 3, 0);//分类器对象调用
//【3】修改区域信息
.......
//修改完毕
imshow("处理后的视频", dstImage); //显示当前帧
if(waitKey(10) >=0 ) break; //延时10ms
}
完整的代码(视频+贴图):
#include <opencv2/opencv.hpp>
#include <iostream>
#include "windows.h"
#include <stdio.h>
#include "My_ImageProssing_base.h"
using namespace cv;
using namespace std;
//训练文件路径
string xmlPath = "D:\\opencv\\opencv4.0\\opencv4.0.0\\build\\etc\\haarcascades\\haarcascade_frontalface_alt2.xml";
//打马赛克函数
void mosaic(Mat& srcImage, Mat& dstImage, int times)
{
blur(srcImage,dstImage, Size(times*2+1, times * 2 + 1));
}
void clearFreckle(Mat& srcImage, Mat& dstImage, int times)
{
bilateralFilter(srcImage, dstImage,times, times*2, times/2);
}
void paste(Mat& srcImage, Mat& dstImage)
{
resize(srcImage,dstImage, dstImage.size());
}
int main()
{
//Mat img = imread("D:\\opencv_picture_test\\beauty\\裴佳欣.png",0);
Mat img2 = imread("D:\\opencv_picture_test\\趣图景图\\小猪.jpg",0);
//imshow("input image", img);
//【1】加载分类器
CascadeClassifier detector;
detector.load(xmlPath);
if (!detector.load(xmlPath)) //加载训练文件
{
cout << "不能加载指定的xml文件" << endl;
return -1;
}
//调用摄像头
VideoCapture capture(0); //类似于 int a=1;
//VideoCapture capture("D:\\opencv_picture_test\\videos\\脸.avi"); //类似于 int a=1;
while (1)
{
Mat img;
capture >> img; //读取当前帧
//imshow("原视频", img); //显示当前帧
cvtColor(img,img, COLOR_BGR2GRAY); //转化为灰度图
Mat dstImage = img.clone();
//【2】检测人脸,将信息存储到矩形类faces中
vector<Rect> faces;
detector.detectMultiScale(img, faces, 1.1, 3, 0);//分类器对象调用
//【3】修改区域信息
for (size_t t = 0; t < faces.size(); t++)
{
int rows = faces[t].height;
int cols = faces[t].width;
int start_y = faces[t].y;
int start_x = faces[t].x;
Mat ROI(rows, cols, CV_8UC1, Scalar(0));
Mat dstROI(rows, cols, CV_8UC1, Scalar(0));
for (int j = 0;j < rows;j++) //行循环
{
for (int i = 0;i < cols;i++) //列循环
{
//-------【开始处理每个像素】---------------
ROI.at<uchar>(j, i) = img.at<uchar>(j + start_y, i + start_x);
//-------【处理结束】---------------
}
}
//马赛克化
//mosaic(ROI,dstROI,10);
//贴图
paste(img2,dstROI);
//去雀斑(磨皮)
//clearFreckle(ROI, dstROI, 10);
for (int j = 0;j < rows;j++) //行循环
{
for (int i = 0;i < cols;i++) //列循环
{
//-------【开始处理每个像素】---------------
dstImage.at<uchar>(j + start_y, i + start_x) = dstROI.at<uchar>(j, i);
//-------【处理结束】---------------
}
}
}
imshow("处理后的视频", dstImage); //显示当前帧
if(waitKey(10) >=0 ) break; //延时10ms
}
return 0;
}
效果展示
1、马赛克效果
2、磨皮效果(脸蛋更加白净!!!)
3、变身乔碧萝
视频放不上来,就放gif动态图了。
参考链接
haarcascade_eye.xml、eye_tree_eyeglasses.xml、haarcascade_lefteye_2splits.xml区别使用
OpenCV人脸识别–detectMultiScale函数