# Save foreground and background in Remove Background

**URL:** <https://forum.opencv.org/t/save-foreground-and-background-in-remove-background/5459>\
**Category:** C++\
**Tags:** video, videoio, core\
**Created:** [October 4, 2021, 12:05pm UTC](https://forum.opencv.org/t/save-foreground-and-background-in-remove-background/5459 "2021-10-04T12:05:23Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![Rainer](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.opencv.org/rainer/32/3285_2.png) [@Rainer](https://forum.opencv.org/u/Rainer)\
**Post date:** [October 4, 2021, 12:05pm UTC](https://forum.opencv.org/t/save-foreground-and-background-in-remove-background/5459/1 "2021-10-04T12:05:23Z")

</div>

Hi

I have compiled the [Remove Background tutorial](https://docs.opencv.org/3.4.15/d1/dc5/tutorial_background_subtraction.html) successfully and it gives me impressive results for my use case. I now have two questions:

1. The tutorial shows the foreground on the screen - how can I save these in a video?
2. How can I save the background in a video?

Thanks

Rainer

---

<div class="post-metadata">

**Author:** ![crackwitz](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.opencv.org/crackwitz/32/14_2.png) [@crackwitz](https://forum.opencv.org/u/crackwitz)\
**Post date:** [October 4, 2021, 12:40pm UTC](https://forum.opencv.org/t/save-foreground-and-background-in-remove-background/5459/2 "2021-10-04T12:40:08Z")

</div>

old tutorial: [OpenCV: Creating a video with OpenCV](https://docs.opencv.org/master/d7/d9e/tutorial_video_write.html)

comparable information, but in python, and smells less dusty: [OpenCV: Getting Started with Videos](https://docs.opencv.org/master/dd/d43/tutorial_py_video_display.html)

---

<div class="post-metadata">

**Author:** ![berak](https://avatars.discourse-cdn.com/v4/letter/b/85f322/32.png) [@berak](https://forum.opencv.org/u/berak)\
**Post date:** [October 4, 2021, 1:41pm UTC](https://forum.opencv.org/t/save-foreground-and-background-in-remove-background/5459/3 "2021-10-04T13:41:48Z")

</div>

also:  
[https://docs.opencv.org/3.4.15/d7/df6/classcv\_1\_1BackgroundSubtractor.html#a98cb8e292a6cbcb32436dad62a82f974](https://docs.opencv.org/3.4.15/d7/df6/classcv_1_1BackgroundSubtractor.html#a98cb8e292a6cbcb32436dad62a82f974)

---

<div class="post-metadata">

**Author:** ![Rainer](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.opencv.org/rainer/32/3285_2.png) [@Rainer](https://forum.opencv.org/u/Rainer)\
**Post date:** [October 5, 2021, 9:12am UTC](https://forum.opencv.org/t/save-foreground-and-background-in-remove-background/5459/4 "2021-10-05T09:12:40Z")

</div>

OK - I am one step further - but I can only save the frame, and not the foreground.

I am using the following code, based on the above mentioned example:

This does not produce a valid output file, while when I replace `output.write(fgMask)` with `output.write(frame)` it gives me a valid video, but as expected with the original content.

```auto
#include <iostream>
#include <sstream>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/video.hpp>
using namespace cv;
using namespace std;
const char* params
    = "{ help h | | Print usage }"
      "{ input | vtest.avi | Path to a video or a sequence of image }"
      "{ algo | MOG2 | Background subtraction method (KNN, MOG2) }";
int main(int argc, char* argv[])
{
    CommandLineParser parser(argc, argv, params);
    parser.about( "This program shows how to use background subtraction methods provided by "
                  " OpenCV. You can process both videos and images.\n" );
    if (parser.has("help"))
    {
        //print help information
        parser.printMessage();
        return 0;
    }
    //create Background Subtractor objects
    Ptr<BackgroundSubtractor> pBackSub;
    if (parser.get<String>("algo") == "MOG2")
        pBackSub = createBackgroundSubtractorMOG2(500, 16, false);
    else
        pBackSub = createBackgroundSubtractorKNN(500, 400.0, false);
    VideoCapture capture( samples::findFile( parser.get<String>("input") ) );
    //Initialize video writer object
    // for saving
int frame_width = static_cast<int>(capture.get(3));
int frame_height = static_cast<int>(capture.get(4));
Size frame_size(frame_width, frame_height);
int fps = 25;
    VideoWriter output("foreground.avi", 
    	VideoWriter::fourcc('M', 'J', 'P', 'G'),
    	fps, 
    	frame_size);
    if (!capture.isOpened()){
        //error in opening the video input
        cerr << "Unable to open: " << parser.get<String>("input") << endl;
        return 0;
    }
    Mat frame, fgMask;
    while (true) {
        capture >> frame;
        if (frame.empty())
            break;
        //update the background model
        pBackSub->apply(frame, fgMask, 0.8);
        //write frame to output file 
        output.write(fgMask);
        //show the current frame and the fg masks
        //imshow("Frame", frame);
        imshow("FG Mask", fgMask);
        //get the input from the keyboard
        int keyboard = waitKey(30);
        if (keyboard == 'q' || keyboard == 27)
            break;
    }
    // Release video writer output
    output.release();

    return 0;
}

```

---

<div class="post-metadata">

**Author:** ![berak](https://avatars.discourse-cdn.com/v4/letter/b/85f322/32.png) [@berak](https://forum.opencv.org/u/berak)\
**Post date:** [October 5, 2021, 9:19am UTC](https://forum.opencv.org/t/save-foreground-and-background-in-remove-background/5459/5 "2021-10-05T09:19:07Z")

</div>

> [@Rainer](#):
>
> ```auto
> VideoWriter output("foreground.avi", 
> VideoWriter::fourcc('M', 'J', 'P', 'G'),
> fps, 
> frame_size,
> false); // <-- those masks are single channel, not bgr !!
> 
> ```

but maybe, you want to save the colour information instead of the bw masks:

```
Mat bgr_mask(frame.size(), CV_8UC3, Scalar::all(0));
frame.copyTo(bgr_mask, fgMask);
output.write(bgr_mask);

```

---

<div class="post-metadata">

**Author:** ![Rainer](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.opencv.org/rainer/32/3285_2.png) [@Rainer](https://forum.opencv.org/u/Rainer)\
**Post date:** [October 5, 2021, 9:43am UTC](https://forum.opencv.org/t/save-foreground-and-background-in-remove-background/5459/6 "2021-10-05T09:43:49Z")

</div>

Thanks @berak - makes sense. But I have tried both approaches you mentioned, but I still don’t get a video which I can play in e.g. vlc player. It is much smaller than the original, which could be explained by the colour depth, but it does not play anything. Am I misunderstanding something here?

---

<div class="post-metadata">

**Author:** ![berak](https://avatars.discourse-cdn.com/v4/letter/b/85f322/32.png) [@berak](https://forum.opencv.org/u/berak)\
**Post date:** [October 5, 2021, 9:47am UTC](https://forum.opencv.org/t/save-foreground-and-background-in-remove-background/5459/7 "2021-10-05T09:47:25Z")

</div>

it wont write any frames, if those dont match what you gave to the VideoWriter ctor (so there’s only the container header in the file on disk)

---

<div class="post-metadata">

**Author:** ![Rainer](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.opencv.org/rainer/32/3285_2.png) [@Rainer](https://forum.opencv.org/u/Rainer)\
**Post date:** [October 5, 2021, 10:03am UTC](https://forum.opencv.org/t/save-foreground-and-background-in-remove-background/5459/8 "2021-10-05T10:03:11Z")

</div>

Thanks berak - it is working now. Perfect. It creates the two videos of the mask and the other one, which are the trails?

For reference, the working code:

```auto
#include <iostream>
#include <sstream>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/video.hpp>
using namespace cv;
using namespace std;
const char* params
    = "{ help h | | Print usage }"
      "{ input | vtest.avi | Path to a video or a sequence of image }"
      "{ algo | MOG2 | Background subtraction method (KNN, MOG2) }";
int main(int argc, char* argv[])
{
    CommandLineParser parser(argc, argv, params);
    parser.about( "This program shows how to use background subtraction methods provided by "
                  " OpenCV. You can process both videos and images.\n" );
    if (parser.has("help"))
    {
        //print help information
        parser.printMessage();
        return 0;
    }
    //create Background Subtractor objects
    Ptr<BackgroundSubtractor> pBackSub;
    if (parser.get<String>("algo") == "MOG2")
        pBackSub = createBackgroundSubtractorMOG2(500, 16, false);
    else
        pBackSub = createBackgroundSubtractorKNN(500, 400.0, false);
    VideoCapture capture( samples::findFile( parser.get<String>("input") ) );
    //Initialize video writer object
    // for saving
    if (!capture.isOpened()){
        //error in opening the video input
        cerr << "Unable to open: " << parser.get<String>("input") << endl;
        return 0;
    }
int frame_width = static_cast<int>(capture.get(3));
int frame_height = static_cast<int>(capture.get(4));
Size frame_size(frame_width, frame_height);
int fps = 25;
    VideoWriter foregroundmask("foregroundmask.avi", 
    	VideoWriter::fourcc('M', 'J', 'P', 'G'),
    	fps, 
    	frame_size,
    	false);
    VideoWriter bgrmask("bgrmask.avi", 
    	VideoWriter::fourcc('M', 'J', 'P', 'G'),
    	fps, 
    	frame_size,
    	true);
    Mat frame, fgMask;
    Mat bgr_mask(frame.size(), CV_8UC3, Scalar::all(0));
    while (true) {
        capture >> frame;
        if (frame.empty())
            break;
        //update the background model
        pBackSub->apply(frame, fgMask, 0.8);

	imshow("FG Mask", fgMask);

	//foregroundmask
	foregroundmask.write(fgMask);
        //imshow("FG Mask", fgMask);
 
        frame.copyTo(bgr_mask, fgMask);
        //write background colour info to foregroundmask file
	bgrmask.write(bgr_mask);
        // imshow("colour", bgr_mask);
        
       //get the input from the keyboard
        int keyboard = waitKey(30);
        if (keyboard == 'q' || keyboard == 27)
            break;
    }
    // Release video writer foregroundmask
    foregroundmask.release();
    bgrmask.release();

    return 0;
}

```

---

<div class="post-metadata">

**Author:** ![berak](https://avatars.discourse-cdn.com/v4/letter/b/85f322/32.png) [@berak](https://forum.opencv.org/u/berak)\
**Post date:** [October 5, 2021, 10:45am UTC](https://forum.opencv.org/t/save-foreground-and-background-in-remove-background/5459/9 "2021-10-05T10:45:04Z")

</div>

> [@Rainer](#):
>
> which are the trails?

sorry i did not understand, explain ? trails ?

---

<div class="post-metadata">

**Author:** ![Rainer](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.opencv.org/rainer/32/3285_2.png) [@Rainer](https://forum.opencv.org/u/Rainer)\
**Post date:** [October 5, 2021, 11:04am UTC](https://forum.opencv.org/t/save-foreground-and-background-in-remove-background/5459/10 "2021-10-05T11:04:24Z")

</div>

These are the trails

 ![Screenshot 2021-10-05 at 13.02.26](https://us1.discourse-cdn.com/flex020/uploads/opencv/original/2X/0/0b5c41208d87a239c5d75021a31310b9a79d7add.jpeg)

---

<div class="post-metadata">

**Author:** ![Rainer](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.opencv.org/rainer/32/3285_2.png) [@Rainer](https://forum.opencv.org/u/Rainer)\
**Post date:** [October 5, 2021, 11:05am UTC](https://forum.opencv.org/t/save-foreground-and-background-in-remove-background/5459/11 "2021-10-05T11:05:02Z")

</div>

And this is the foreground

 ![Screenshot 2021-10-05 at 13.04.42](https://us1.discourse-cdn.com/flex020/uploads/opencv/original/2X/f/fd6515e6845f4a034b82811dbd91c1d9a0c8395b.png)

---

<div class="post-metadata">

**Author:** ![berak](https://avatars.discourse-cdn.com/v4/letter/b/85f322/32.png) [@berak](https://forum.opencv.org/u/berak)\
**Post date:** [October 5, 2021, 11:12am UTC](https://forum.opencv.org/t/save-foreground-and-background-in-remove-background/5459/12 "2021-10-05T11:12:57Z")

</div>

[looks cool](https://de.wikipedia.org/wiki/Nebelkammer) 😉  
(but you probably did not want it …)

> [@Rainer](#):
>
> `Mat bgr_mask(frame.size(), CV_8UC3, Scalar::all(0));`

as long as this is outside/above the loop, you consecutively **add** new dots to an existing image in the copyTo()  
(it’ll only copy, where the mask is white, and leave anything else untouched !)  
you have to build a fresh, black bgr\_mask each time, if you want to avoid it

---

<div class="post-metadata">

**Author:** ![Rainer](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.opencv.org/rainer/32/3285_2.png) [@Rainer](https://forum.opencv.org/u/Rainer)\
**Post date:** [October 5, 2021, 11:58am UTC](https://forum.opencv.org/t/save-foreground-and-background-in-remove-background/5459/13 "2021-10-05T11:58:23Z")

</div>

Makes sense. But even in its current form it is useful.

Thanks a lot.
