Skip to content
Snippets Groups Projects
Select Git revision
  • afc40557ade2e0cf15f1834cfaa7e21c4412d6b3
  • master default protected
  • beta
  • dev
  • andrewssobral-patch-1
  • update
  • thomas-fork
  • 2.0
  • v3.2.0
  • v3.1.0
  • v3.0
  • bgslib_py27_ocv3_win64
  • bgslib_java_2.0.0
  • bgslib_console_2.0.0
  • bgslib_matlab_win64_2.0.0
  • bgslib_qtgui_2.0.0
  • 2.0.0
  • bgs_console_2.0.0
  • bgs_matlab_win64_2.0.0
  • bgs_qtgui_2.0.0
  • v1.9.2_x86_mfc_gui
  • v1.9.2_x64_java_gui
  • v1.9.2_x86_java_gui
23 results

VideoAnalysis.cpp

Blame
  • Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    Demo.cpp 26.99 KiB
    /*
    ./bgs_demo -i test45/ -a 100 -o test45/results/
    based  on original demo.cpp
    */
    
    //cpp c
    #include <iostream>
    #include <algorithm>
    #include <cstdlib>
    #include <stdio.h>      /* printf, scanf, puts, NULL */
    #include <stdlib.h>     /* srand, rand */
    #include <time.h>       /* time */
    #include <ctime>
    
    
    #define PROCESS_CENTER_VERSION_MAJOR 0
    #define PROCESS_CENTER_VERSION_MINOR 9
    #define PROCESS_CENTER_VERSION_MINOR_FIXES 7
    
    //opencv
    #include <opencv2/opencv.hpp>
    //bgslibrary
    #include "package_bgs/bgslibrary.h"
    //my class
    #include "package_bgs/Tapter.h"
    #include "package_bgs/ttoolbox.h"
    
    using namespace cv;
    using namespace std;
    
    char* getCmdOption(char ** begin, char ** end, const std::string & option)
    {
        char ** itr = std::find(begin, end, option);
        if (itr != end && ++itr != end)
        {
            return *itr;
        }
        return 0;
    }
    
    bool cmdOptionExists(char** begin, char** end, const std::string& option)
    {
        return std::find(begin, end, option) != end;
    }
    
    
    int main(int argc, char * argv[])
    {
    
        std::cout << "using processcenter  " <<PROCESS_CENTER_VERSION_MAJOR <<"."<< PROCESS_CENTER_VERSION_MINOR << endl;
        std::cout << "Using OpenCV " << CV_MAJOR_VERSION << "." << CV_MINOR_VERSION << "." << CV_SUBMINOR_VERSION <<"."<<PROCESS_CENTER_VERSION_MINOR_FIXES<< std::endl;
        //!** parse programm input****************/
        if(cmdOptionExists(argv, argv+argc, "-h"))
        {
            cout <<" error: please use command as\n./bgs_demo -i pathToInputDir -a amountOfJpgFiles -c exactCenterConfFile.xml -o outPutPath"<<endl;
            return  EXIT_FAILURE;
        }
        if(!cmdOptionExists(argv, argv+argc, "-i")||!cmdOptionExists(argv, argv+argc, "-a")||!cmdOptionExists(argv, argv+argc, "-o") )
        {
            cout <<" error: please use command as\n./bgs_demo -i pathToInputDir -a amountOfJpgFiles -c exactCenterConfFile.xml -o outPutPath"<<endl;
            return  EXIT_FAILURE;
        }
    
        char *testInputDir = getCmdOption(argv, argv + argc, "-i");
        std::string inputDir(".");
        if (testInputDir)
        {
            //test dir exists
            inputDir = string(testInputDir);
        }
        int amountFiles = -1;
        char *testFileAmount = getCmdOption(argv, argv + argc, "-a");
        if (testFileAmount)
        {
            string s(testFileAmount);
            stringstream foo(s);
            foo >> amountFiles;
        }
    
    
        char *centerFile = getCmdOption(argv, argv + argc, "-c");
        std::string centerFileString(".");
        if (centerFile)
        {
            //test dir exists
            centerFileString = string(centerFile);
        }
    
        char *testOutputDir = getCmdOption(argv, argv + argc, "-o");
        std::string outputDir(".");
        if (testOutputDir)
        {
            //test dir exists
            outputDir = string(testOutputDir);
        }
    
        cout <<"args: -i "<<inputDir<<" -a "<<amountFiles << " -c" <<  centerFileString<<" -o " << outputDir;
        //!**** end parse input***********/
    
        //./program -i pathToInputDir -a amountOfJpgFiles -o outPutPath
    
        //pathToInputDir
        //----should have
        //      centerFile.xml
        //      -data/
        //          #which include all jpg and tt files
        //      first file mus be: 0000000000.jpg
        //      -bk.jpg
        //          #is the neutral bk file for training the bgs method
        //
    
    
        //    VideoCapture capture;
    
        //    if (argc > 1)
        //    {
        //        std::cout << "Openning: " << argv[1] << std::endl;
        //        capture.open(argv[1]);
        //    }
        //    else
        //        capture.open(0);
    
        //    if (!capture.isOpened())
        //    {
        //        std::cerr << "Cannot initialize video!" << std::endl;
        //        return -1;
        //    }
    
        /* Background Subtraction Methods */
        //IBGS *bgs;
    
        //bgs = new FrameDifference;
        //bgs = new StaticFrameDifference;
        //bgs = new WeightedMovingMean;
        //bgs = new WeightedMovingVariance;
        //bgs = new MixtureOfGaussianV1; // only on OpenCV 2.x
        //bgs = new MixtureOfGaussianV2;
        //bgs = new AdaptiveBackgroundLearning;
        //bgs = new AdaptiveSelectiveBackgroundLearning;
        //bgs = new GMG; // only on OpenCV 2.x
        //bgs = new KNN; // only on OpenCV 3.x
        //bgs = new DPAdaptiveMedian;
        //bgs = new DPGrimsonGMM;
        //bgs = new DPZivkovicAGMM;
        //bgs = new DPMean;
        //bgs = new DPWrenGA;
        //bgs = new DPPratiMediod;
        //bgs = new DPEigenbackground;
        //bgs = new DPTexture;
        //bgs = new T2FGMM_UM;
        //bgs = new T2FGMM_UV;
        //bgs = new T2FMRF_UM;
        //bgs = new T2FMRF_UV;
        //bgs = new FuzzySugenoIntegral;
        //bgs = new FuzzyChoquetIntegral;
        //bgs = new MultiLayer;
        //bgs = new PixelBasedAdaptiveSegmenter;
        //bgs = new LBSimpleGaussian;
        //bgs = new LBFuzzyGaussian;
        //bgs = new LBMixtureOfGaussians;
        //bgs = new LBAdaptiveSOM;
        //bgs = new LBFuzzyAdaptiveSOM;
        //bgs = new LBP_MRF;
        //bgs = new VuMeter;
        //bgs = new KDE;
        //bgs = new IndependentMultimodal;
        //bgs = new MultiCue;
        //bgs = new SigmaDelta;
        //bgs = new SuBSENSE;
        //bgs = new LOBSTER;
        //bgs = new PAWCS;
        //bgs = new TwoPoints;
        //bgs = new ViBe;
        //bgs = new Tapter;
    
        Tapter *bgs = new Tapter;
    
        //    bgs->setPathOut(outputDir);
        //    bgs->setInitialFrameCounter(0);
        //    bgs->setFlagWrite(0);
        //    bgs->setFlagWriteDBGpic(0);
    
    
        //see paper https://dl.acm.org/citation.cfm?id=2321600
        //https://ieeexplore.ieee.org/document/4527178/
        //was in benchmark on top https://www.researchgate.net/publication/259340906_A_comprehensive_review_of_background_subtraction_algorithms_evaluated_with_synthetic_and_real_videos
        //my own adapter to use the model
    
        int i= 0;
        cv::Mat img_input;
    
        //init the random number generator
        srand (time(NULL));
    
        clock_t beginAll = clock();
    
        //! we read the center config file for cut out the ROI
        //TODO merge this config with the Tapter.xml ??
        //circle param
        int circleCenterX = 880;
        int circleCenterY = 750;
        int circleRadius = 700;
        cv::String  configFileNameCenter(centerFileString);
        //read the config
        cout  << "parameter of centerConfigFile.xml"<<endl;
        FileStorage fsCen;
        fsCen.open(configFileNameCenter, FileStorage::READ);
        if (!fsCen.isOpened())
        {
            cout << "error during open " <<centerFileString <<  " will abort\n ";
            return EXIT_FAILURE;
        }
    
        circleCenterX = (int) fsCen["circleCenterX"];
        cout  <<"circleCenterX: "<< circleCenterX<<endl;
    
        circleCenterY = (int) fsCen["circleCenterY"];
        cout  <<"circleCenterY: "<< circleCenterY<<endl;
    
        circleRadius = (int) fsCen["circleRadius"];
        cout  <<"circleRadius: "<< circleRadius<<endl;
        fsCen.release();
    
        //first the static pic**********
        //std::string fileName = getFileName(begin);
        std::string staticFile = inputDir+"/bk.jpg";
        cout <<"a) load first static background pic :"<< staticFile<<endl;
    
        //we check for corrupt image
        if(TToolBox::checkFileCorrupted(staticFile))
        {
            cout<<"error file: "<< staticFile<<" is corrupted, will abort"<<endl;
            return  EXIT_FAILURE;
        }
    
        img_input = imread(staticFile.c_str(), CV_LOAD_IMAGE_COLOR);
        if(img_input.data )
        {
            //we cut out a smaller ROI
            img_input = TToolBox::cropImageCircle(img_input,circleCenterX,circleCenterY,circleRadius);
    
            cv::Mat img_mask;
            cv::Mat img_bkgmodel;
            bgs->process(img_input, img_mask, img_bkgmodel);
        }
        else
        {
            cout<<"error loading file: "<< staticFile<<", will abort"<<endl;
            return  EXIT_FAILURE;
        }
    
        std::string fileName;
    
        //! we train with first x on random draws
        int amountTrainingSteps = 200;
        //we open the config file and readin
        cv::String  configFileName("./config/Tapter.xml");
        {//read the config
            FileStorage fs;
            fs.open(configFileName, FileStorage::READ);
            if (!fs.isOpened())
            {
                cout << "error during open " << configFileName <<  " will abort " <<endl;
                return EXIT_FAILURE;
            }
            //param
            amountTrainingSteps = (int) fs["trainingSteps"];
            //cout <<"amountTrainingSteps: "<< amountTrainingSteps<< endl;
            fs.release();
        }
    
        cout <<"b) we train the background with random choosen files"<< fileName<<endl;
        //int j=255;
        vector<string> myRandomTrainList; //we save all draws in a list which will save to the results
        for(i=0;i<amountTrainingSteps;i++)
        {
    
            //random index
            int index  = rand() % amountFiles; //TODO: double check no double draw ??
            fileName = inputDir +  TToolBox::getFileName(index);
            myRandomTrainList.push_back(fileName);
    
            //we check for corrupt image
            if(TToolBox::checkFileCorrupted(fileName))
            {
                cout<<"error file: "<< fileName<<" is corrupted, will ignore it and draw new"<<endl;
                i--;
                continue; //we jump over the rest //TODO bad style
            }
    
            cout <<"\t"<<i <<"\t of \t"<<amountTrainingSteps<<" rnd file :"<< fileName<<endl;
            img_input = imread(fileName.c_str(), CV_LOAD_IMAGE_COLOR);
    
            cout << " a "<<endl;
    
            if(img_input.data )
            {
                //we cut out a smaller ROI
                img_input = TToolBox::cropImageCircle(img_input,circleCenterX,circleCenterY,circleRadius);
    
                //cv::imshow("input", img_input);
                cv::Mat img_mask;
                cv::Mat img_bkgmodel;
    
                //            //adapter learning rate
                //            if(j>62)
                //                bgs->setLearningRate(j);
    
                bgs->process(img_input, img_mask, img_bkgmodel); // by default, it shows automatically the foreground mask image
    
                cout << " b "<<endl;
    
                //            //we save the bk gmodel
                //            std::string bkTestFileName = inputDir + "bk_"+TToolBox::mNzero(i)+".jpg";
                //            imwrite(bkTestFileName.c_str(),img_bkgmodel);
            }
            else
            {
                cout<<"error loading file: "<< fileName<<", will draw again"<<endl;
                i--;
                //return  EXIT_FAILURE;
            }
        }
    
        cout << " c "<<endl;
    
    
        cout <<"c) we produce train the background with random choosen files"<< fileName<<endl;
    
        int everyPic=60*5;
    
        int frameCounter=0;
        vector<string> myFileErrorList;//list for pure io error
        vector<string> myFileListNoContour; //list for no contours found;
        vector<string> myFileListAfterContourSelection; //list for no contours found after selection;
        vector<string> myFileListCorrupted; //list all corrupted jpg files
    
        for(frameCounter=0;frameCounter<amountFiles;frameCounter++)
        {
    
            cout << " d "<<endl;
    
            //measure time consumption
            clock_t begin = clock();
    
            //we define the type better to prevent error
            fileName = std::string(inputDir + TToolBox::getFileName(frameCounter));
    
            //        //check the string
            //        cout <<"open fileName: "<< fileName<<endl;
            //        if(fileName.empty())
            //            cerr <<"error: empty string fileName"<<endl;
    
    
            cout <<"\t"<<frameCounter<<"\tof \t"<<amountFiles<<"  load file :"<< fileName<<endl;
            //cv::imwrite(convert.str().c_str(), img_output);
            //we open the file
            cv::String fileNameCV(fileName);
            cout << " d 3: "<< fileName.size()<< " size: "<< fileName<<endl;
            cout << " d 3: "<< fileNameCV.size()<< " size:"<< fileNameCV.c_str();
    
            //we check if the image in NOT corrupted
            if(!TToolBox::checkFileCorrupted(fileName))
            {
                //we load the file
                img_input = imread(fileNameCV, CV_LOAD_IMAGE_COLOR);
    
                cout << " e "<<endl;
    
                if(img_input.data )
                {
                    //! we cut out a smaller ROI,
                    //! step 1)
                    img_input = TToolBox::cropImageCircle(img_input,circleCenterX,circleCenterY,circleRadius);
    
                    //!  normal bgs processing
                    //! step 2)
                    cv::Mat img_mask;
                    cv::Mat img_bkgmodel;
    
                    bgs->process(img_input, img_mask, img_bkgmodel); // by default, it shows automatically the foreground mask image
    
                    cout << " f "<<endl;
    
                    //! step 3) we make  we apply a edge detection
                    //TODO make this in a function, how many times is this listed ??
                    //TODO read from tapter config
                    //TODO all parameter from applyCannyEdgeAndCalcCountours also !!
                    double threshholdMin = 150;
                    double threshholdMax = 200;
                    int apertureSize = 3;
                    std::vector<vector<Point> > contours = TToolBox::applyCannyEdgeAndCalcCountours(img_mask,threshholdMin,threshholdMax,apertureSize);
    
                    //define what we will write down
                    std::vector<vector<Point> > contourSelection;
                    vector<Point2f> massCenters;
                    vector<Point> conHull;
                    Point2f muConvexHullMassCenter(0.0,0.0);
    
                    if(!contours.empty())
                    {
                        //        //TODO: we need to  order the points to get a nice polygon, otherwise not usefull
                        //        //we also try to find the aproximate polygon*****************
                        ////        vector<Point> aproxiCurve;
    
                        ////        //  //see https://docs.opencv.org/3.4/d3/d63/classcv_1_1Mat.html#a167a8e0a3a3d86e84b70e33483af4466
                        ////        //  if(aproxiCurve::checkVector(10,CV_32F)==-1)
                        ////        //      cout<<"error wrong format of vector"<<endl;
    
                        ////        //calc 0.1 percent of arc length of convex hull
                        ////        double epsilon =  0.1  * cv::arcLength(hullComplete,true);
    
                        ////        //see https://docs.opencv.org/2.4.13.2/modules/imgproc/doc/structural_analysis_and_shape_descriptors.html#approxpolydp
                        ////        cv::approxPolyDP(allContourPoints,aproxiCurve,epsilon,false);
    
                        ////#ifdef  MC_SHOW_STEP_ANALYSE
                        ////        if(aproxiCurve.size()>=2)//we only draw if we have at least a line
                        ////        {
                        ////            Mat imgPolyApr = Mat::zeros( img_input.size(), CV_8UC3 );
                        ////            imgPolyApr =  Scalar(255,255,255); //fille the picture
                        ////            Scalar colorC( 0,0,255,255 );//red
    
    
                        ////            //for(imgPolyApr)
    
                        ////            polylines(imgPolyApr, aproxiCurve, true, colorC, 1, 8);
    
                        ////            cv::String outpath3=  "/homes/tb55xemi/work/bugTrainingSet/testRec/rec04379437pp/result/";
                        ////            std::ostringstream convert3;
                        ////            convert3 << outpath3 << frameCounter <<"_appr_poly.jpg";
                        ////            cv::imwrite(convert3.str().c_str(), imgPolyApr);
                        ////        }
                        ////        else
                        ////            cout<<"approximate poly has not enough points will skip file: "<<frameCounter<<endl;
    
                        ////#endif
    
    
                        //! step 4) we make a selection out of all counters with area sizes******************************
    
                        //we calc all min rotated  rectangles for all contour from candy egde detect
                        //we exlcude very small one and very big ones
                        vector<RotatedRect> minRect( contours.size() );
    
                        //calc boxes around the contours
                        for( size_t i = 0; i < contours.size(); i++ )
                            minRect[i] = minAreaRect( Mat(contours[i]) ); //may use boundingRect ?? to use fix non rotated rectangles ?
    
                        vector<Point2f> recCenterPoints;
                        float areaMinThreshold = 150;
                        float areaMaxThreshold = 300000; //old max threshold was to small //TODO apply moving filter ??, an more adaptive approach
    
                        cout << " g "<<endl;
    
    
                        //iterate all rectangles
                        for( size_t i = 0; i< minRect.size(); i++ )
                        {
                            Point2f rect_points[4];
                            //get all points of the retange
                            minRect[i].points( rect_points );
    
                            //construct contour based on rectangle points because contour != rectangle with points
                            vector<Point> contourRect;
                            for(int j=0;j<4;j++)
                                contourRect.push_back(rect_points[j]);
    
                            //calc the area of the contour
                            double area0 = contourArea(contourRect);
                            //over stepp all small areas
                            if(area0<areaMinThreshold||area0>areaMaxThreshold)
                            {
                                //cout<<i<<":area0:"<<area0<<" dismissed "<<endl;
                                //skipe if the area is too small
                                continue;
                            }
                            else
                            {
                                //cout<<i<<":area0:"<<area0<<" choose "<<endl;
    
                                //get the center of this rectangle
                                Point2f center = minRect[i].center;
                                recCenterPoints.push_back(center);
    
                                //we also add the this contour to a selection
                                contourSelection.push_back(contours[i]);
    
                            }
                        }//end iterate all min rectangle
    
                        if(!contourSelection.empty())
                        {
                            //! step 5) we calc the moments from the contour selection
                            vector<Moments> mu(contourSelection.size() );
                            for( size_t i = 0; i < contourSelection.size(); i++ )
                            {
                                mu[i] = moments( contourSelection[i], false );
                            }
    
                            //  Get the mass centers:
                            massCenters =  vector<Point2f>( contourSelection.size() );
                            for( size_t i = 0; i < contourSelection.size(); i++ )
                            {
                                massCenters[i] = Point2f( mu[i].m10/mu[i].m00 , mu[i].m01/mu[i].m00 );
                            }
    
                            //! step 6) calc convex hull of all points of the contour selection *********
                            //TODO produce center of convex hull of all polygones
                            //TODO double check if ne contour sharing a center point ? nearby ??
    
                            //we merge all points
                            vector<Point> allContourPoints;
                            for (size_t cC = 0; cC < contourSelection.size(); ++cC)
                                for(size_t cP =0; cP < contourSelection[cC].size(); cP++)
                                {
                                    Point currentContourPixel = contourSelection[cC][cP];
                                    allContourPoints.push_back(currentContourPixel);
                                }
    
                            // calc the hull ******************
                            conHull = vector<Point>(allContourPoints.size());
                            convexHull( Mat(allContourPoints), conHull, false );
                            //    Point roiCenter;
                            //    float roiRadius;
    
                            //calc the min circle around
                            //minEnclosingCircle(conHull,roiCenter,roiRadius);
                            //we calc the mass center of the convex hull
    
                            ///we calc the mass center of the convex hull
                            Moments muConvexHull;
                            if(!conHull.empty())
                            {
                                muConvexHull = moments(conHull, true );
                                muConvexHullMassCenter= Point2f( muConvexHull.m10/muConvexHull.m00 , muConvexHull.m01/muConvexHull.m00 );
                            }
    
                            cout << " h "<<endl;
    
    
                        }//end after selection is empty
                        {
                            cerr<<"error, no contour found after selection in file: "<< fileName<<endl;
                            myFileListAfterContourSelection.push_back(fileName);
                        }
                    }//end if contours are empty, to canny edge found nothing
                    else
                    {
                        cerr<<"error, no contour found at all in file: "<< fileName<<endl;
                        myFileListNoContour.push_back(fileName);
    
                    }
    #ifdef  MC_SHOW_STEP_ANALYSE
    
                    if(!conHull.empty())//if we any elements, we process further
                    {
                        Mat imgConvexHull = Mat::zeros( img_input.size(), CV_8UC3 );
                        imgConvexHull =  Scalar(255,255,255); //fille the picture
    
                        Scalar colorB( 0,0,255,255 );//red
                        polylines(imgConvexHull, hullComplete, true, colorB, 1, 8);
    
                        //draw circle around
                        //circle( imgConvexHull, roiCenter, (int) roiRadius, colorB, 2, 8, 0 );
    
                        //we draw it
                        cv::String outpath2=  outputDir;
                        std::ostringstream convert2;
                        convert2 << outpath2 <<TToolBox::mNzero(frameCounter) <<"_convex_hull.jpg";
                        cv::imwrite(convert2.str().c_str(), imgConvexHull);
                    }
                    else
                        cout<<"convex hull has no points will skip file: "<<i<<endl;
    
    #endif
    
                    cout << " i "<<endl;
                    //cout<<"we try to write file: "<< i <<endl;
                    //! step 8: we write down all our results in yml file
                    std::string nameOutPutFileData =  outputDir + TToolBox::mNzero(frameCounter) + ".yml";
    
                    cout << " j "<<endl;
    
    
                    //           //check the string
                    //            cout <<"write output nameOutPutFileData: "<< nameOutPutFileData<<endl;
                    //            if(nameOutPutFileData.empty())
                    //                cerr <<"error: empty string nameOutPutFileData"<<endl;
    
    
                    FileStorage fs(nameOutPutFileData.c_str(), FileStorage::WRITE);
                    fs << "masscenters" <<  massCenters;
                    fs << "polygonselection"<< contourSelection;
                    fs << "convexhull"<<conHull;
                    fs << "masscenterconvexhull"<<muConvexHullMassCenter;
                    fs.release();
    
                    cout << " k "<<endl;
    
                    //! we write from time to time a dbg picture
                    if(frameCounter%everyPic==0)
                    {
                        Scalar colorRed( 0,0,255,255 );//red
                        RNG rng(4344234);
                        Mat imgDebugPaint2 = Mat::zeros( img_input.size(), CV_8UC3 );
                        imgDebugPaint2 =  Scalar(255,255,255); //fill the picture white
    
                        //we write all polyies of the selection and the mass centers with a random color
                        for( size_t i = 0; i< contourSelection.size(); i++ )
                        {
                            //random color
                            Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );
                            //contour
                            drawContours( imgDebugPaint2, contourSelection, i, color, 1, LINE_AA);
                            //draw the center
                            circle( imgDebugPaint2, massCenters[i], 4, color, -1, 8, 0 );
                        }
    
                        //we write the convex hull
                        if(!conHull.empty())
                        {
                            //the poly
                            polylines(imgDebugPaint2, conHull, true, colorRed, 1, 8);
                            //the center
                            circle( imgDebugPaint2,muConvexHullMassCenter, 4, colorRed, -1, 8, 0 );
                        }
    
                        //we make a copy
                        Mat imgOverlay2 = img_input.clone();
                        //we add a overlay of our paitings
                        addWeighted( imgDebugPaint2, 0.7, imgOverlay2, 0.3, 0.0, imgOverlay2);
                        //we write the file down
                        std::string nameOutPutFileDBGpic =  outputDir + TToolBox::mNzero(frameCounter) + std::string(".jpg");
    
                        //                //check the string
                        //                cout <<"write dbg file: "<< nameOutPutFileDBGpic<<endl;
                        //                if(nameOutPutFileDBGpic.empty())
                        //                    cerr <<"error: empty string nameOutPutFileDBGpic"<<endl;
    
                        imwrite(nameOutPutFileDBGpic.c_str(),imgOverlay2);
    
                        cout << " l "<<endl;
                    }//end if we write a dbg picture
    
    
                }//end if the loaded picture has data
                else
                {
                    cerr<<"error loading file: "<< fileName<<", will skip this file"<<endl;
                    myFileErrorList.push_back(fileName);
                }
    
            }//end if not corrupted picture
            else
            {
                cout<<"error file: "<< fileName<<" is corrupted, will ignore it"<<endl;
                myFileListCorrupted.push_back(fileName);
    
            }
    
    
            //we calc the time which we used for a picture
            clock_t end = clock();
            double elapsedSecs = double(end - begin) / CLOCKS_PER_SEC;
    
    
            //we calc the time which was used for all picture
            clock_t endAll = clock();
            double elapsedSecTotal = double(endAll - beginAll) / CLOCKS_PER_SEC;
            cout <<"process single pic:\t"<<elapsedSecs<<" s  - \t\t"<<(int)(elapsedSecTotal/60)<<" min -\t"<<(int)(elapsedSecTotal/60/60)<<" h"<<endl;
    
            cout << " --- "<<endl;
        }
        cout << " X "<<endl;
    
        //finishing time
        clock_t endAll = clock();
        double elapsed = double(endAll - beginAll) / CLOCKS_PER_SEC;
        cout <<"process : "<<amountFiles<<" files took:\t"<<(int)(elapsed/60)<<" min -\t"<<(int)(elapsed/60/60)<<" h \n in total"<<endl;
    
        //we write the random file list to a file
        std::string nameOutRandomFile =  outputDir + "randlist.yml";
        FileStorage fs(nameOutRandomFile.c_str(), FileStorage::WRITE);
        fs << "randomlist" <<  myRandomTrainList;
        fs.release();
    
        //TODO we should merge the file
    
        //we write the random file list to a file
        std::string nameOutErrorList =  outputDir + "fileErrorList.yml";
        cout <<"amount of file errors: "<< myFileErrorList.size()<<endl;
        FileStorage fs2(nameOutErrorList.c_str(), FileStorage::WRITE);
        fs2 << "fileErrorIOs" <<  myFileErrorList;
    
        //we write error list no contours found in file
        cout <<"amount contour errors with canny edge: "<< myFileListNoContour.size()<<endl;
        fs2 << "fileErrorNoContours" <<  myFileListNoContour;
    
        //we write error list no contours found in file
        cout <<"amount contour errors after selection: "<< myFileListAfterContourSelection.size()<<endl;
        fs2 << "fileErrorNoContoursAfterSelections" <<  myFileListAfterContourSelection;
    
    
        //we write error list no contours found in file
        cout <<"amount of corrupted jpg files: "<< myFileListCorrupted.size()<<endl;
        fs2 << "fileErrorIOcorruptFiles" <<  myFileListCorrupted;
    
    
        fs2.release();
    
        delete bgs;
    
        //    capture.release();
        cvDestroyAllWindows();
    
        return 0;
    }