教你用OpenCV人脸检测自动给头像戴圣诞帽(附代码)

简介:

原图:

 968368b8a8bbefcabe27181aac90ea144835e3f6

效果:

85ff25f0420f8e0c7b756c65b35e4086aa39ffc6 

原理其实很简单:

采用一张圣诞帽的png图像作为素材

 a325d6e4db44f122923a60042f766811bd92f810

利用png图像背景是透明的,贴在背景图片上就是戴帽子的效果了。

人脸检测的目的主要是为了确定贴帽子的位置,类似ps中自由变换的功能,检测到人脸中间的位置(两眼中间),resize圣诞帽子和人脸大小匹配,确定位置,贴上去,ok!

代码:非常简洁,根据参考博客给出的代码,由OpenCV自带的人脸检测代码经过简单修改即可。

// getheader.cpp : 定义控制台应用程序的入口点。  
//  
  
#include "stdafx.h"  
  
#include "opencv2/objdetect/objdetect.hpp"  
#include "opencv2/highgui/highgui.hpp"  
#include "opencv2/imgproc/imgproc.hpp"  
  
#include <iostream>  
#include <stdio.h>  
  
using namespace std;  
using namespace cv;  
  
  
#pragma comment(lib,"opencv_core2410d.lib")                  
#pragma comment(lib,"opencv_highgui2410d.lib")                  
#pragma comment(lib,"opencv_objdetect2410d.lib")     
#pragma comment(lib,"opencv_imgproc2410d.lib")    
  
/** Function Headers */  
void detectAndDisplay( Mat frame );  
  
/** Global variables */  
//-- Note, either copy these two files from opencv/data/haarscascades to your current folder, or change these locations  
String face_cascade_name = "D:\\Program Files\\opencv\\sources\\data\\haarcascades\\haarcascade_frontalface_alt.xml";  
String eyes_cascade_name = "D:\\Program Files\\opencv\\sources\\data\\haarcascades\\haarcascade_eye_tree_eyeglasses.xml";  
CascadeClassifier face_cascade;  
CascadeClassifier eyes_cascade;  
string window_name = "Capture - Face detection";  
RNG rng(12345);  
  
const int FRAME_WIDTH = 1280;  
const int FRAME_HEIGHT = 240;  
/** 
* @function main 
*/  
int main( void )  
{  
    CvCapture* capture;  
    //VideoCapture capture;  
    Mat frame;  
  
    //-- 1. Load the cascades  
    if( !face_cascade.load( face_cascade_name ) ){ printf("--(!)Error loading\n"); return -1; };  
    if( !eyes_cascade.load( eyes_cascade_name ) ){ printf("--(!)Error loading\n"); return -1; };  
  
            frame = imread("19.jpg");//背景图片  
  
            //-- 3. Apply the classifier to the frame  
            if( !frame.empty() )  
            { detectAndDisplay( frame ); }  
              
            waitKey(0);  
      
    return 0;  
}  
  
void mapToMat(const cv::Mat &srcAlpha, cv::Mat &dest, int x, int y)  
{  
    int nc = 3;  
    int alpha = 0;  
  
    for (int j = 0; j < srcAlpha.rows; j++)  
    {  
        for (int i = 0; i < srcAlpha.cols*3; i += 3)  
        {  
            alpha = srcAlpha.ptr<uchar>(j)[i / 3*4 + 3];  
            //alpha = 255-alpha;  
            if(alpha != 0) //4通道图像的alpha判断  
            {  
                for (int k = 0; k < 3; k++)  
                {  
                    // if (src1.ptr<uchar>(j)[i / nc*nc + k] != 0)  
                    if( (j+y < dest.rows) && (j+y>=0) &&  
                        ((i+x*3) / 3*3 + k < dest.cols*3) && ((i+x*3) / 3*3 + k >= 0) &&  
                        (i/nc*4 + k < srcAlpha.cols*4) && (i/nc*4 + k >=0) )  
                    {  
                        dest.ptr<uchar>(j+y)[(i+x*nc) / nc*nc + k] = srcAlpha.ptr<uchar>(j)[(i) / nc*4 + k];  
                    }  
                }  
            }  
        }  
    }  
}  
  
/** 
* @function detectAndDisplay 
*/  
void detectAndDisplay( Mat frame )  
{  
    std::vector<Rect> faces;  
    Mat frame_gray;  
    Mat hatAlpha;  
  
    hatAlpha = imread("2.png",-1);//圣诞帽的图片  
  
    cvtColor( frame, frame_gray, COLOR_BGR2GRAY );  
    equalizeHist( frame_gray, frame_gray );  
    //-- Detect faces  
    face_cascade.detectMultiScale( frame_gray, faces, 1.1, 2, 0|CV_HAAR_SCALE_IMAGE, Size(30, 30) );  
  
    for( size_t i = 0; i < faces.size(); 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 ), 2, 8, 0 );  
  
        // line(frame,Point(faces[i].x,faces[i].y),center,Scalar(255,0,0),5);  
  
        Mat faceROI = frame_gray( faces[i] );  
        std::vector<Rect> eyes;  
  
        //-- In each face, detect eyes  
        eyes_cascade.detectMultiScale( faceROI, eyes, 1.1, 2, 0 |CV_HAAR_SCALE_IMAGE, Size(30, 30) );  
  
        for( size_t j = 0; j < eyes.size(); 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 ), 3, 8, 0 );  
        }  
  
        // if(eyes.size())  
        {  
            resize(hatAlpha,hatAlpha,Size(faces[i].width, faces[i].height),0,0,INTER_LANCZOS4);  
            // mapToMat(hatAlpha,frame,center.x+2.5*faces[i].width,center.y-1.3*faces[i].height);  
            mapToMat(hatAlpha,frame,faces[i].x,faces[i].y-0.8*faces[i].height);  
        }  
    }  
    //-- Show what you got  
    imshow( window_name, frame );  
    imwrite("merry christmas.jpg",frame);  
}  

下面是摄像头实时戴帽子,改下主函数就好了:
 
int main( void )  
{  
    CvCapture* capture;  
    //VideoCapture capture;  
    Mat frame;  
  
    //-- 1. Load the cascades  
    if( !face_cascade.load( face_cascade_name ) ){ printf("--(!)Error loading\n"); return -1; };  
    if( !eyes_cascade.load( eyes_cascade_name ) ){ printf("--(!)Error loading\n"); return -1; };  
  
        //  frame = imread("19.jpg");//背景图片  
  
  
            VideoCapture cap(0); //打开默认的摄像头号  
            if(!cap.isOpened())  //检测是否打开成功  
                return -1;  
  
            Mat edges;  
            //namedWindow("edges",1);  
            for(;;)  
            {  
                Mat frame;  
                cap >> frame; // 从摄像头中获取新的一帧  
                detectAndDisplay( frame );  
                //imshow("edges", frame);  
                if(waitKey(30) >= 0) break;  
            }  
            //摄像头会在VideoCapture的析构函数中释放  
            waitKey(0);  
      
    return 0;  
} 

我的系统的是win10 64位的系统,之前摄像头出来都是黑的,发现需要用vs2010配置一下x64版本方可使用,查了半天还是自己之前写的博客靠谱:

就是按照win7 x64来配置,完美运行:

http://blog.csdn.net/wangyaninglm/article/details/16325283

效果:

92e5b661aabf4872fa05c43a64630efa1ef9b6aa

参考文献:

http://blog.csdn.net/lonelyrains/article/details/50388999

http://docs.opencv.org/doc/tutorials/objdetect/cascade_classifier/cascade_classifier.html

我调试好的工程:

http://download.csdn.net/download/wangyaninglm/9389344


原文发布时间为:2017-12-23

本文作者:流川疯

本文来自云栖社区合作伙伴“数据派THU”,了解相关信息可以关注“数据派THU”微信公众号

相关文章
|
6月前
|
算法 IDE 开发工具
OpenCV常用的 7 个示例:从读取到人脸检测(Python版)
OpenCV常用的 7 个示例:从读取到人脸检测(Python版)
|
计算机视觉 C++ Python
OpenCV人脸检测打卡系统
OpenCV人脸检测打卡系统
88 0
|
5月前
|
机器学习/深度学习 Java 开发工具
【移花接木】OpenCV4.8 For Java 深度学习 实时人脸检测
【移花接木】OpenCV4.8 For Java 深度学习 实时人脸检测
99 0
|
6月前
|
XML 算法 计算机视觉
使用OpenCV进行人脸检测和戴墨镜特效实战(附Python源码)
使用OpenCV进行人脸检测和戴墨镜特效实战(附Python源码)
298 1
|
5月前
|
监控 安全 计算机视觉
实战 | 18行代码轻松实现人脸实时检测【附完整代码与源码详解】Opencv、人脸检测
实战 | 18行代码轻松实现人脸实时检测【附完整代码与源码详解】Opencv、人脸检测
|
5月前
|
机器学习/深度学习 算法 数据可视化
基于OpenCV的人脸检测软件(含Python源码+UI界面+图文详解)
基于OpenCV的人脸检测软件(含Python源码+UI界面+图文详解)
|
6月前
|
前端开发 Java Maven
java集成opencv(不踩坑),实现人脸检测小demo(含上传人像图片识别接口),windows,IDEA,Springboot
java集成opencv(不踩坑),实现人脸检测小demo(含上传人像图片识别接口),windows,IDEA,Springboot
968 0
|
11月前
|
编解码 计算机视觉 Ruby
Python图像处理(二)opencv人脸检测
人脸检测部分,我们需要使用到opencv,看清楚,是opencv,不是opencv_python 首先,我们打开opencv的官网:opencv.org/# 当然,纯英文的。 我们找到library目录下的release目录: 选择你需要的版本,下载对应的平台就好。如下图所示,我当然要尝试最新版的了。 下载完成之后,双击安装就可以了。 我理解的人脸检测呢,其实就是opencv根据采集到的图像与其库中预置的人脸特征去比对,有符合人脸特征的,就说明采集到的图像是有人脸的。初学,我也不清楚我说的是否正确。 有不对的地方,欢迎大佬指出。
72 0
|
文字识别 算法 IDE
OpenCV常用的 7 个示例:从读取到人脸检测(Python版)
OpenCV常用的 7 个示例:从读取到人脸检测(Python版)
|
机器学习/深度学习 人工智能 算法
LabVIEW快速实现OpenCV DNN(YunNet)的人脸检测(含源码)
LabVIEW快速实现OpenCV DNN(YunNet)的人脸检测
577 0
LabVIEW快速实现OpenCV DNN(YunNet)的人脸检测(含源码)