diff --git a/Demo2.cpp b/Demo2.cpp index cbb6edbda8ff6af27b740c33d0a6ae189f91f0ec..3ce643189c85c8a74096a9ab7be41d45450cdba9 100644 --- a/Demo2.cpp +++ b/Demo2.cpp @@ -1,106 +1,665 @@ /* -This file is part of BGSLibrary. +./bgs_demo -i test45/ -a 100 -o test45/results/ +based on original demo.cpp +*/ -BGSLibrary is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. +//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> -BGSLibrary is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. -*/ -#include <iostream> -#include <opencv2/opencv.hpp> +#define PROCESS_CENTER_VERSION_MAJOR 0 +#define PROCESS_CENTER_VERSION_MINOR 6 +//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; -int main(int argc, char **argv) +char* getCmdOption(char ** begin, char ** end, const std::string & option) { - std::cout << "Using OpenCV " << CV_MAJOR_VERSION << "." << CV_MINOR_VERSION << "." << CV_SUBMINOR_VERSION << std::endl; - - /* 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; - - int frameNumber = 1; - int key = 0; - while (key != 'q') - { - std::stringstream ss; - ss << frameNumber; - std::string fileName = "dataset/frames/" + ss.str() + ".png"; - std::cout << "reading " << fileName << std::endl; - - cv::Mat img_input = cv::imread(fileName, CV_LOAD_IMAGE_COLOR); - - if (img_input.empty()) - break; - - cv::imshow("input", img_input); - - cv::Mat img_mask; - cv::Mat img_bkgmodel; - bgs->process(img_input, img_mask, img_bkgmodel); - // by default, "bgs->process(.)" automatically shows the foreground mask image - // or set "bgs->setShowOutput(false)" to disable - - //if(!img_mask.empty()) - // cv::imshow("Foreground", img_mask); - // do something - - key = cvWaitKey(33); - frameNumber++; - } - cvWaitKey(0); - delete bgs; - cvDestroyAllWindows(); - - return 0; + 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 produce bk " <<PROCESS_CENTER_VERSION_MAJOR <<"."<< PROCESS_CENTER_VERSION_MINOR << endl; + std::cout << "Using OpenCV " << CV_MAJOR_VERSION << "." << CV_MINOR_VERSION << "." << CV_SUBMINOR_VERSION << 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"); + 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"); + string centerFileString("."); + if (centerFile) + { + //test dir exists + centerFileString = string(centerFile); + } + + char *testOutputDir = getCmdOption(argv, argv + argc, "-o"); + 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; + // 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 = 2; + // //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 <<"a) we choose two random file "<< fileName<<endl; + //int j=255; + + vector<Mat> picsMask; + vector<Mat> picsOrigin; + int maxTrain = 10; + vector<string> myRandomTrainList; //we save all draws in a list which will save to the results + for(i=0;i<maxTrain;i++) + { + + //random index + int index = rand() % amountFiles; //TODO: double check no double draw ?? + fileName = inputDir + TToolBox::getFileName(index); + myRandomTrainList.push_back(fileName); + + cout <<"\t"<<i <<"\t of \t"<<maxTrain<<" rnd file :"<< fileName<<endl; + img_input = imread(fileName.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::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 + + if(i>=(maxTrain-2)) + { + picsMask.push_back(img_mask.clone()); + picsOrigin.push_back(img_input.clone()); + } + + // //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 abort"<<endl; + return EXIT_FAILURE; + } + } + + + cout <<"b) we calc the two polygones of the points"<< fileName<<endl; + + if(picsMask.empty()) + { + cout<<"error no pics loaded"<<endl; + return EXIT_FAILURE; + } + else + cout<<"pics.size(): "<<picsMask.size()<<endl; + + int frameCounter = 0; + //vector<vector<vector<Point>>> polyGones; + vector<RotatedRect> rectanglesPicA;//we will save the rectangles for each polygone which was selected + vector<RotatedRect> rectanglesPicB; + + for(frameCounter=0;frameCounter<2;frameCounter++) + { + Mat img_mask = picsMask[frameCounter]; + + //! 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); + + + // //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****************************** + vector<vector<Point> > contourSelection; + //we exlcude very small one and very big ones + + //we calc all min rotated rectangles for all contour from candy egde detect + 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 = 15000; //TODO apply moving filter ??, an more adaptive approach + + //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; + //we add the rectangles to the list + if(frameCounter==0) + rectanglesPicA.push_back(minRect[i]); + if(frameCounter==1) + rectanglesPicB.push_back(minRect[i]); + + //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 + + // //! 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: + // vector<Point2f> massCenters( 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 ****************** + // vector<Point> conHull(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; + // Point2f muConvexHullMassCenter(0.0,0.0); + // if(!conHull.empty()) + // { + // muConvexHull = moments(conHull, true ); + // muConvexHullMassCenter= Point2f( muConvexHull.m10/muConvexHull.m00 , muConvexHull.m01/muConvexHull.m00 ); + // } + + //#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 + + // //! step 8: we write down all our results in yml file + // std::string nameOutPutFileData = outputDir + TToolBox::mNzero(frameCounter) + ".yml"; + + // FileStorage fs(nameOutPutFileData.c_str(), FileStorage::WRITE); + // fs << "masscenters" << massCenters; + // fs << "polygonselection"<< contourSelection; + // fs << "convexhull"<<conHull; + // fs << "masscenterconvexhull"<<muConvexHullMassCenter; + // fs.release(); + + + // //! 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) + ".jpg"; + // imwrite(nameOutPutFileDBGpic.c_str(),imgOverlay2); + + // } + + }//end for iterate frame + + + if(rectanglesPicA.empty()||rectanglesPicB.empty()) + cout<<"error no retangles found in pics "<<endl; + + Mat picA = picsOrigin[0].clone(); + Mat picB = picsOrigin[1].clone(); + //now we iterate all rectangles in picA and will produce pictures + for(size_t i=0;i<rectanglesPicA.size();i++) + { + std::string filenName = outputDir + "bk_candidate_a_" + TToolBox::mNzero(i) + ".jpg"; + cout << "process picA i"<<i<<" name" <<filenName << endl; + + //get the points + RotatedRect rectA= rectanglesPicA[i]; + Point2f rectApoints[4]; + //get all points of the retange + rectA.points( rectApoints ); + //@see https://docs.opencv.org/3.4.0/db/dd6/classcv_1_1RotatedRect.html#a69d648b086f26dbce0029facae9bfb2d + //The points array for storing rectangle vertices. + //The order is bottomLeft, topLeft, topRight, bottomRight. + Point2f corner = rectApoints[1]; + //we should add some offset + int offset = 50; //TODO double check offset + Point2f cornerOffset= Point2f((float)( corner.x-offset), (float) (corner.y-offset)); + + + Rect rect = rectA.boundingRect(); + //TODO check if out of our area + Rect rectOffset = Rect((float) (cornerOffset.x),(float) (cornerOffset.y),(float)(rect.width + offset) ,(float) (rect.height+offset )) ; + Mat imageRoi = picB(rectOffset); + + // std::string filenNameROI = outputDir + "bk_test_a_roi_" + TToolBox::mNzero(i) + ".jpg"; + // imwrite(filenNameROI.c_str(),imageRoi); + + //imageRoi = Scalar( 255, 0, 0); //fill blue) + + // std::cout << "rect size: " << rect.size() << std::endl; + // std::cout << "tempResult cols,rows: " << picB.cols << ", " << picB.rows << endl; + + cv::Rect rectROI(cornerOffset.x,cornerOffset.y, imageRoi.cols, imageRoi.rows); + imageRoi.copyTo(picA(rectROI)); + + cout << "."<<endl; + + imwrite(filenName.c_str(),picA); + } + //now we iterate all rectangles and will produce pictures + for(size_t i=0;i<rectanglesPicB.size();i++) + { + + std::string filenName = outputDir + "bk_candidate_b_" + TToolBox::mNzero(i) + ".jpg"; + cout << "process picB i"<<i<<" name" <<filenName << endl; + + //get the points + RotatedRect rectB= rectanglesPicB[i]; + Point2f rectBpoints[4]; + //get all points of the retange + rectB.points( rectBpoints ); + //@see https://docs.opencv.org/3.4.0/db/dd6/classcv_1_1RotatedRect.html#a69d648b086f26dbce0029facae9bfb2d + //The points array for storing rectangle vertices. + //The order is bottomLeft, topLeft, topRight, bottomRight. + Point2f corner = rectBpoints[1]; + //we should add some offset + int offset = 50; //TODO double check offset + Point2f cornerOffset= Point2f((float)( corner.x-offset), (float) (corner.y-offset)); + + Rect rect = rectB.boundingRect(); + //TODO check if out of our area + Rect rectOffset = Rect((float) (cornerOffset.x),(float)(cornerOffset.y),(float)(rect.width+offset) ,(float) (rect.height+offset)) ; + Mat imageRoi = picA(rectOffset); + + // std::string filenNameROI = outputDir + "bk_test_a_roi_" + TToolBox::mNzero(i) + ".jpg"; + // imwrite(filenNameROI.c_str(),imageRoi); + + //imageRoi = Scalar( 255, 0, 0); //fill blue) + + // std::cout << "rect size: " << rect.size() << std::endl; + // std::cout << "tempResult cols,rows: " << picB.cols << ", " << picB.rows << endl; + + cv::Rect rectROI(cornerOffset.x,cornerOffset.y, imageRoi.cols, imageRoi.rows); + imageRoi.copyTo(picB(rectROI)); + + cout << "."<<endl; + + imwrite(filenName.c_str(),picB); + + } + + // //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; + + + + + delete bgs; + + // capture.release(); + cvDestroyAllWindows(); + + return 0; }