Skip to main content

OpenCV : Face Detection

Why do you want to detect face? In general, face detection is used in many areas, such as auto focusing, game, etc. Today, we will make a program to synthesize images on the face by using face detection.



First, we need a "haarcascade_frontalface_alt2.xml" file. This is used for face detect algorithm. We can take this file in following url. 
https://github.com/opencv/opencv/blob/master/data/haarcascades/haarcascade_frontalface_alt2.xml

 And also we need images to synthesize on the face. I made a simple animal head for you.
  

Now, let's start make face detecting program. The full code is as follows.


preprogress.h

#ifndef DETACTFACE_PREPROGRASS_H#define DETACTFACE_PREPROGRASS_H
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;

//load specific cascade file
void load_cascade(CascadeClassifier& cascade, string frame){
    string path = "./res/haarcascades/";
    string full_path = path + frame;
    CV_Assert(cascade.load(full_path)); //CV_Assert is like error exception
}
// convert image coloar to grayMat 
convertToGray(Mat img){
    Mat gray;
    cvtColor(img, gray, CV_BGR2GRAY);
    equalizeHist(gray, gray);
    return gray;
}

// synthesize image and detect face roi
Mat getResultImg(Mat originMat, Mat maskMat, Rect roiRect){
    Mat grayMask;
    Mat mask_inv;
    cvtColor(maskMat, grayMask, CV_BGR2GRAY);
    threshold(grayMask, grayMask, 10, 255, 0);
    bitwise_not(grayMask, mask_inv);

    Mat imgRoi;
    imgRoi = originMat(roiRect);

    Mat back;
    Mat mask_for;

    bitwise_and(maskMat, maskMat, mask_for, grayMask);
    bitwise_and(imgRoi, imgRoi, back, mask_inv);

    Mat dst;
    add(back, mask_for, dst);
    dst.copyTo(imgRoi);
    return originMat;
}
#endif //DETACTFACE_PREPROGRASS_H




main.cpp

#include <iostream>
#include "preprograss.h"
using namespace std;
using namespace cv;

int main() {
    CascadeClassifier face_cascade, eyes_cascade;
    load_cascade(face_cascade, "haarcascade_frontalface_alt2.xml");
    Mat animalImg = imread("./res/pic/animal_head.png");
    Mat frame;
    VideoCapture stream(0);
    if(!stream.isOpened()) cout << "Cannot open camera";
    while (1){
        if (!(stream.read(frame))) break;
        flip(frame, frame, 1); // flip image left and right        
        Mat gray = convertToGray(frame);
        vector<Rect> faces, eyes;
        face_cascade.detectMultiScale(gray, faces, 1.1, 2, 0, Size(100, 100)); // detect face        
        if(faces.size() > 0){
//            rectangle(frame, faces[0], Scalar(0,0,255), 3);            
            Mat newAni;
            float ratio = faces[0].width/animalImg.size().width; // get ratio detected face's width and animal image's width            
            int ani_height = (int)(animalImg.size().height * ratio); // get animal image's height for resizing            
            resize(animalImg, newAni, Size(faces[0].width, ani_height));
            int pointY = (faces[0].y - ani_height) > 0 ? (faces[0].y - ani_height) : 0; // if y coordinate is negative, it is zero            
            frame = getResultImg(frame, newAni, Rect(faces[0].x, pointY, newAni.size().width, newAni.size().height));
        }
        imshow("detact face", frame);

        if (waitKey(5) >= 0) break;
    }
    return 0;
}




  • Detect face
faces.size() is count of detected faces 

face_cascade.detectMultiScale(gray, faces, 1.1, 2, 0, Size(100, 100));

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() );



  • Masking Images
Synthesize two images. This is explained in detail at the link below.
https://canysway.blogspot.kr/2018/05/opencv-tutorial-image-synthesis-roi.html

// synthesize image and detect face roiMat getResultImg(Mat originMat, Mat maskMat, Rect roiRect){
    Mat grayMask;
    Mat mask_inv;
  .... 


Comments

Popular posts from this blog

OpenGL SL - Show Video and Image

The simple image is made like this. void  mainImage(  out   vec4  fragColor,  in   vec2  fragCoord ){      // Normalized pixel coordinates (from 0 to 1)      vec2  uv = fragCoord/iResolution.xy;           //uv.x = uv.x - 0.3;      fragColor =  texture (iChannel0, uv); } I think GPU processing has two major steps. Normalizing and Pointing. 1. Normalizing Each pixel has screen coordinate and we need to normalizing from 0.0 to 1.0, because there are many displays with various resolutions around us. We can not manage it at each resolution. It is very troublesome. So we should normalize it :   vec2   uv = fragCoord/iResolution.xy; 2. Pointing I told you each pixel has a screen coordinate. At each coordinate we need to link with sampler's coordinate. Sampler has also coordinate 0.0 to 1.0. As a result, we see the samplers p...

How to make gaussian blur in SparkAR

 Gaussian blur is result of blurring an image by Gaussian function. We need to use large kernel to make strong blur and this cause the high complexity. And that's why we should use multi-pass which is seperated into horizontal, vertical pass . It can reduce the complexity and make faster. In Spark AR there are many ways to make it. And I wanna introduce one of them using shader files (.sca). You can download it for free from the gumload link below. It is modulated to adjust horizontal, vertical strength easily . Hope this can help you. Loading...

OpenGL SL - Translate, roate, and scale

Translate, rotate and scale are most basic element of image effect. If you didn't understand how make effect at each pixel, please read again before post "Show Video and Image" . 1. Translate Translation means each pixel move parallel on the x, y-axis. In other words, if you want to translate 0.25 on the x-axis, a pixel should point to a distance of -0.25 from the original. Translate ex) void mainImage( out vec4 fragColor, in vec2 fragCoord ){     vec2 uv = fragCoord/iResolution.xy;     if (uv.x < 0.5 ){         // translate to x ( -0.25 )         uv.x += 0.25 ;     } else {         // translate to x ( +0.25 )         uv.x -= 0.25 ;     }     fragColor = texture (iChannel0, uv); } result) 2. Scale Scale also has a  similar concept to parallel translation. If you want to zoom in twice, each pixel s...