Opencv 3 mask over the face by detectMultiScale - face detection

This tutorial demonstrates how to use OpenCV and C++ to detect faces in an image and replace them with a mask. By following these easy steps, you can achieve results similar to those of many popular face-enhancing applications. The tutorial assumes that you already have a video reader implemented in OpenCV and focuses on applying face detection and overlaying a mask on the detected faces.

Pixel-by-pixel color value filtering

Let me explain how to add a transparent mask over the ROI in a video sequence.

It is easy to overlay an image of an anonymous mask with a white background onto a selected area of a video. The mask is added pixel by pixel, with the condition that it is only applied to the background video if the color of the mask is black. While there are other methods for adding the image over the region of interest (ROI), this approach allows for filtering by pixel color value. 

The condition has the following logic
IF imageMask.at(xx,yy)[0] < 10 Then copy. The black color has a value (0,0,0). The code compares just the value of the mask in one channel[0] on location xx, yy. If the value of a pixel on channel [0] is less than 10. Based on the source mask image which has just values (0,0,0) or (255,255,255) the condition is going to copy the black part. Otherwise, the white part is not copied to the source image which makes the part of the face transparent through the mask. 

Transparent Mask Opnecv




The detectMultiScale in Opencv 3

function takes several parameters that you can adjust to fine-tune face detection.:

 detectMultiScale(Input Image, Output detections, ScaleFactor, minNeighbors, flags, minSize, MaxSize. 

  • scaleFactor: This parameter specifies how much the image size is reduced at each scale. A value of 1.05 means that the image is reduced by 5% at each scale. A smaller value will increase the chance of detecting faces but will also slow down the algorithm.
  • minNeighbors: This parameter specifies how many neighbors each candidate rectangle should have to be retained. A higher value will result in fewer detections but with higher quality.
  • minSize: This parameter specifies the minimum size of objects to be detected. Objects smaller than this size will be ignored.
  • maxSize: This parameter specifies the maximum size of objects to be detected. Objects larger than this size will be ignored.

How to replace the defective part with a Mask pixel-by-pixel

You can replace a single pixel by pixel by: 
image1.at<cv::Vec3b>(y1, x1) = image2.at<cv::Vec3b>(y2, x2); 
The second way is almost similar, but you will replace pixel by pixel in a concrete color channel. 

    // Load the two images
    cv::Mat image1 = cv::imread("image1.jpg");
    cv::Mat image2 = cv::imread("image2.jpg");

    // Coordinates of the pixel to be replaced in image1
    int x1 = 10;
    int y1 = 20;

    // Coordinates of the pixel to be used from image2
    int x2 = 30;
    int y2 = 40;


    // You can do in for position x,y where number in [x]
// y1,x1 are coordinates where tu copy content of pixel
// of image2 from location x2,y2
    // represent the channel B,G,R                    
    image1.at(y1,x1)[0] =  image2.at(x2,y2)[0];                        
    image1.at(y1,x1)[1] =  image2.at(x2,y2)[1];                        
    image1.at(y1,x1)[2] =  image2.at(x2,y2)[2];

    // Save the modified image
    cv::imwrite("modified_image.jpg", image1);

Code Opencv Tutorial - Mask face detection

 The pixel-by-pixel replacement of the detected rectangle by the mask is valid for Opencv 3 and 4. In general, I can recommend replacing CascadeClassifier with some neural network in the DNN module to detect faces. 

//Normal face detection by haar cascade in opencv
  CascadeClassifier faceDetector;
  bool loaded1 = faceDetector.load("facehaarcascade.xml");
  Mat original;  img.copyTo(original);
  std::vector faces;  
  cvtColor(img, img, CV_BGR2GRAY);
  equalizeHist(img, img);
  detectorBody.detectMultiScale(img, faces, 1.1, 2, 0 | 1, Size(40, 40), Size(400,400 ));




Mat Original;
//Read the anonymous mask
Mat imageMask = imread("MASK.png", 1);
// Draw the mask over all rectangles
for( size_t i = 0; i < faces.size(); i++ )
   {
      int xx =0, yy =0;
  // Just iterate in face region pixel by pixel
     for(int x = faces[i].x; x < faces[i].x+faces[i].width; x++)
                {
              for (int y = faces[i].y; y < faces[i].y+faces[i].height; y++)
                    {
                     
                     //This is core of the trick.
                     // Copy Mask to Original image  If the 0 chan
                     // Proper condition is over all color channels
                     // imageMask.at(xx,yy)[0] < 10
                     // imageMask.at(xx,yy)[1] < 10
                     // imageMask.at(xx,yy)[2] < 10
                    // Black Color(0,0,0)
                        if (imageMask.at(xx,yy)[0] < 10)
                        {
                          // Copy to original image on (y,x) places  the pixel of xx,yy mask
                          Original.at(y,x)[0] =  imageMask .at(xx,yy)[0];
                          Original.at(y,x)[1] =  imageMask .at(xx,yy)[1];
                          Original.at(y,x)[2] =  imageMask .at(xx,yy)[2];
                          }
                          // Iterate in mask x
                  xx =xx+1;
            }
      // iterate next row of imageMask
      xx = 0;
      yy =yy+1;
      }
   }
]

Next Post Previous Post
8 Comments
  • fakhri wu
    fakhri wu February 12, 2016 at 4:16 PM

    so interesting! can i have full source code bro? :D

  • Vl
    Vl February 13, 2016 at 1:50 AM

    This is almost full source code! You only need capture video from video file or web camera. Put this image or image sequence into Mat Original; and apply the mask (Code is here). I am sorry this is more than enough. You only need to video input loop.

  • YouLoseBellyFat
    YouLoseBellyFat September 21, 2016 at 2:54 AM

    java codings with examples

  • UplayOnline
    UplayOnline May 25, 2017 at 7:46 AM

    I am sorry this is more than enough. You only need to video input loop.


    โกลเด้นสล็อต



    goldenslot

  • GloriaEasterfan
    GloriaEasterfan July 2, 2017 at 8:46 AM

    Great work! I want to do something like placing image on the eyes. How can I get it done? Any ideas? I'd really love to know. Thank you! :D

  • TONLOVE69
    TONLOVE69 February 4, 2018 at 12:03 AM

    Videos and articles are good and useful.

    goldenslot

  • Unknown
    Unknown February 23, 2018 at 3:04 PM

    This comment has been removed by the author.

  • Unknown
    Unknown April 23, 2018 at 11:42 PM

    It is a subject that is novel and very interesting to follow.

    viva9988 holiday

Add Comment
comment url