Commit aa7a9641 authored by Maksim Shabunin's avatar Maksim Shabunin Committed by Alexander Alekhin

Merge pull request #10868 from mshabunin:sample-bgsegm

* Samples: reworked bgfg_bgsegm

* fixup! Samples: reworked bgfg_bgsegm
parent 73a83696
#include "opencv2/core.hpp" #include "opencv2/core.hpp"
#include <opencv2/core/utility.hpp>
#include "opencv2/imgproc.hpp" #include "opencv2/imgproc.hpp"
#include "opencv2/video/background_segm.hpp" #include "opencv2/video.hpp"
#include "opencv2/videoio.hpp" #include "opencv2/videoio.hpp"
#include "opencv2/highgui.hpp" #include "opencv2/highgui.hpp"
#include <stdio.h> #include <iostream>
using namespace std; using namespace std;
using namespace cv; 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) 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); 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 useCamera = parser.has("camera");
bool smoothMask = parser.has("smooth"); String file = parser.get<String>("file_name");
string file = parser.get<string>("file_name"); String method = parser.get<String>("method");
string method = parser.get<string>("method"); if (!parser.check())
VideoCapture cap; {
bool update_bg_model = true; parser.printErrors();
return 1;
}
if( useCamera ) VideoCapture cap;
if (useCamera)
cap.open(0); cap.open(0);
else else
cap.open(file.c_str()); cap.open(file.c_str());
if (!cap.isOpened())
parser.printMessage();
if( !cap.isOpened() )
{ {
printf("can not open camera or video file\n"); cout << "Can not open video stream: '" << (useCamera ? "<camera 0>" : file) << "'" << endl;
return -1; return 2;
} }
namedWindow("image", WINDOW_NORMAL); Ptr<BackgroundSubtractor> model;
namedWindow("foreground mask", WINDOW_NORMAL); if (method == "knn")
namedWindow("foreground image", WINDOW_NORMAL); model = createBackgroundSubtractorKNN();
namedWindow("mean background image", WINDOW_NORMAL); else if (method == "mog2")
model = createBackgroundSubtractorMOG2();
Ptr<BackgroundSubtractor> bg_model = method == "knn" ? if (!model)
createBackgroundSubtractorKNN().dynamicCast<BackgroundSubtractor>() : {
createBackgroundSubtractorMOG2().dynamicCast<BackgroundSubtractor>(); cout << "Can not create background model using provided method: '" << method << "'" << endl;
return 3;
}
Mat img0, img, fgmask, fgimg; 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;
for(;;) Mat inputFrame, frame, foregroundMask, foreground, background;
for (;;)
{ {
cap >> img0; // prepare input frame
cap >> inputFrame;
if( img0.empty() ) if (inputFrame.empty())
{
cout << "Finished reading: empty frame" << endl;
break; break;
}
const Size scaledSize(640, 640 * inputFrame.rows / inputFrame.cols);
resize(inputFrame, frame, scaledSize, 0, 0, INTER_LINEAR);
resize(img0, img, Size(640, 640*img0.rows/img0.cols), 0, 0, INTER_LINEAR_EXACT); // pass the frame to background model
model->apply(frame, foregroundMask, doUpdateModel ? -1 : 0);
if( fgimg.empty() ) // show processed frame
fgimg.create(img.size(), img.type()); imshow("image", frame);
//update the model // show foreground image and mask (with optional smoothing)
bg_model->apply(img, fgmask, update_bg_model ? -1 : 0); if (doSmoothMask)
if( smoothMask )
{ {
GaussianBlur(fgmask, fgmask, Size(11, 11), 3.5, 3.5); GaussianBlur(foregroundMask, foregroundMask, Size(11, 11), 3.5, 3.5);
threshold(fgmask, fgmask, 10, 255, THRESH_BINARY); threshold(foregroundMask, foregroundMask, 10, 255, THRESH_BINARY);
} }
if (foreground.empty())
fgimg = Scalar::all(0); foreground.create(scaledSize, frame.type());
img.copyTo(fgimg, fgmask); foreground = Scalar::all(0);
frame.copyTo(foreground, foregroundMask);
Mat bgimg; imshow("foreground mask", foregroundMask);
bg_model->getBackgroundImage(bgimg); imshow("foreground image", foreground);
imshow("image", img); // show background image
imshow("foreground mask", fgmask); model->getBackgroundImage(background);
imshow("foreground image", fgimg); if (!background.empty())
if(!bgimg.empty()) imshow("mean background image", background );
imshow("mean background image", bgimg );
// interact with user
char k = (char)waitKey(30); const char key = (char)waitKey(30);
if( k == 27 ) break; if (key == 27 || key == 'q') // ESC
if( k == ' ' ) {
cout << "Exit requested" << endl;
break;
}
else if (key == ' ')
{ {
update_bg_model = !update_bg_model; doUpdateModel = !doUpdateModel;
if(update_bg_model) cout << "Toggle background update: " << (doUpdateModel ? "ON" : "OFF") << endl;
printf("Background update is on\n"); }
else else if (key == 's')
printf("Background update is off\n"); {
doSmoothMask = !doSmoothMask;
cout << "Toggle foreground mask smoothing: " << (doSmoothMask ? "ON" : "OFF") << endl;
} }
} }
return 0; return 0;
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment