2013-10-07 5 views
18

я пытался пройти через этот учебник på OpenCV.org:OpenCV: как использовать createBackgroundSubtractorMOG

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

Указатель MOG инициализируется как

Ptr<BackgroundSubtractor> pMOG; //MOG Background subtractor 

и в основном, это используется следующим образом:

pMOG = createBackgroundSubtractorMOG(); 

Однако, это yie LDS следующее сообщение об ошибке:

Error: Identifier "createBackgroundSubtractorMOG" is undefined 

Кроме того, когда модель фона должна быть обновлена, используется следующая команда:

pMOG->apply(frame, fgMaskMOG); 

Что в свою очередь дает следующее сообщение об ошибке:

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

Любая идея, что можно сделать по этому поводу? Большое спасибо заранее!

Вот весь код учебник:

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

ответ

35

я случайно встретил эту проблему сегодня. Это руководство предназначено для OpenCV 3.0, а не для OpenCV 2.4+, сделать несколько изменений следующим образом:

//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

Спасибо, это работает! :) – Rickz0r

+0

Хотя это не работает так хорошо, по крайней мере, не для отслеживания человека перед веб-камерой, может быть, лучше отслеживать людей на улицах или подобных. Кажется, он никогда не забывает о первом кадре. Независимо от того, какие значения параметров я использую, первый кадр похож на постоянную маску. Я предполагаю, что я без каких-либо других изменений просто использую захват видеозахвата (0); вместо захват видеозахвата (videoFilename); – Rickz0r

+0

Хорошо, я понял! Просто изменил скорость обучения: 'pMOG-> operator() (frame, fgMaskMOG, 0.1);' Не понимаю, почему 0.0 будет по умолчанию, но в любом случае я счастлив сейчас :) – Rickz0r

5

Соответственно к предыдущему ответу фон вычитателя также может быть определен как:

BackgroundSubtractorMOG MOG; 

вместо :

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

, что также потребуется удалить pMOG, когда он больше не используется, кроме того, функтор может быть использован для обновления переднего плана маски немного умнее образом:

MOG(newFrame, foregroundMask); 

InstEd из:

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

по умолчанию предположения OpenCV является то, что фон является довольно постоянным и не требует обновлений, поэтому, после обучения начальной фазы смеси гауссового не изменяется больше. Подробное и четкое описание также можно найти здесь:

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

+0

Спасибо за разъяснение – Rickz0r

+0

Гораздо понятнее, чем Ptr вещи сверху. Благодаря! – br1

+0

Официально рекомендованный подход заключается в использовании 'makePtr <>' или 'Algorithm :: create', NOT' new'. См. [Руководство по переходу OpenCV 3] (http://docs.opencv.org/master/db/dfa/tutorial_transition_guide.html#tutorial_transition_algorithm). – chappjc

1

Я также имел тот же вопрос: Error: Identifier «createBackgroundSubtractorMOG» не определено, который был, потому что я был недостающим звеном в OpenCV библиотеки libopencv_video.so в моем алгоритме.

Я решил это, включив libopencv_video.так во время связывания проекта, который может быть сделано в вашем Makefile так: -L/usr/local/lib/libopencv_video.so

Он разрешил ошибку, и я могу использовать оригинальный учебник, как указано здесь: http://docs.opencv.org/3.0-beta/doc/tutorials/video/background_subtraction/background_subtraction.html

+0

Забавно, что сейчас был предложен правильный ответ (ссылка на требуемый видеомодуль). +1 – chappjc

+0

Но обратите внимание, что функция в текущем учебнике (начиная с 3.1) является 'createBackgroundSubtractorMOG2', который, кстати, объявлен в opencv2/video/background_segm.hpp, что должно сделать достаточно очевидным, с каким модулем вы должны ссылаться. :) – chappjc

1

Если вы хотите, чтобы метод MOG работать, вы должны

#include "opencv2/bgsegm.hpp" 

, а затем

pMOG = bgsegm::createBackgroundSubtractorMOG(); 
Смежные вопросы