• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /**
2   * @file bg_sub.cpp
3   * @brief Background subtraction tutorial sample code
4   * @author Domenico D. Bloisi
5   */
6  
7  //opencv
8  #include "opencv2/imgcodecs.hpp"
9  #include "opencv2/imgproc.hpp"
10  #include "opencv2/videoio.hpp"
11  #include <opencv2/highgui.hpp>
12  #include <opencv2/video.hpp>
13  //C
14  #include <stdio.h>
15  //C++
16  #include <iostream>
17  #include <sstream>
18  
19  using namespace cv;
20  using namespace std;
21  
22  // Global variables
23  Mat frame; //current frame
24  Mat fgMaskMOG2; //fg mask fg mask generated by MOG2 method
25  Ptr<BackgroundSubtractor> pMOG2; //MOG2 Background subtractor
26  int keyboard; //input from keyboard
27  
28  /** Function Headers */
29  void help();
30  void processVideo(char* videoFilename);
31  void processImages(char* firstFrameFilename);
32  
help()33  void help()
34  {
35      cout
36      << "--------------------------------------------------------------------------" << endl
37      << "This program shows how to use background subtraction methods provided by "  << endl
38      << " OpenCV. You can process both videos (-vid) and images (-img)."             << endl
39                                                                                      << endl
40      << "Usage:"                                                                     << endl
41      << "./bs {-vid <video filename>|-img <image filename>}"                         << endl
42      << "for example: ./bs -vid video.avi"                                           << endl
43      << "or: ./bs -img /data/images/1.png"                                           << endl
44      << "--------------------------------------------------------------------------" << endl
45      << endl;
46  }
47  
48  /**
49   * @function main
50   */
main(int argc,char * argv[])51  int main(int argc, char* argv[])
52  {
53      //print help information
54      help();
55  
56      //check for the input parameter correctness
57      if(argc != 3) {
58          cerr <<"Incorret input list" << endl;
59          cerr <<"exiting..." << endl;
60          return EXIT_FAILURE;
61      }
62  
63      //create GUI windows
64      namedWindow("Frame");
65      namedWindow("FG Mask MOG 2");
66  
67      //create Background Subtractor objects
68      pMOG2 = createBackgroundSubtractorMOG2(); //MOG2 approach
69  
70      if(strcmp(argv[1], "-vid") == 0) {
71          //input data coming from a video
72          processVideo(argv[2]);
73      }
74      else if(strcmp(argv[1], "-img") == 0) {
75          //input data coming from a sequence of images
76          processImages(argv[2]);
77      }
78      else {
79          //error in reading input parameters
80          cerr <<"Please, check the input parameters." << endl;
81          cerr <<"Exiting..." << endl;
82          return EXIT_FAILURE;
83      }
84      //destroy GUI windows
85      destroyAllWindows();
86      return EXIT_SUCCESS;
87  }
88  
89  /**
90   * @function processVideo
91   */
processVideo(char * videoFilename)92  void processVideo(char* videoFilename) {
93      //create the capture object
94      VideoCapture capture(videoFilename);
95      if(!capture.isOpened()){
96          //error in opening the video input
97          cerr << "Unable to open video file: " << videoFilename << endl;
98          exit(EXIT_FAILURE);
99      }
100      //read input data. ESC or 'q' for quitting
101      while( (char)keyboard != 'q' && (char)keyboard != 27 ){
102          //read the current frame
103          if(!capture.read(frame)) {
104              cerr << "Unable to read next frame." << endl;
105              cerr << "Exiting..." << endl;
106              exit(EXIT_FAILURE);
107          }
108          //update the background model
109          pMOG2->apply(frame, fgMaskMOG2);
110          //get the frame number and write it on the current frame
111          stringstream ss;
112          rectangle(frame, cv::Point(10, 2), cv::Point(100,20),
113                    cv::Scalar(255,255,255), -1);
114          ss << capture.get(CAP_PROP_POS_FRAMES);
115          string frameNumberString = ss.str();
116          putText(frame, frameNumberString.c_str(), cv::Point(15, 15),
117                  FONT_HERSHEY_SIMPLEX, 0.5 , cv::Scalar(0,0,0));
118          //show the current frame and the fg masks
119          imshow("Frame", frame);
120          imshow("FG Mask MOG 2", fgMaskMOG2);
121          //get the input from the keyboard
122          keyboard = waitKey( 30 );
123      }
124      //delete capture object
125      capture.release();
126  }
127  
128  /**
129   * @function processImages
130   */
processImages(char * fistFrameFilename)131  void processImages(char* fistFrameFilename) {
132      //read the first file of the sequence
133      frame = imread(fistFrameFilename);
134      if(frame.empty()){
135          //error in opening the first image
136          cerr << "Unable to open first image frame: " << fistFrameFilename << endl;
137          exit(EXIT_FAILURE);
138      }
139      //current image filename
140      string fn(fistFrameFilename);
141      //read input data. ESC or 'q' for quitting
142      while( (char)keyboard != 'q' && (char)keyboard != 27 ){
143          //update the background model
144          pMOG2->apply(frame, fgMaskMOG2);
145          //get the frame number and write it on the current frame
146          size_t index = fn.find_last_of("/");
147          if(index == string::npos) {
148              index = fn.find_last_of("\\");
149          }
150          size_t index2 = fn.find_last_of(".");
151          string prefix = fn.substr(0,index+1);
152          string suffix = fn.substr(index2);
153          string frameNumberString = fn.substr(index+1, index2-index-1);
154          istringstream iss(frameNumberString);
155          int frameNumber = 0;
156          iss >> frameNumber;
157          rectangle(frame, cv::Point(10, 2), cv::Point(100,20),
158                    cv::Scalar(255,255,255), -1);
159          putText(frame, frameNumberString.c_str(), cv::Point(15, 15),
160                  FONT_HERSHEY_SIMPLEX, 0.5 , cv::Scalar(0,0,0));
161          //show the current frame and the fg masks
162          imshow("Frame", frame);
163          imshow("FG Mask MOG 2", fgMaskMOG2);
164          //get the input from the keyboard
165          keyboard = waitKey( 30 );
166          //search for the next image in the sequence
167          ostringstream oss;
168          oss << (frameNumber + 1);
169          string nextFrameNumberString = oss.str();
170          string nextFrameFilename = prefix + nextFrameNumberString + suffix;
171          //read the next frame
172          frame = imread(nextFrameFilename);
173          if(frame.empty()){
174              //error in opening the next image in the sequence
175              cerr << "Unable to open image frame: " << nextFrameFilename << endl;
176              exit(EXIT_FAILURE);
177          }
178          //update the path of the current frame
179          fn.assign(nextFrameFilename);
180      }
181  }
182