diff --git a/CMakeLists.txt b/CMakeLists.txt index 6a01cce7f22aefc347789b441115adb3c734e168..b15bdfc6f7b3185b64d0322b282f42ce56ced6e3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -66,6 +66,13 @@ if(${OpenCV_VERSION} VERSION_LESS 2.3.1) message(FATAL_ERROR "OpenCV version is not compatible: ${OpenCV_VERSION}") endif() +find_package(LibArchive REQUIRED) +message(STATUS "LibArchive library status:") +message(STATUS " version: ${LibArchive_VERSION}") +message(STATUS " libraries: ${LibArchive_LIBRARIES}") +message(STATUS " include path: ${LibArchive_VERSION}") + + if(BGS_PYTHON_SUPPORT) set(Boost_USE_STATIC_LIBS OFF) set(Boost_USE_MULTITHREADED ON) @@ -134,7 +141,7 @@ add_executable(bgs_demo ${demo}) target_link_libraries(bgs_demo ${OpenCV_LIBS} libbgs) add_executable(bgs_demo2 ${demo2}) -target_link_libraries(bgs_demo2 ${OpenCV_LIBS} libbgs) +target_link_libraries(bgs_demo2 ${OpenCV_LIBS} ${LibArchive_LIBRARIES} libbgs) install(TARGETS libbgs bgslibrary diff --git a/Demo2.cpp b/Demo2.cpp index e518a8c9b576f5d7d45e37b6c7b6437ea6f344be..6c114134df1ba91ef369cd2b320d1976d7c83014 100644 --- a/Demo2.cpp +++ b/Demo2.cpp @@ -3,6 +3,15 @@ based on original demo.cpp */ +// c +#include <sys/types.h> +#include <sys/stat.h> +#include <archive.h> +#include <archive_entry.h> +#include <fcntl.h> +#include <string.h> +#include <unistd.h> + //cpp c #include <iostream> #include <algorithm> @@ -12,7 +21,6 @@ based on original demo.cpp #include <time.h> /* time */ #include <ctime> - #define PROCESS_CENTER_VERSION_MAJOR 0 #define PROCESS_CENTER_VERSION_MINOR 2 @@ -92,571 +100,16 @@ int main(int argc, char * argv[]) 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; - - - + struct archive *a; + struct archive *ext; + struct archive_entry *entry; + int r; + int flags = ARCHIVE_EXTRACT_TIME; // see https://linux.die.net/man/3/archive_write_disk for more flags + const char *filename = "recTest.tar"; - delete bgs; + a = archive_read_new(); + ext = archive_write_disk_new(); + archive_write_disk_set_options(ext, flags); // capture.release(); cvDestroyAllWindows();