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