opencv background-subtraction mog

OpenCV: cómo usar createBackgroundSubtractorMOG



background subtraction opencv c++ (4)

De acuerdo con la respuesta anterior, el restador de fondo también se puede definir como:

BackgroundSubtractorMOG MOG;

en lugar de:

Ptr<BackgroundSubtractor> pMOG; pMOG= new BackgroundSubtractorMOG(); //MOG approach

eso también requeriría eliminar pMOG cuando ya no se usa, además functor se puede usar para actualizar la máscara de primer plano de una manera un poco más inteligente:

MOG(newFrame, foregroundMask);

inscribed de:

pMOG->operator()(frame, fgMaskMOG);

La suposición predeterminada de openCV es que el fondo es bastante constante y no necesita ninguna actualización, por lo que, después de la fase inicial de aprendizaje, la Mezcla de gaussianos ya no cambia. Una descripción detallada y clara también se puede encontrar aquí:

http://hal.archives-ouvertes.fr/docs/00/33/82/06/PDF/RPCS_2008.pdf

Estaba tratando de seguir este tutorial en OpenCV.org:

http://docs.opencv.org/trunk/doc/tutorials/video/background_subtraction/background_subtraction.html#background-subtraction

El puntero MOG se inicializa como

Ptr<BackgroundSubtractor> pMOG; //MOG Background subtractor

y en general, se usa de la siguiente manera:

pMOG = createBackgroundSubtractorMOG();

Sin embargo, esto produce el siguiente error:

Error: Identifier "createBackgroundSubtractorMOG" is undefined

Además, cuando se va a actualizar el modelo de fondo, se usa el siguiente comando:

pMOG->apply(frame, fgMaskMOG);

Que a su vez produce el siguiente error:

Error: class "cv::BackgroundSubtractor" has no member "apply"

¿Alguna idea de lo que se puede hacer al respecto? ¡Muchas gracias de antemano!

Aquí está el código completo del tutorial:

//opencv #include <opencv2/highgui/highgui.hpp> #include <opencv2/video/background_segm.hpp> //C #include <stdio.h> //C++ #include <iostream> #include <sstream> using namespace cv; using namespace std; //global variables Mat frame; //current frame Mat fgMaskMOG; //fg mask generated by MOG method Mat fgMaskMOG2; //fg mask fg mask generated by MOG2 method Ptr<BackgroundSubtractor> pMOG; //MOG Background subtractor Ptr<BackgroundSubtractor> pMOG2; //MOG2 Background subtractor int keyboard; //function declarations void help(); void processVideo(char* videoFilename); void processImages(char* firstFrameFilename); void help() { cout << "--------------------------------------------------------------------------" << endl << "This program shows how to use background subtraction methods provided by " << endl << " OpenCV. You can process both videos (-vid) and images (-img)." << endl << endl << "Usage:" << endl << "./bs {-vid <video filename>|-img <image filename>}" << endl << "for example: ./bs -vid video.avi" << endl << "or: ./bs -img /data/images/1.png" << endl << "--------------------------------------------------------------------------" << endl << endl; } int main(int argc, char* argv[]) { //print help information help(); //check for the input parameter correctness if(argc != 3) { cerr <<"Incorret input list" << endl; cerr <<"exiting..." << endl; return EXIT_FAILURE; } //create GUI windows namedWindow("Frame"); namedWindow("FG Mask MOG"); namedWindow("FG Mask MOG 2"); //create Background Subtractor objects pMOG = createBackgroundSubtractorMOG(); //MOG approach pMOG2 = createBackgroundSubtractorMOG2(); //MOG2 approach if(strcmp(argv[1], "-vid") == 0) { //input data coming from a video processVideo(argv[2]); } else if(strcmp(argv[1], "-img") == 0) { //input data coming from a sequence of images processImages(argv[2]); } else { //error in reading input parameters cerr <<"Please, check the input parameters." << endl; cerr <<"Exiting..." << endl; return EXIT_FAILURE; } //destroy GUI windows destroyAllWindows(); return EXIT_SUCCESS; } void processVideo(char* videoFilename) { //create the capture object VideoCapture capture(videoFilename); if(!capture.isOpened()){ //error in opening the video input cerr << "Unable to open video file: " << videoFilename << endl; exit(EXIT_FAILURE); } //read input data. ESC or ''q'' for quitting while( (char)keyboard != ''q'' && (char)keyboard != 27 ){ //read the current frame if(!capture.read(frame)) { cerr << "Unable to read next frame." << endl; cerr << "Exiting..." << endl; exit(EXIT_FAILURE); } //update the background model pMOG->apply(frame, fgMaskMOG); pMOG2->apply(frame, fgMaskMOG2); //get the frame number and write it on the current frame stringstream ss; rectangle(frame, cv::Point(10, 2), cv::Point(100,20), cv::Scalar(255,255,255), -1); ss << capture.get(CAP_PROP_POS_FRAMES); string frameNumberString = ss.str(); putText(frame, frameNumberString.c_str(), cv::Point(15, 15), FONT_HERSHEY_SIMPLEX, 0.5 , cv::Scalar(0,0,0)); //show the current frame and the fg masks imshow("Frame", frame); imshow("FG Mask MOG", fgMaskMOG); imshow("FG Mask MOG 2", fgMaskMOG2); //get the input from the keyboard keyboard = waitKey( 30 ); } //delete capture object capture.release(); } void processImages(char* fistFrameFilename) { //read the first file of the sequence frame = imread(fistFrameFilename); if(!frame.data){ //error in opening the first image cerr << "Unable to open first image frame: " << fistFrameFilename << endl; exit(EXIT_FAILURE); } //current image filename string fn(fistFrameFilename); //read input data. ESC or ''q'' for quitting while( (char)keyboard != ''q'' && (char)keyboard != 27 ){ //update the background model pMOG->apply(frame, fgMaskMOG); pMOG2->apply(frame, fgMaskMOG2); //get the frame number and write it on the current frame size_t index = fn.find_last_of("/"); if(index == string::npos) { index = fn.find_last_of("//"); } size_t index2 = fn.find_last_of("."); string prefix = fn.substr(0,index+1); string suffix = fn.substr(index2); string frameNumberString = fn.substr(index+1, index2-index-1); istringstream iss(frameNumberString); int frameNumber = 0; iss >> frameNumber; rectangle(frame, cv::Point(10, 2), cv::Point(100,20), cv::Scalar(255,255,255), -1); putText(frame, frameNumberString.c_str(), cv::Point(15, 15), FONT_HERSHEY_SIMPLEX, 0.5 , cv::Scalar(0,0,0)); //show the current frame and the fg masks imshow("Frame", frame); imshow("FG Mask MOG", fgMaskMOG); imshow("FG Mask MOG 2", fgMaskMOG2); //get the input from the keyboard keyboard = waitKey( 30 ); //search for the next image in the sequence ostringstream oss; oss << (frameNumber + 1); string nextFrameNumberString = oss.str(); string nextFrameFilename = prefix + nextFrameNumberString + suffix; //read the next frame frame = imread(nextFrameFilename); if(!frame.data){ //error in opening the next image in the sequence cerr << "Unable to open image frame: " << nextFrameFilename << endl; exit(EXIT_FAILURE); } //update the path of the current frame fn.assign(nextFrameFilename); } }


Hoy encontré este problema. Este tutorial es para opencv 3.0, no para opencv 2.4+, realice algunos cambios de la siguiente manera:

//opencv #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/video/background_segm.hpp> //C #include <stdio.h> //C++ #include <iostream> #include <sstream> using namespace cv; using namespace std; //global variables Mat frame; //current frame Mat fgMaskMOG; //fg mask generated by MOG method Mat fgMaskMOG2; //fg mask fg mask generated by MOG2 method Ptr<BackgroundSubtractor> pMOG; //MOG Background subtractor Ptr<BackgroundSubtractor> pMOG2; //MOG2 Background subtractor int keyboard; //function declarations void help(); void processVideo(char* videoFilename); void processImages(char* firstFrameFilename); void help() { cout << "--------------------------------------------------------------------------" << endl << "This program shows how to use background subtraction methods provided by " << endl << " OpenCV. You can process both videos (-vid) and images (-img)." << endl << endl << "Usage:" << endl << "./bs {-vid <video filename>|-img <image filename>}" << endl << "for example: ./bs -vid video.avi" << endl << "or: ./bs -img /data/images/1.png" << endl << "--------------------------------------------------------------------------" << endl << endl; } int main(int argc, char* argv[]) { //print help information help(); //check for the input parameter correctness if(argc != 3) { cerr <<"Incorret input list" << endl; cerr <<"exiting..." << endl; return EXIT_FAILURE; } //create GUI windows namedWindow("Frame"); namedWindow("FG Mask MOG"); namedWindow("FG Mask MOG 2"); //create Background Subtractor objects //NOTE HERE!!!! pMOG= new BackgroundSubtractorMOG(); //MOG approach pMOG2 = new BackgroundSubtractorMOG2(); //MOG2 approach if(strcmp(argv[1], "-vid") == 0) { //input data coming from a video processVideo(argv[2]); } else if(strcmp(argv[1], "-img") == 0) { //input data coming from a sequence of images processImages(argv[2]); } else { //error in reading input parameters cerr <<"Please, check the input parameters." << endl; cerr <<"Exiting..." << endl; return EXIT_FAILURE; } //destroy GUI windows destroyAllWindows(); return EXIT_SUCCESS; } void processVideo(char* videoFilename) { //create the capture object VideoCapture capture(videoFilename); if(!capture.isOpened()){ //error in opening the video input cerr << "Unable to open video file: " << videoFilename << endl; exit(EXIT_FAILURE); } //read input data. ESC or ''q'' for quitting while( (char)keyboard != ''q'' && (char)keyboard != 27 ){ //read the current frame if(!capture.read(frame)) { cerr << "Unable to read next frame." << endl; cerr << "Exiting..." << endl; exit(EXIT_FAILURE); } //update the background model //AND HERE!!! pMOG->operator()(frame, fgMaskMOG); pMOG2->operator()(frame, fgMaskMOG2); //get the frame number and write it on the current frame stringstream ss; rectangle(frame, cv::Point(10, 2), cv::Point(100,20), cv::Scalar(255,255,255), -1); ss << capture.get(CV_CAP_PROP_POS_FRAMES); string frameNumberString = ss.str(); putText(frame, frameNumberString.c_str(), cv::Point(15, 15), FONT_HERSHEY_SIMPLEX, 0.5 , cv::Scalar(0,0,0)); //show the current frame and the fg masks imshow("Frame", frame); imshow("FG Mask MOG", fgMaskMOG); imshow("FG Mask MOG 2", fgMaskMOG2); //get the input from the keyboard keyboard = waitKey( 30 ); } //delete capture object capture.release(); } void processImages(char* fistFrameFilename) { //read the first file of the sequence frame = imread(fistFrameFilename); if(!frame.data){ //error in opening the first image cerr << "Unable to open first image frame: " << fistFrameFilename << endl; exit(EXIT_FAILURE); } //current image filename string fn(fistFrameFilename); //read input data. ESC or ''q'' for quitting while( (char)keyboard != ''q'' && (char)keyboard != 27 ){ //update the background model //ALSO HERE!!!! pMOG->operator()(frame, fgMaskMOG); pMOG2->operator()(frame, fgMaskMOG2); //get the frame number and write it on the current frame size_t index = fn.find_last_of("/"); if(index == string::npos) { index = fn.find_last_of("//"); } size_t index2 = fn.find_last_of("."); string prefix = fn.substr(0,index+1); string suffix = fn.substr(index2); string frameNumberString = fn.substr(index+1, index2-index-1); istringstream iss(frameNumberString); int frameNumber = 0; iss >> frameNumber; rectangle(frame, cv::Point(10, 2), cv::Point(100,20), cv::Scalar(255,255,255), -1); putText(frame, frameNumberString.c_str(), cv::Point(15, 15), FONT_HERSHEY_SIMPLEX, 0.5 , cv::Scalar(0,0,0)); //show the current frame and the fg masks imshow("Frame", frame); imshow("FG Mask MOG", fgMaskMOG); imshow("FG Mask MOG 2", fgMaskMOG2); //get the input from the keyboard keyboard = waitKey( 30 ); //search for the next image in the sequence ostringstream oss; oss << (frameNumber + 1); string nextFrameNumberString = oss.str(); string nextFrameFilename = prefix + nextFrameNumberString + suffix; //read the next frame frame = imread(nextFrameFilename); if(!frame.data){ //error in opening the next image in the sequence cerr << "Unable to open image frame: " << nextFrameFilename << endl; exit(EXIT_FAILURE); } //update the path of the current frame fn.assign(nextFrameFilename); } }


También tuve el mismo problema: Error: El identificador "createBackgroundSubtractorMOG" no está definido, lo cual se debía a que me faltaba el enlace a la biblioteca de opencv libopencv_video.so en mi algoritmo.

Lo resolví al incluir libopencv_video.so durante la vinculación del proyecto que se puede hacer en su archivo Makefile de esta manera: -L/usr/local/lib/libopencv_video.so

Resolvió el error y puedo usar el tutorial original que se muestra aquí: http://docs.opencv.org/3.0-beta/doc/tutorials/video/background_subtraction/background_subtraction.html


Si quieres que el método MOG funcione, deberías

#include "opencv2/bgsegm.hpp"

y entonces

pMOG = bgsegm::createBackgroundSubtractorMOG();