OpenCV实现人脸检测并覆盖面具

来源:互联网 发布:uplay有mac版本吗 编辑:程序博客网 时间:2024/04/29 12:09
#include "stdafx.h"#include <opencv2/highgui/highgui.hpp>#include <opencv2/imgproc/imgproc.hpp>#include <opencv2/objdetect/objdetect.hpp>#include <iostream>using namespace std;using namespace cv;int _tmain(int argc, _TCHAR* argv[]){//输入用于面部识别的人脸级联的xml文件string faceCascadeName = argv[1];//定义级联分类器,并使用facecascade.load()加载级联xml文件CascadeClassifier faceCascade;if( !faceCascade.load(faceCascadeName) ){cerr << "Error loading cascade file. Exiting!" << endl;return -1;}//加载面具图像Mat faceMask = imread(argv[2]);if ( !faceMask.data ){cerr << "Error loading mask image. Exiting!" << endl;}// Current frameMat frame, frameGray;Mat frameROI, faceMaskSmall;Mat grayMaskSmall, grayMaskSmallThresh, grayMaskSmallThreshInv;Mat maskedFace, maskedFrame;char ch;// 创建摄像头对象 并读入摄像头(按照设备号读入)VideoCapture cap(0);// If you cannot open the webcam, stop the execution!if( !cap.isOpened() )return -1;//create GUI windowsnamedWindow("Frame");//,CV_WINDOW_NORMAL);// Scaling factor to resize the input frames from the webcamfloat scalingFactor = 0.75;vector<Rect> faces;// Iterate until the user presses the Esc keywhile(true){// Capture the current framecap >> frame;/* 重置输入图像大小resize(InputArray src, OutputArray dst, Size dsize, double fx=0, double fy=0, int interpolation=INTER_LINEAR )InputArray:原图像OutputArray:目的图像Size dsize:目的图像大小,若未定义则dsize=(fx*src.cols,fy*src.rows)fx:目的图像在原图像宽的基础上的缩放因子fy:目的图像在原图像高的基础上的缩放因子interpolation:图像插值方法(INTER_NEAREST - 最近邻插值,INTER_LINEAR - 线性插值(默认),INTER_AREA - 区域插值,INTER_CUBIC - 三次样条插值,INTER_LANCZOS4 - Lanczos插值)*/resize(frame, frame, Size(), scalingFactor, scalingFactor, INTER_AREA);// 彩色2灰色cvtColor(frame, frameGray, CV_BGR2GRAY);// 直方图均衡化,为了补偿亮度和饱和度等问题equalizeHist(frameGray, frameGray);/* 检测脸部,该函数在输入图像的不同尺度中检测物体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() );image:输入图像objects:检测到的面部矩形区域scaleFactor:图像尺度中的尺度参数,默认为1.1minNeighbors:每一个级联矩形应该保留的近邻个数 默认为3flags:检测标识(CV_HAAR_DO_CANNY_PRUNING利用Canny边缘检测器来排除一些边缘很少或者很多的图像区域,CV_HAAR_SCALE_IMAGE就是按比例正常检测,CV_HAAR_FIND_BIGGEST_OBJECT只检测最大的物体,CV_HAAR_DO_ROUGH_SEARCH只做初略检测)minSize:用来限制得到的目标区域的最小范围maxSize:用来限制得到的目标区域的最大范围*/faceCascade.detectMultiScale(frameGray, faces, 1.1, 2, 0|CV_HAAR_SCALE_IMAGE, Size(30, 30) );// 在脸部画绿色矩形for(int i = 0; i < faces.size(); i++){Rect faceRect(faces[i].x, faces[i].y, faces[i].width, faces[i].height);// 自定义参数以使面具适合脸的大小,你必须调节他来起作用.int x = faces[i].x - int(0.1*faces[i].width);int y = faces[i].y - int(0.0*faces[i].height);/*int w = int(1.1 * faces[i].width);int h = int(1.3 * faces[i].height);*/int w = int(1 * faces[i].width);int h = int(1 * faces[i].height);// 提取感兴趣区域来覆盖面部frameROI = frame(Rect(x,y,w,h));//在ROI上调整面具图像的基础尺寸resize(faceMask, faceMaskSmall, Size(w,h));// 转换面具为灰度图像cvtColor(faceMaskSmall, grayMaskSmall, CV_BGR2GRAY);// 隔离图像上像素的边缘,仅与面具有关(即面具的白色区域剔除),下面函数将大于230像素的值置为0,小于的置为255threshold(grayMaskSmall, grayMaskSmallThresh, 230, 255, CV_THRESH_BINARY_INV);// 通过反转上面的图像创建掩码(因为不希望背景影响叠加)bitwise_not(grayMaskSmallThresh, grayMaskSmallThreshInv);//使用位“与”运算来提取面具精确的边界bitwise_and(faceMaskSmall, faceMaskSmall, maskedFace, grayMaskSmallThresh);// 使用位“与”运算来叠加面具bitwise_and(frameROI, frameROI, maskedFrame, grayMaskSmallThreshInv);// 添加面具,并将其放置在原始图像的ROI来创建最终图像add(maskedFace, maskedFrame, frame(Rect(x,y,w,h)));}imshow("Frame", frame);// Get the keyboard input and check if it's 'Esc'// 27 -> ASCII value of 'Esc' keych = waitKey( 30 );if (ch == 27) {break;}}// 释放the video capture objectcap.release();// 释放窗口destroyAllWindows();return 1;}

原创粉丝点击