|
|
@ -8,15 +8,15 @@ using namespace cv; |
|
|
|
using namespace cv::bgsegm; |
|
|
|
using namespace cv::bgsegm; |
|
|
|
|
|
|
|
|
|
|
|
const String about = |
|
|
|
const String about = |
|
|
|
"\nA program demonstrating the use and capabilities of different background subtraction algrorithms\n" |
|
|
|
"\nA program demonstrating the use and capabilities of different background subtraction algorithms\n" |
|
|
|
"Using OpenCV version " + String(CV_VERSION) + |
|
|
|
"Using OpenCV version " + String(CV_VERSION) + |
|
|
|
"\nPress q or ESC to exit\n"; |
|
|
|
"\n\nPress 'c' to change the algorithm" |
|
|
|
|
|
|
|
"\nPress 'm' to toggle showing only foreground mask or ghost effect" |
|
|
|
|
|
|
|
"\nPress 'n' to change number of threads" |
|
|
|
|
|
|
|
"\nPress SPACE to toggle wait delay of imshow" |
|
|
|
|
|
|
|
"\nPress 'q' or ESC to exit\n"; |
|
|
|
|
|
|
|
|
|
|
|
const String keys = |
|
|
|
const String algos[7] = { "GMG", "CNT", "KNN", "MOG", "MOG2", "GSOC", "LSBP" }; |
|
|
|
"{help h usage ? | | print this message }" |
|
|
|
|
|
|
|
"{vid | | path to a video file }" |
|
|
|
|
|
|
|
"{algo | GMG | name of the algorithm (GMG, CNT, KNN, MOG, MOG2) }" |
|
|
|
|
|
|
|
; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static Ptr<BackgroundSubtractor> createBGSubtractorByName(const String& algoName) |
|
|
|
static Ptr<BackgroundSubtractor> createBGSubtractorByName(const String& algoName) |
|
|
|
{ |
|
|
|
{ |
|
|
@ -31,42 +31,26 @@ static Ptr<BackgroundSubtractor> createBGSubtractorByName(const String& algoName |
|
|
|
algo = createBackgroundSubtractorMOG(); |
|
|
|
algo = createBackgroundSubtractorMOG(); |
|
|
|
else if(algoName == String("MOG2")) |
|
|
|
else if(algoName == String("MOG2")) |
|
|
|
algo = createBackgroundSubtractorMOG2(); |
|
|
|
algo = createBackgroundSubtractorMOG2(); |
|
|
|
|
|
|
|
else if(algoName == String("GSOC")) |
|
|
|
|
|
|
|
algo = createBackgroundSubtractorGSOC(); |
|
|
|
|
|
|
|
else if(algoName == String("LSBP")) |
|
|
|
|
|
|
|
algo = createBackgroundSubtractorLSBP(); |
|
|
|
|
|
|
|
|
|
|
|
return algo; |
|
|
|
return algo; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
int main(int argc, char** argv) |
|
|
|
int main(int argc, char** argv) |
|
|
|
{ |
|
|
|
{ |
|
|
|
CommandLineParser parser(argc, argv, keys); |
|
|
|
CommandLineParser parser(argc, argv, "{@video | vtest.avi | path to a video file}"); |
|
|
|
parser.about(about); |
|
|
|
parser.about(about); |
|
|
|
parser.printMessage(); |
|
|
|
parser.printMessage(); |
|
|
|
if (parser.has("help")) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
parser.printMessage(); |
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
String videoPath = parser.get<String>("vid"); |
|
|
|
String videoPath = samples::findFile(parser.get<String>(0),false); |
|
|
|
String algoName = parser.get<String>("algo"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!parser.check()) |
|
|
|
Ptr<BackgroundSubtractor> bgfs = createBGSubtractorByName(algos[0]); |
|
|
|
{ |
|
|
|
|
|
|
|
parser.printErrors(); |
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Ptr<BackgroundSubtractor> bgfs = createBGSubtractorByName(algoName); |
|
|
|
|
|
|
|
if (!bgfs) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
std::cerr << "Failed to create " << algoName << " background subtractor" << std::endl; |
|
|
|
|
|
|
|
return -1; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VideoCapture cap; |
|
|
|
VideoCapture cap; |
|
|
|
if (argc > 1) |
|
|
|
cap.open(videoPath); |
|
|
|
cap.open(videoPath); |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
cap.open(0); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!cap.isOpened()) |
|
|
|
if (!cap.isOpened()) |
|
|
|
{ |
|
|
|
{ |
|
|
@ -76,24 +60,63 @@ int main(int argc, char** argv) |
|
|
|
|
|
|
|
|
|
|
|
Mat frame, fgmask, segm; |
|
|
|
Mat frame, fgmask, segm; |
|
|
|
|
|
|
|
|
|
|
|
namedWindow("FG Segmentation", WINDOW_NORMAL); |
|
|
|
int delay = 30; |
|
|
|
|
|
|
|
int algo_index = 0; |
|
|
|
|
|
|
|
int nthreads = getNumberOfCPUs(); |
|
|
|
|
|
|
|
bool show_fgmask = false; |
|
|
|
|
|
|
|
|
|
|
|
for (;;) |
|
|
|
for (;;) |
|
|
|
{ |
|
|
|
{ |
|
|
|
cap >> frame; |
|
|
|
cap >> frame; |
|
|
|
|
|
|
|
|
|
|
|
if (frame.empty()) |
|
|
|
if (frame.empty()) |
|
|
|
break; |
|
|
|
{ |
|
|
|
|
|
|
|
cap.set(CAP_PROP_POS_FRAMES, 0); |
|
|
|
|
|
|
|
cap >> frame; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bgfs->apply(frame, fgmask); |
|
|
|
bgfs->apply(frame, fgmask); |
|
|
|
|
|
|
|
|
|
|
|
frame.convertTo(segm, CV_8U, 0.5); |
|
|
|
if (show_fgmask) |
|
|
|
add(frame, Scalar(100, 100, 0), segm, fgmask); |
|
|
|
segm = fgmask; |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
frame.convertTo(segm, CV_8U, 0.5); |
|
|
|
|
|
|
|
add(frame, Scalar(100, 100, 0), segm, fgmask); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
putText(segm, algos[algo_index], Point(10, 30), FONT_HERSHEY_PLAIN, 2.0, Scalar(255, 0, 255), 2, LINE_AA); |
|
|
|
|
|
|
|
putText(segm, format("%d threads", nthreads), Point(10, 60), FONT_HERSHEY_PLAIN, 2.0, Scalar(255, 0, 255), 2, LINE_AA); |
|
|
|
|
|
|
|
|
|
|
|
imshow("FG Segmentation", segm); |
|
|
|
imshow("FG Segmentation", segm); |
|
|
|
|
|
|
|
|
|
|
|
int c = waitKey(30); |
|
|
|
int c = waitKey(delay); |
|
|
|
if (c == 'q' || c == 'Q' || (c & 255) == 27) |
|
|
|
|
|
|
|
|
|
|
|
if (c == ' ') |
|
|
|
|
|
|
|
delay = delay == 30 ? 1 : 30; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (c == 'c' || c == 'C') |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
algo_index++; |
|
|
|
|
|
|
|
if ( algo_index > 6 ) |
|
|
|
|
|
|
|
algo_index = 0; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bgfs = createBGSubtractorByName(algos[algo_index]); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (c == 'n' || c == 'N') |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
nthreads++; |
|
|
|
|
|
|
|
if ( nthreads > 8 ) |
|
|
|
|
|
|
|
nthreads = 1; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
setNumThreads(nthreads); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (c == 'm' || c == 'M') |
|
|
|
|
|
|
|
show_fgmask = !show_fgmask; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (c == 'q' || c == 'Q' || c == 27) |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|