diff --git a/Demo.cpp b/Demo.cpp index 4a5559a28113ce2214f5ae1cefc5e6ec6c940693..351d21fd3160e99797e0bb2a002c6bd30e1142c8 100644 --- a/Demo.cpp +++ b/Demo.cpp @@ -10,27 +10,30 @@ based on original demo.cpp #include <stdio.h> /* printf, scanf, puts, NULL */ #include <stdlib.h> /* srand, rand */ #include <time.h> /* time */ +#include <ctime> + //opencv #include <opencv2/opencv.hpp> //bgslibrary #include "package_bgs/bgslibrary.h" //my class #include "package_bgs/Tapter.h" - -std::string mNzero(int i) -{ - std::ostringstream convert; - convert << i ; - std::string numberString = convert.str(); - std::string newNumberString = std::string(10 - numberString.length(), '0') + numberString; - return newNumberString; -} -std::string getFileName(int i) -{ - //cv::String inputPath= "/homes/tb55xemi/work/bugTrainingSet/testRec/rec04379437pp/data/"; - std::string fileName = "/data/"+ mNzero(i) + ".jpg"; - return fileName; -} +#include "package_bgs/ttoolbox.h" + +//std::string mNzero(int i) +//{ +// std::ostringstream convert; +// convert << i ; +// std::string numberString = convert.str(); +// std::string newNumberString = std::string(10 - numberString.length(), '0') + numberString; +// return newNumberString; +//} +//std::string getFileName(int i) +//{ +// //cv::String inputPath= "/homes/tb55xemi/work/bugTrainingSet/testRec/rec04379437pp/data/"; +// std::string fileName = "/data/"+ mNzero(i) + ".jpg"; +// return fileName; +//} char* getCmdOption(char ** begin, char ** end, const std::string & option) @@ -167,8 +170,11 @@ int main(int argc, char * argv[]) Tapter *bgs = new Tapter; - bgs->setInitialFrameCounter(0); 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/ @@ -206,12 +212,12 @@ int main(int argc, char * argv[]) //! we train with first 54 on random draws cout <<"b) we train the background with random choosen files"<< fileName<<endl; - list<string> myRandomTrainList; //we save all draws in a list which will save to the results + vector<string> myRandomTrainList; //we save all draws in a list which will save to the results for(i=0;i<54;i++) //TODO make 54 as parameter { //random index int index = rand() % steps + begin; //TODO: double check no double draw ?? - fileName = inputDir + getFileName(index); + fileName = inputDir + TToolBox::getFileName(index); myRandomTrainList.push_back(fileName); cout <<"load rnd file :"<< fileName<<endl; @@ -232,10 +238,18 @@ int main(int argc, char * argv[]) } cout <<"c) we produce train the background with random choosen files"<< fileName<<endl; + bgs->setInitialFrameCounter(0); + bgs->setFlagWrite(1); + bgs->setFlagWriteDBGpic(1); + + clock_t beginAll = clock(); for(i=begin;i<begin+steps;i++) { - fileName = inputDir + getFileName(i); + + clock_t begin = clock(); + + fileName = inputDir + TToolBox::getFileName(i); cout <<"load file :"<< fileName<<endl; //cv::imwrite(convert.str().c_str(), img_output); img_input = imread(fileName.c_str(), CV_LOAD_IMAGE_COLOR); @@ -253,27 +267,23 @@ int main(int argc, char * argv[]) cout<<"error loading file: "<< fileName<<", will abort"<<endl; return EXIT_FAILURE; } - } - /* - while (key != 'q') - { - capture >> img_input; - 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, it shows automatically the foreground mask image + clock_t end = clock(); + double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC; - //if(!img_mask.empty()) - // cv::imshow("Foreground", img_mask); - // do something + cout <<"process took:\t"<<elapsed_secs<<"s"<<endl; + } - key = cvWaitKey(33); - } + clock_t endAll = clock(); + double elapsed_secs = double(endAll - beginAll) / CLOCKS_PER_SEC; + cout <<"process"<<amountFiles<<" took:\t"<<(int)(elapsed_secs/60)<<" min"<<endl; + //we write the random file list + //format output file + std::string nameOutRandomFile = outputDir + "randlist.yml"; -*/ + FileStorage fs(nameOutRandomFile.c_str(), FileStorage::WRITE); + fs << "randomlist" << myRandomTrainList; + fs.release(); delete bgs; diff --git a/package_bgs/Tapter.cpp b/package_bgs/Tapter.cpp index 92738941b68eba6556f9f62556f19e2504dc1900..5e86569ab9500313c5a5db1060337a60b89b544a 100644 --- a/package_bgs/Tapter.cpp +++ b/package_bgs/Tapter.cpp @@ -26,6 +26,8 @@ Tapter::Tapter() : frameCounter = 0; //inputPath = "."; outputPath = "."; + flagWrite = -1; + writeDbgPic = -1; } @@ -35,6 +37,16 @@ Tapter::~Tapter() std::cout << "~Tapter()" << std::endl; } +void Tapter::setFlagWrite(short flag) +{ + flagWrite = flag; +} + +void Tapter::setFlagWriteDBGpic(short flag) +{ + writeDbgPic = flag; +} + void Tapter::setPathOut(std::string outPath) { outputPath = outPath; @@ -99,52 +111,6 @@ void Tapter::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img vector<vector<Point> > contours = applyCannyEdgeAndCalcCountours(img_output,threshholdMin,threshholdMax,apertureSize); - - //! produce center of convex hull of all polygones -// //TODO double check if ne contour sharing a center point ? nearby ?? - -// //TODO we should apply everything to the selection !!!! - -// //! calc convex hull of all remaining contours ************************* -// vector<Point> allContourPoints; -// //we merge all points -// for (size_t cC = 0; cC < contours.size(); ++cC) -// for(size_t cP =0; cP < contours[cC].size(); cP++) -// { -// Point currentContourPixel = contours[cC][cP]; -// allContourPoints.push_back(currentContourPixel); -// } - - -// ////calc the hull ****************** -// vector<Point> hullComplete(allContourPoints.size()); -// convexHull( Mat(allContourPoints), hullComplete, false ); - -// if(!hullComplete.empty())//if we any elements, we process further -// { -// // Point2f roiCenter; -// // float roiRadius; - -// //calc the min circle around -// //minEnclosingCircle(hullComplete,roiCenter,roiRadius); - -//#ifdef MC_SHOW_STEP_ANALYSE -// 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= "/homes/tb55xemi/work/bugTrainingSet/testRec/rec04379437pp/result/"; -// std::ostringstream convert2; -// convert2 << outpath2 << frameCounter <<"_convex_hull.jpg"; -// cv::imwrite(convert2.str().c_str(), imgConvexHull); -//#endif - // //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; @@ -180,12 +146,10 @@ void Tapter::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img //// cout<<"approximate poly has not enough points will skip file: "<<frameCounter<<endl; ////#endif -// } -// else -// cout<<"convex hull has no points will skip file: "<<frameCounter<<endl; ///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 @@ -196,7 +160,6 @@ void Tapter::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img minRect[i] = minAreaRect( Mat(contours[i]) ); //may use boundingRect ?? to use fix non rotated rectangles ? vector<Point2f> recCenterPoints; - vector<vector<Point> > contourSelection; float areaMinThreshold = 150; float areaMaxThreshold = 15000; //TODO apply moving filter ??, an more adaptive approach @@ -237,19 +200,132 @@ void Tapter::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img ///we calc the moments from the contour selection vector<Moments> mu(contourSelection.size() ); - for( int i = 0; i < contourSelection.size(); i++ ) + 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( int i = 0; i < contourSelection.size(); i++ ) + for( size_t i = 0; i < contourSelection.size(); i++ ) { massCenters[i] = Point2f( mu[i].m10/mu[i].m00 , mu[i].m01/mu[i].m00 ); } + //! 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 moments from the contour selection + 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= "/homes/tb55xemi/work/bugTrainingSet/testRec/rec04379437pp/result/"; + std::ostringstream convert2; + convert2 << outpath2 << frameCounter <<"_convex_hull.jpg"; + cv::imwrite(convert2.str().c_str(), imgConvexHull); + } + else + cout<<"convex hull has no points will skip file: "<<frameCounter<<endl; + +#endif + + if(flagWrite) + { + //format output file + std::string nameOutPutFileData = outputPath + TToolBox::mNzero(frameCounter) + ".yml"; + + FileStorage fs(nameOutPutFileData.c_str(), FileStorage::WRITE); + fs << "masscenters" << massCenters; + fs << "polygonselection"<< contourSelection; + fs << "convexhull"<<conHull; + fs << "masscenterconvexhull"<<muConvexHullMassCenter; + + //fs << "masscenters" << "["; +// for( size_t i = 0; i < massCenters.size(); i++ ) +// { +// Point2f p = massCenters[i]; +// fs << "{:" << "x" << (float) p.x << "y" << (float) p.y << "}"; +// } +// fs << "]"; + + fs.release(); + + } + + if(writeDbgPic) + { + 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 = outputPath + TToolBox::mNzero(frameCounter) + ".jpg"; + imwrite(nameOutPutFileDBGpic.c_str(),imgOverlay2); + + } #ifdef MC_SHOW_STEP_ANALYSE @@ -325,7 +401,7 @@ void Tapter::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img } else cout<<"error no contour in selective list left, skip frame: "<<frameCounter<<endl; -#endif + //******** @@ -335,7 +411,9 @@ void Tapter::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img convert << outpath << frameCounter++ << ".jpg"; cv::imwrite(convert.str().c_str(), img_output); //**** end - +#else + frameCounter++; +#endif delete frame; @@ -420,8 +498,6 @@ vector<vector<Point> > Tapter::applyCannyEdgeAndCalcCountours(Mat imgSource, dou #endif - - // return minRect; return contours; } diff --git a/package_bgs/Tapter.h b/package_bgs/Tapter.h index cbfe940f3f89575a4ba7f4fe7f7962e1e38dc7cb..840f7fa2669c3613cd12814fac29c3689c308a3e 100644 --- a/package_bgs/Tapter.h +++ b/package_bgs/Tapter.h @@ -26,8 +26,10 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. #include "lb/BGModelSom.h" #include "IBGS.h" +#include "ttoolbox.h" -#define MC_SHOW_STEP_ANALYSE + +//#define MC_SHOW_STEP_ANALYSE using namespace lb_library; using namespace lb_library::AdaptiveSOM; @@ -50,6 +52,8 @@ namespace bgslibrary int frameCounter; // std::string inputPath; + short flagWrite; + short writeDbgPic; std::string outputPath; public: @@ -61,6 +65,14 @@ namespace bgslibrary // void setPaths(std::string inPath,std::string outPath); void setPathOut(std::string outPath); + //! 1 is on + //! other no write + void setFlagWrite(short flag); + + //! 1 is on + //! other no write + void setFlagWriteDBGpic(short flag); + void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel); private: @@ -68,6 +80,7 @@ namespace bgslibrary void loadConfig(); vector<vector<Point> > applyCannyEdgeAndCalcCountours(cv::Mat imgSource, double threshholdMin, double threshholdMax, int apertureSize); + }; } }