HSV-based background matting demo (opencv)


Design sketch:



This is a simple rough matting demo, based on HSV matting.

Suitable for similar background color.

But because it's demo, it's rough.

In the process of writing, I read a lot of blogs, so a lot of content is learned from Daniel's blog.

If there are similar codes, they are basically learning Daniel's haha.

The main purpose of writing this demo is to get the appropriate HSV values and use them as tools.


Specific content

  • Read the address of the destination image and background image in the configuration file
  • Read the picture and determine if it is successful
    Frame = imread(Add);
    Back = imread(BAdd);
    if (Frame.empty() || Back.empty())
    		cout << "Frame/Back read Failed !" << endl;
    		return -1;


  • Preparations for creating slider windows, etc.
    createTrackbar("Huemin", WIN, &h, hsvMax);
    createTrackbar("Huemax", WIN, &h2, hsvMax);
    createTrackbar("Saturationmin", WIN, &s, hsvMax);
    createTrackbar("Valuemin", WIN, &v, hsvMax);


  • Target image converted to HSV format
    cvtColor(Frame, Hsv, COLOR_BGR2HSV);


  • Processing pictures
    //The color range, which stores the results in the mask  
    inRange(Hsv, Scalar(h, s, v), Scalar(h2, 255, 255), Mask);
    //The image and background of each frame of video are mixed and the result is returned to the result. 
    Mat result = BlendFrame(Frame, Mask);
    string print = format(" Huemin = %d\n 
                            Huemax = %d\n 
                            Saturationmin = %d\n 
                            Valuemin =%d\n\n\n", h, h2, s, v);
    cout << print.c_str() << endl;
    imshow("mask", Mask);
    imshow(WIN, result);


  • Image mixing for each frame
    //Create a result graph  
    cv::Mat result = cv::Mat(frame.size(), frame.type());
    //Image width and channel number  
    int height = result.rows;
    int width = result.cols;
    int channels = result.channels();
    //Pixel value of mask  
    int m = 0;
    //Proportion of fusion  
    double wt = 0;
    //Output pixels 
    int r = 0, g = 0, b = 0; 
    int r1 = 0, g1 = 0, b1 = 0;
    int r2 = 0, g2 = 0, b2 = 0;


  • Cyclic Mixing by Image Width and Height
    //Read the pixel value of the mask 
    m = *pmask++;


  • Judging whether the foreground is background
    //If it's the background  
    if (m == 255)
        //Assignment of three channels  
    	*presult++ = *pbg++;
    	*presult++ = *pbg++;
    	*presult++ = *pbg++;
        //Move the channel of the frame's image's pixels to a single consistency 
    	pframe += 3; 
    //If it's the future  
    else if (m == 0)
    	//Assignment of three channels  
    	*presult++ = *pframe++;
    	*presult++ = *pframe++;
    	*presult++ = *pframe++;
        //Move the channel of the frame's image's pixels to a single consistency  
    	pbg += 3;


  • The rest
    //Three channels per pixel of background image  
    b1 = *pbg++;
    g1 = *pbg++;
    r1 = *pbg++;
    //Three channels per pixel per frame  
    b2 = *pframe++;
    g2 = *pframe++;
    r2 = *pframe++;
    // weight  
    wt = m / 255.0;
    // blend  
    b = b1*wt + b2*(1.0 - wt);
    g = g1*wt + g2*(1.0 - wt);
    r = r1*wt + r2*(1.0 - wt);
    *presult++ = b;
    *presult++ = g;
    *presult++ = r;


  • You can write another output, adjust it to a satisfactory image and export the HSV of the image. Then you can realize the function of a tool to acquire the HSV of the target image.


The results of operation are original map, background map and Mask result map, respectively.




  1. The background size should be the same as the target image.
  2. When processing pictures, it is easy to adjust them by writing them in circles.
  3. When processing HSV images, we can do some edge blurring, so that the fusion will not be too abrupt, but because of the demo, it is not written in this version.


demo address: Waiting for upload...


These are learning notes.

Tags: Windows REST

Posted on Thu, 10 Oct 2019 00:28:35 -0700 by Bottyz