Merge pull request #10868 from mshabunin:sample-bgsegm

* Samples: reworked bgfg_bgsegm

* fixup! Samples: reworked bgfg_bgsegm
This commit is contained in:
Maksim Shabunin 2018-02-17 15:04:14 +03:00 committed by Alexander Alekhin
parent 73a8369631
commit aa7a964139

View File

@ -1,111 +1,117 @@
#include "opencv2/core.hpp"
#include <opencv2/core/utility.hpp>
#include "opencv2/imgproc.hpp"
#include "opencv2/video/background_segm.hpp"
#include "opencv2/video.hpp"
#include "opencv2/videoio.hpp"
#include "opencv2/highgui.hpp"
#include <stdio.h>
#include <iostream>
using namespace std;
using namespace cv;
static void help()
{
printf("\nDo background segmentation, especially demonstrating the use of cvUpdateBGStatModel().\n"
"Learns the background at the start and then segments.\n"
"Learning is togged by the space key. Will read from file or camera\n"
"Usage: \n"
" ./bgfg_segm [--camera]=<use camera, if this key is present>, [--file_name]=<path to movie file> \n\n");
}
const char* keys =
{
"{c camera | | use camera or not}"
"{m method |mog2 | method (knn or mog2) }"
"{s smooth | | smooth the mask }"
"{fn file_name|../data/tree.avi | movie file }"
};
//this is a sample for foreground detection functions
int main(int argc, const char** argv)
{
help();
const String keys = "{c camera||use video stream from camera (default is NO)}"
"{fn file_name|../data/tree.avi|video file}"
"{m method|mog2|method: background subtraction algorithm ('knn', 'mog2')}"
"{h help||show help message}";
CommandLineParser parser(argc, argv, keys);
parser.about("This sample demonstrates background segmentation.");
if (parser.has("help"))
{
parser.printMessage();
return 0;
}
bool useCamera = parser.has("camera");
bool smoothMask = parser.has("smooth");
string file = parser.get<string>("file_name");
string method = parser.get<string>("method");
VideoCapture cap;
bool update_bg_model = true;
String file = parser.get<String>("file_name");
String method = parser.get<String>("method");
if (!parser.check())
{
parser.printErrors();
return 1;
}
if( useCamera )
VideoCapture cap;
if (useCamera)
cap.open(0);
else
cap.open(file.c_str());
parser.printMessage();
if( !cap.isOpened() )
if (!cap.isOpened())
{
printf("can not open camera or video file\n");
return -1;
cout << "Can not open video stream: '" << (useCamera ? "<camera 0>" : file) << "'" << endl;
return 2;
}
namedWindow("image", WINDOW_NORMAL);
namedWindow("foreground mask", WINDOW_NORMAL);
namedWindow("foreground image", WINDOW_NORMAL);
namedWindow("mean background image", WINDOW_NORMAL);
Ptr<BackgroundSubtractor> bg_model = method == "knn" ?
createBackgroundSubtractorKNN().dynamicCast<BackgroundSubtractor>() :
createBackgroundSubtractorMOG2().dynamicCast<BackgroundSubtractor>();
Mat img0, img, fgmask, fgimg;
for(;;)
Ptr<BackgroundSubtractor> model;
if (method == "knn")
model = createBackgroundSubtractorKNN();
else if (method == "mog2")
model = createBackgroundSubtractorMOG2();
if (!model)
{
cap >> img0;
cout << "Can not create background model using provided method: '" << method << "'" << endl;
return 3;
}
if( img0.empty() )
cout << "Press <space> to toggle background model update" << endl;
cout << "Press 's' to toggle foreground mask smoothing" << endl;
cout << "Press ESC or 'q' to exit" << endl;
bool doUpdateModel = true;
bool doSmoothMask = false;
Mat inputFrame, frame, foregroundMask, foreground, background;
for (;;)
{
// prepare input frame
cap >> inputFrame;
if (inputFrame.empty())
{
cout << "Finished reading: empty frame" << endl;
break;
resize(img0, img, Size(640, 640*img0.rows/img0.cols), 0, 0, INTER_LINEAR_EXACT);
if( fgimg.empty() )
fgimg.create(img.size(), img.type());
//update the model
bg_model->apply(img, fgmask, update_bg_model ? -1 : 0);
if( smoothMask )
{
GaussianBlur(fgmask, fgmask, Size(11, 11), 3.5, 3.5);
threshold(fgmask, fgmask, 10, 255, THRESH_BINARY);
}
const Size scaledSize(640, 640 * inputFrame.rows / inputFrame.cols);
resize(inputFrame, frame, scaledSize, 0, 0, INTER_LINEAR);
fgimg = Scalar::all(0);
img.copyTo(fgimg, fgmask);
// pass the frame to background model
model->apply(frame, foregroundMask, doUpdateModel ? -1 : 0);
Mat bgimg;
bg_model->getBackgroundImage(bgimg);
// show processed frame
imshow("image", frame);
imshow("image", img);
imshow("foreground mask", fgmask);
imshow("foreground image", fgimg);
if(!bgimg.empty())
imshow("mean background image", bgimg );
char k = (char)waitKey(30);
if( k == 27 ) break;
if( k == ' ' )
// show foreground image and mask (with optional smoothing)
if (doSmoothMask)
{
update_bg_model = !update_bg_model;
if(update_bg_model)
printf("Background update is on\n");
else
printf("Background update is off\n");
GaussianBlur(foregroundMask, foregroundMask, Size(11, 11), 3.5, 3.5);
threshold(foregroundMask, foregroundMask, 10, 255, THRESH_BINARY);
}
if (foreground.empty())
foreground.create(scaledSize, frame.type());
foreground = Scalar::all(0);
frame.copyTo(foreground, foregroundMask);
imshow("foreground mask", foregroundMask);
imshow("foreground image", foreground);
// show background image
model->getBackgroundImage(background);
if (!background.empty())
imshow("mean background image", background );
// interact with user
const char key = (char)waitKey(30);
if (key == 27 || key == 'q') // ESC
{
cout << "Exit requested" << endl;
break;
}
else if (key == ' ')
{
doUpdateModel = !doUpdateModel;
cout << "Toggle background update: " << (doUpdateModel ? "ON" : "OFF") << endl;
}
else if (key == 's')
{
doSmoothMask = !doSmoothMask;
cout << "Toggle foreground mask smoothing: " << (doSmoothMask ? "ON" : "OFF") << endl;
}
}
return 0;
}