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.
#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;
}
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?
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