Added the tutorial on background subtraction, in the video section
authorzio dodo <domenicobloisi@yahoo.com>
Wed, 21 Aug 2013 10:06:48 +0000 (12:06 +0200)
committerzio dodo <domenicobloisi@yahoo.com>
Wed, 21 Aug 2013 10:06:48 +0000 (12:06 +0200)
doc/conf.py
doc/tutorials/definitions/tocDefinitions.rst
doc/tutorials/video/background_subtraction/background_subtraction.rst [new file with mode: 0644]
doc/tutorials/video/background_subtraction/images/Background_Subtraction_Tutorial_Result_1.png [new file with mode: 0644]
doc/tutorials/video/background_subtraction/images/Background_Subtraction_Tutorial_Result_2.png [new file with mode: 0644]
doc/tutorials/video/background_subtraction/images/Background_Subtraction_Tutorial_Scheme.png [new file with mode: 0644]
doc/tutorials/video/table_of_content_video/images/Background_Subtraction_Tutorial_Cover.jpg [new file with mode: 0644]
doc/tutorials/video/table_of_content_video/table_of_content_video.rst
modules/stitching/src/motion_estimators.cpp
samples/cpp/tutorial_code/video/bg_sub.cpp [new file with mode: 0644]

index 312a1c2..ff683cc 100755 (executable)
@@ -401,5 +401,7 @@ extlinks = {
             'brute_force_matcher' : ('http://docs.opencv.org/modules/features2d/doc/common_interfaces_of_descriptor_matchers.html?highlight=bruteforcematcher#bruteforcematcher%s', None ),
             'cascade_classifier' : ('http://docs.opencv.org/modules/objdetect/doc/cascade_classification.html?highlight=cascadeclassifier#cascadeclassifier%s', None ),
             'cascade_classifier_load' : ('http://docs.opencv.org/modules/objdetect/doc/cascade_classification.html?highlight=load#cascadeclassifier-load%s', None ),
-            'cascade_classifier_detect_multiscale' : ('http://docs.opencv.org/modules/objdetect/doc/cascade_classification.html?highlight=detectmultiscale#cascadeclassifier-detectmultiscale%s', None )
-           }
+            'cascade_classifier_detect_multiscale' : ('http://docs.opencv.org/modules/objdetect/doc/cascade_classification.html?highlight=detectmultiscale#cascadeclassifier-detectmultiscale%s', None ),
+                       'background_subtractor' : ('http://opencv.itseez.com/modules/video/doc/motion_analysis_and_object_tracking.html?highlight=backgroundsubtractor#backgroundsubtractor%s', None),
+                       'video_capture' : ('http://opencv.itseez.com/modules/highgui/doc/reading_and_writing_images_and_video.html?highlight=videocapture#videocapture%s', None)
+                  }
index 4695623..c918aa2 100644 (file)
@@ -11,3 +11,4 @@
 .. |Author_EricCh| unicode:: Eric U+0020 Christiansen
 .. |Author_AndreyP| unicode:: Andrey U+0020 Pavlenko
 .. |Author_AlexS| unicode:: Alexander U+0020 Smorkalov
+.. |Author_DomenicoB| unicode:: Domenico U+0020 Daniele U+0020 Bloisi
diff --git a/doc/tutorials/video/background_subtraction/background_subtraction.rst b/doc/tutorials/video/background_subtraction/background_subtraction.rst
new file mode 100644 (file)
index 0000000..864cca6
--- /dev/null
@@ -0,0 +1,394 @@
+.. _Background_Subtraction:
+
+How to Use Background Subtraction Methods
+*****************************************
+
+* Background subtraction (BS) is a common and widely used technique for generating a foreground mask (namely, a binary image containing the pixels belonging to moving objects in the scene) by using static cameras.
+
+* As the name suggests, BS calculates the foreground mask performing a subtraction between the current frame and a background model, containing the static part of the scene or, more in general, everything that can be considered as background given the characteristics of the observed scene.
+  
+  .. image:: images/Background_Subtraction_Tutorial_Scheme.png
+     :alt: Background Subtraction - General Scheme
+     :align: center 
+        
+* Background modeling consists of two main steps:
+
+  #. Background Initialization;
+  #. Background Update.
+
+  In the first step, an initial model of the background is computed, while in the second step that model is updated in order to adapt to possible changes in the scene.
+
+* In this tutorial we will learn how to perform BS by using OpenCV. As input, we will use data coming from the publicly available data set `Background Models Challenge (BMC) <http://bmc.univ-bpclermont.fr/>`_ .
+
+Goals
+======
+
+In this tutorial you will learn how to:
+
+  #. Read data from videos by using :video_capture:`VideoCapture <>` or image sequences by using :imread:`imread <>`;
+  #. Create and update the background model by using :background_subtractor:`BackgroundSubtractor <>` class;
+  #. Get and show the foreground mask by using :imshow:`imshow <>`;
+  #. Save the output by using :imwrite:`imwrite <>` to quantitatively evaluate the results.
+
+Code
+=====
+
+In the following you can find the source code. We will let the user chose to process either a video file or a sequence of images.
+
+* Two different methods are used to generate two foreground masks:
+       #. MOG
+       #. MOG2 
+The results as well as the input data are shown on the screen.
+
+.. code-block:: cpp
+
+  //opencv
+  #include <opencv2/highgui/highgui.hpp>
+  #include <opencv2/highgui/highgui_c.h>
+  #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(CV_CAP_PROP_POS_FRAMES);
+      string frameNumberString = ss.str();
+      putText(frame, frameNumberString.c_str(), cv::Point(15, 15),
+              CV_FONT_NORMAL, 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;
+        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),
+                CV_FONT_NORMAL, 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);
+      }
+  }
+  
+* The source file can be downloaded :download:`here <../../../../samples/cpp/tutorial_code/video/bg_sub.cpp>`.
+
+
+Explanation
+============
+
+We discuss the main parts of the above code:
+
+#. First, three Mat objects are allocated to store the current frame and two foreground masks, obtained by using two different BS algorithms.
+
+   .. code-block:: cpp
+   
+     Mat frame; //current frame
+     Mat fgMaskMOG; //fg mask generated by MOG method
+     Mat fgMaskMOG2; //fg mask fg mask generated by MOG2 method
+   
+#. Two :background_subtractor:`BackgroundSubtractor <>` objects will be used to generate the foreground masks. In this example, default parameters are used, but it is also possible to declare specific parameters in the create function.   
+       
+   .. code-block:: cpp
+   
+     Ptr<BackgroundSubtractor> pMOG; //MOG Background subtractor
+     Ptr<BackgroundSubtractor> pMOG2; //MOG2 Background subtractor
+        ...
+     //create Background Subtractor objects
+     pMOG = createBackgroundSubtractorMOG(); //MOG approach
+     pMOG2 = createBackgroundSubtractorMOG2(); //MOG2 approach
+
+#. The command line arguments are analysed. The user can chose between two options:
+
+   * video files (by choosing the option -vid);
+   * image sequences (by choosing the option -img).
+
+   .. code-block:: cpp
+
+      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]);
+      }
+
+#. Suppose you want to process a video file. The video is read until the end is reached or the user presses the button 'q' or the button 'ESC'.
+
+   .. code-block:: cpp
+
+      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);
+        }
+
+#. Every frame is used both for calculating the foreground mask and for updating the background.
+
+   .. code-block:: cpp
+
+      //update the background model
+      pMOG->apply(frame, fgMaskMOG);
+      pMOG2->apply(frame, fgMaskMOG2);
+         
+#. The current frame number can be extracted from the :video_capture:`VideoCapture <>` object and stamped in the top left corner of the current frame. A white rectangle is used to highlight the black colored frame number.
+
+   .. code-block:: cpp
+   
+      //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),
+              CV_FONT_NORMAL, 0.5 , cv::Scalar(0,0,0));
+
+#. We are ready to show the current input frame and the results.
+
+   .. code-block:: cpp
+
+      //show the current frame and the fg masks
+      imshow("Frame", frame);
+      imshow("FG Mask MOG", fgMaskMOG);
+      imshow("FG Mask MOG 2", fgMaskMOG2);
+         
+#. The same operations listed above can be performed using a sequence of images as input. The processImage function is called and, instead of using a :video_capture:`VideoCapture <>` object, the images are read by using :imread:`imread <>`, after individuating the correct path for the next frame to read.
+
+   .. code-block:: cpp
+
+      //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);
+      }
+      ...
+      //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);
+   
+   
+   Note that:
+   * this example works only on image sequences in which the filename format is <n>.png, where n is the frame number (e.g., 7.png).
+Results
+=======
+
+* Given the following input parameters:
+
+  .. code-block:: cpp
+  
+     -vid Video_001.avi
+        
+  The output of the program will look as the following:
+
+  .. image:: images/Background_Subtraction_Tutorial_Result_1.png
+     :alt: Background Subtraction - Video File
+     :align: center 
+
+* The video file Video_001.avi is part of the `Background Models Challenge (BMC) <http://bmc.univ-bpclermont.fr/>`_ data set and it can be downloaded from `here <http://bmc.univ-bpclermont.fr/sites/default/files/videos/evaluation/Video_001.zip>`_.         
+        
+        
+* If you want to process a sequence of images, then the '-img' option has to be chosen:
+
+  .. code-block:: cpp
+  
+     -img 111_png/input/1.png
+        
+  The output of the program will look as the following:
+
+  .. image:: images/Background_Subtraction_Tutorial_Result_2.png
+     :alt: Background Subtraction - Image Sequence 
+     :align: center 
+
+* The sequence of images used in this example is part of the `Background Models Challenge (BMC) <http://bmc.univ-bpclermont.fr/>`_ dataset and it can be downloaded from `here <http://bmc.univ-bpclermont.fr/sites/default/files/videos/learning/111_png.zip>`_. Please, note that this example works only on sequences in which the filename format is <n>.png, where n is the frame number (e.g., 7.png).
+
+Evaluation
+==========  
+  
+To quantitatively evaluate the results obtained, we need to:
+
+* Save the output images;
+* Have the ground truth images for the chosen sequence.
+
+In order to save the output images, we can use :imwrite:`imwrite <>`. Adding the following code allows for saving the foreground masks.
+
+  .. code-block:: cpp 
+
+     string imageToSave = "output_MOG_" + frameNumberString + ".png";
+     bool saved = imwrite(imageToSave, fgMaskMOG);
+     if(!saved) {
+       cerr << "Unable to save " << imageToSave << endl;
+     }
+        
+Once we have collected the result images, we can compare them with the ground truth data. There exist several publicly available sequences for background subtraction that come with ground truth data. If you decide to use the `Background Models Challenge (BMC) <http://bmc.univ-bpclermont.fr/>`_, then the result images can be used as input for the `BMC Wizard <http://bmc.univ-bpclermont.fr/?q=node/7>`_. The wizard can compute different measures about the accuracy of the results.  
+  
+References
+==========
+
+* Background Models Challenge (BMC) website, `<http://bmc.univ-bpclermont.fr/>`_
+
+* Antoine Vacavant, Thierry Chateau, Alexis Wilhelm and Laurent Lequievre. A Benchmark Dataset for Foreground/Background Extraction. In ACCV 2012, Workshop: Background Models Challenge, LNCS 7728, 291-300. November 2012, Daejeon, Korea.
+
+
+
diff --git a/doc/tutorials/video/background_subtraction/images/Background_Subtraction_Tutorial_Result_1.png b/doc/tutorials/video/background_subtraction/images/Background_Subtraction_Tutorial_Result_1.png
new file mode 100644 (file)
index 0000000..a646a4f
Binary files /dev/null and b/doc/tutorials/video/background_subtraction/images/Background_Subtraction_Tutorial_Result_1.png differ
diff --git a/doc/tutorials/video/background_subtraction/images/Background_Subtraction_Tutorial_Result_2.png b/doc/tutorials/video/background_subtraction/images/Background_Subtraction_Tutorial_Result_2.png
new file mode 100644 (file)
index 0000000..ed95dde
Binary files /dev/null and b/doc/tutorials/video/background_subtraction/images/Background_Subtraction_Tutorial_Result_2.png differ
diff --git a/doc/tutorials/video/background_subtraction/images/Background_Subtraction_Tutorial_Scheme.png b/doc/tutorials/video/background_subtraction/images/Background_Subtraction_Tutorial_Scheme.png
new file mode 100644 (file)
index 0000000..7c9bf6c
Binary files /dev/null and b/doc/tutorials/video/background_subtraction/images/Background_Subtraction_Tutorial_Scheme.png differ
diff --git a/doc/tutorials/video/table_of_content_video/images/Background_Subtraction_Tutorial_Cover.jpg b/doc/tutorials/video/table_of_content_video/images/Background_Subtraction_Tutorial_Cover.jpg
new file mode 100644 (file)
index 0000000..d5c84a3
Binary files /dev/null and b/doc/tutorials/video/table_of_content_video/images/Background_Subtraction_Tutorial_Cover.jpg differ
index a2521d6..1965654 100644 (file)
@@ -3,10 +3,35 @@
 *video* module. Video analysis
 -----------------------------------------------------------
 
-Look here in order to find use on your video stream algoritms like: motion extraction, feature tracking and foreground extractions.
+Look here in order to find use on your video stream algoritms like: motion extraction, feature tracking and foreground extractions. 
 
-.. include:: ../../definitions/noContent.rst
+.. include:: ../../definitions/tocDefinitions.rst
+
++ 
+  .. tabularcolumns:: m{100pt} m{300pt}
+  .. cssclass:: toctableopencv
+
+  =============== ======================================================
+   |BgSub|        **Title:** :ref:`Background_Subtraction`
+  
+                  *Compatibility:* > OpenCV 2.4.5
+
+                  *Author:* |Author_DomenicoB|
+  
+                  We will learn how to extract foreground masks from both videos and sequences of images and to show them.
+  
+  =============== ======================================================
+  
+  .. |BgSub| image:: images/Background_Subtraction_Tutorial_Cover.jpg
+                   :height: 90pt
+                   :width:  90pt
 
 .. raw:: latex
 
    \pagebreak
+
+.. toctree::
+   :hidden:
+
+   ../background_subtraction/background_subtraction
+
index abd43b1..b09253c 100644 (file)
@@ -259,7 +259,7 @@ bool BundleAdjusterBase::estimate(const std::vector<ImageFeatures> &features,
     bool ok = true;
     for (int i = 0; i < cam_params_.rows; ++i)
     {
-        if (isnan(cam_params_.at<double>(i,0)))
+        if (std::isnan(cam_params_.at<double>(i,0)))
         {
             ok = false;
             break;
diff --git a/samples/cpp/tutorial_code/video/bg_sub.cpp b/samples/cpp/tutorial_code/video/bg_sub.cpp
new file mode 100644 (file)
index 0000000..7d2375e
--- /dev/null
@@ -0,0 +1,172 @@
+//opencv
+#include <opencv2/highgui/highgui.hpp>
+#include <opencv2/highgui/highgui_c.h>
+#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; //input from 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(CV_CAP_PROP_POS_FRAMES);
+               string frameNumberString = ss.str();
+               putText(frame, frameNumberString.c_str(), cv::Point(15, 15),
+              CV_FONT_NORMAL, 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;
+               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),
+                       CV_FONT_NORMAL, 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);
+       }
+}