2013-10-07 13 views
18

stavo cercando di passare attraverso questo tutorial på OpenCV.org:OpenCV: come utilizzare createBackgroundSubtractorMOG

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

Il puntatore MOG viene inizializzato come

Ptr<BackgroundSubtractor> pMOG; //MOG Background subtractor 

e principale, è utilizzato nel modo seguente:

pMOG = createBackgroundSubtractorMOG(); 

Tuttavia, questo sì LDS il seguente errore:

Error: Identifier "createBackgroundSubtractorMOG" is undefined 

Inoltre, quando il modello di fondo deve essere aggiornato, il seguente comando viene utilizzato:

pMOG->apply(frame, fgMaskMOG); 

Che a sua volta produce il seguente errore:

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

Qualche idea su cosa si può fare a riguardo? Molte grazie in anticipo!

Ecco l'intero codice 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); 
    } 
} 

risposta

35

mi è capitato di incontrare questo problema oggi. Questo tutorial è per OpenCV 3.0, non per OpenCV 2.4+, fare alcuni cambiamenti nel modo seguente:

//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); 
    } 
} 
+0

Grazie, funziona! :) – Rickz0r

+0

Anche se non funziona così bene, almeno non per tracciare una persona di fronte alla web cam, forse è meglio quando si rintracciano le persone nelle strade o simili. Sembra che non dimentichi mai veramente il primo fotogramma. Indipendentemente dai valori dei parametri che uso, il primo frame è come una maschera costante. Suppongo che io senza altre modifiche utilizzi solo l'acquisizione di VideoCapture (0); anziché acquisizione di VideoCapture (videoFile); – Rickz0r

+0

Ok, ho capito! Ho appena cambiato la velocità di apprendimento: 'pMOG-> operator() (frame, fgMaskMOG, 0.1);' Non capisco perché 0.0 sarà il default, ma comunque, sono felice ora :) – Rickz0r

5

conseguenza alla risposta precedente sottrattore sfondo può essere anche definito come:

BackgroundSubtractorMOG MOG; 

invece di :

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

che richiederebbe anche di eliminare pMOG quando non è più utilizzato, inoltre, funtore può essere utilizzato per aggiornare la maschera in primo piano in modo un po 'più intelligente:

MOG(newFrame, foregroundMask); 

invece di:

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

L'ipotesi di default di OpenCV è che lo sfondo è abbastanza costante e non ha bisogno di alcun aggiornamento, quindi, dopo la fase iniziale di apprendimento della miscela di gaussiane non è cambiato più. Una descrizione chiara e precisa può essere anche essere trovato qui:

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

+0

Grazie per il chiarimento – Rickz0r

+0

Molto più chiaro del Ptr roba da sopra. Grazie! – br1

+0

L'approccio raccomandato ufficialmente è quello di usare 'makePtr <>' o 'Algorithm :: create', NOT' new'. Vedi la [Guida Transizione OpenCV 3] (http://docs.opencv.org/master/db/dfa/tutorial_transition_guide.html#tutorial_transition_algorithm). – chappjc

1

Ho anche avuto lo stesso problema: Errore: Identifier "createBackgroundSubtractorMOG" non è definito che era perché mi mancava collegamento alla libreria OpenCV libopencv_video.so nel mio algoritmo.

Ho risolto questo includendo libopencv_video.così durante il collegamento del progetto che può essere fatto nella vostra Makefile come questo: -L/usr/local/lib/libopencv_video.so

E 'stato risolto l'errore e io sono in grado di utilizzare il originale tutorial come dato qui: http://docs.opencv.org/3.0-beta/doc/tutorials/video/background_subtraction/background_subtraction.html

+0

È divertente che sia stata suggerita la risposta corretta (collegamento con il modulo video richiesto). +1 – chappjc

+0

Si noti che la funzione nel tutorial corrente (a partire da 3.1) è 'createBackgroundSubtractorMOG2', che tra l'altro è dichiarata in opencv2/video/background_segm.hpp, che dovrebbe rendere abbastanza ovvio il modulo da collegare. :) – chappjc

1

Se si desidera che il metodo di MOG al lavoro, si dovrebbe

#include "opencv2/bgsegm.hpp" 

e poi

pMOG = bgsegm::createBackgroundSubtractorMOG(); 
Problemi correlati