Skip to content
Snippets Groups Projects
Commit ee50060e authored by am0ebe's avatar am0ebe
Browse files

.

parent d8ad04b2
No related branches found
No related tags found
No related merge requests found
/*
bgs_demo -i ../../dataset/video.tar -a 100 -o ../../output -c ../../config/centerConfigFile.xml -p ../../config/camParam.xml
*/
//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>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <archive.h>
#include <archive_entry.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <regex> //cpp 11X
#define PROCESS_CENTER_VERSION_MAJOR 2
#define PROCESS_CENTER_VERSION_MINOR 0
#define PROCESS_CENTER_VERSION_MINOR_FIXES 1
#include <opencv2/opencv.hpp> //opencv
#include "../src/algorithms/algorithms.h" //bgs
using namespace bgslibrary::algorithms;
using namespace cv;
using namespace std;
Scalar color_red( 0,0,255,255 );
int g_badSignalFlagAbort = 0;
void my_handler(int signum);
char* getCmdOption(char ** begin, char ** end, const string & option);
bool cmdOptionExists(char** begin, char** end, const string& option);
vector<char> copyDataInBuffer(struct archive *aw);
//! we convert our actual jpg file number to framenumber
int toFrameNumber(string filename);
int main(int argc, char * argv[])
{
signal(SIGUSR1, my_handler);
cout << "Using OpenCV " << CV_MAJOR_VERSION << "." << CV_MINOR_VERSION << "." << CV_SUBMINOR_VERSION << endl;
cout << "Using processcenter " << PROCESS_CENTER_VERSION_MAJOR << "." << PROCESS_CENTER_VERSION_MINOR << "." << PROCESS_CENTER_VERSION_MINOR_FIXES << endl << endl;
//!** parse programm input****************/
if( cmdOptionExists(argv, argv+argc, "-h")
|| cmdOptionExists(argv, argv+argc, "-?")
|| !cmdOptionExists(argv, argv+argc, "-i")
|| !cmdOptionExists(argv, argv+argc, "-a")
|| !cmdOptionExists(argv, argv+argc, "-o")
|| !cmdOptionExists(argv, argv+argc, "-p"))
{
cout << " Usage:" << endl;
cout << " " << argv[0] << " -i in.tar -a amount -c center.xml -o outPath -p camparameterFile.xml" << endl << endl;
cout << " Options:" << endl;
cout << " i - input tarfile/dir containing tars ?" << endl;
cout << " a - amount of files/frames ?" << endl;
cout << " c - exact center xml-conf file" << endl;
cout << " o - output path / dir" << endl;
cout << " p - camparameterFile ?" << endl;
return EXIT_FAILURE;
}
char *testFile = getCmdOption(argv, argv + argc, "-i");
string inputFile(".");
if (testFile)
{
//test dir exists
inputFile = string(testFile);
}
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);
}
char *camerFile = getCmdOption(argv, argv + argc, "-p");
string cameraParameterFile(".");
if (camerFile)
{
//test dir exists
cameraParameterFile = string(camerFile);
}
cout << "args: -i " << inputFile << " -a " << amountFiles << " -c" << centerFileString << " -o " << outputDir << " -p " << cameraParameterFile << endl;
//!**** end parse input***********/
//libarchive things
struct archive *archive;
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 = testFile;
archive = archive_read_new();
ext = archive_write_disk_new();
archive_write_disk_set_options(ext, flags);
archive_read_support_format_tar(archive);
//we get the filename
if (filename != NULL && strcmp(filename, "-") == 0)
filename = NULL;
//and open the handler
if ((r = archive_read_open_filename(archive, filename, 10240)))
{
cerr << "archive_read_open_filename: error: " << archive_error_string(archive) << " will abort" << endl;
exit(1);
}
/* #### Background Subtraction Methods #####
Codebook is new!
Tapter is TBoy!
List of all algorithms:
AdaptiveBackgroundLearning,AdaptiveSelectiveBackgroundLearning,CodeBook,DPAdaptiveMedian,DPEigenbackground,
DPGrimsonGMM,DPMean,DPPratiMediod,DPTexture,DPWrenGA,DPZivkovicAGMM,FrameDifference,FuzzyChoquetIntegral,
FuzzySugenoIntegral,GMG,IndependentMultimodal,KDE,KNN,LBAdaptiveSOM,LBFuzzyAdaptiveSOM,LBFuzzyGaussian,
LBMixtureOfGaussians,LBP_MRF,LBSimpleGaussian,LOBSTER,MixtureOfGaussianV2,MixtureOfGaussianV1,MultiCue,
MultiLayer,PAWCS,PixelBasedAdaptiveSegmenter,SigmaDelta,StaticFrameDifference,SuBSENSE,T2FGMM_UM,T2FGMM_UV,
T2FMRF_UM,T2FMRF_UV,TwoPoints,ViBe,VuMeter,WeightedMovingMean,WeightedMovingVariance
(Note that some of these algorithms are available only for a specific version of OpenCV, see algorithms.h)
*/
IBGS *bgs = new FrameDifference;
// IBGS *bgs = new PixelBasedAdaptiveSegmenter; // TODO
//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 (tapter?)
//init the random number generator
srand (time(NULL));
clock_t beginAll = clock();
//! read the center config file to 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" << endl;
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();
cout << "here" << endl;
system("pause");
//open camera config file
cv::String camParam (cameraParameterFile);
Mat intrinsicsCameraMatrix, distortionCoeff;
{
cout << "read cam parameter of: " << cameraParameterFile << endl;
FileStorage fs;
fs.open(camParam, FileStorage::READ);
if (!fs.isOpened())
{
cerr << "error during open " << cameraParameterFile << " will abort" << endl;
return -1;
}
fs["camera_matrix"] >> intrinsicsCameraMatrix;
fs["distortion_coefficients"] >> distortionCoeff;
// intrinsicsCameraMatrix = (int) fs["camera_matrix"];
// intrinsicsCameraMatrix = fs["camera_matrix"].mat();
cout << "camera_matrix = " << intrinsicsCameraMatrix << endl;
// distortionCoeff = (int) fs["distortion_coefficients"];
// distortionCoeff = fs["distortion_coefficients"].mat();
cout << "distortion_coefficients = " << distortionCoeff << endl;
}
cout << "a) process all frames " << endl;
int everyPic= 60*5;
//string fileName;
int frameCounter=0;
int myFileTarWriterHeaderCounter = 0;
int frameCounterOld = -1;
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;
//loop over _all_ pictures in the tar archive
for (;;)
{
//measure time consumption
//sa opencv tick timer:
// https://docs.opencv.org/4.x/d9/d6f/classcv_1_1TickMeter.html#details
clock_t begin = clock(); //for every single file
vector<char> vec;
//read the next header
r = archive_read_next_header(archive, &entry);
if (r == ARCHIVE_EOF)
break;
if (r != ARCHIVE_OK)
{
cerr << "archive_read_next_header: error: " << archive_error_string(archive) << " will abort" << endl;
exit(1);
}
cout << "here2" << endl;
// get filename
const char *fileNamePtr = archive_entry_pathname(entry);
string filename(fileNamePtr,strlen(fileNamePtr) );
//cout << "fileName: " << filename << endl;
// convert it to a framenumber
frameCounter = toFrameNumber(filename);
if(frameCounterOld>frameCounter)
{
cerr << " error during read in the file number, found non-monotonic order, will abort";
exit(1);
}
frameCounterOld = frameCounter;
r = archive_write_header(ext, entry);
if (r != ARCHIVE_OK)
{
cerr << "archive_write_header() error: " << archive_error_string(ext)<< endl;
myFileTarWriterHeaderCounter++;
continue; //we overjump all in our for loop
}
vec = copyDataInBuffer(archive);
if(vec.empty())
cerr << "error during load data into buffer";
r = archive_write_finish_entry(ext);
if (r != ARCHIVE_OK)
{
cerr << "archive_write_finish_entry: error: " << archive_error_string(ext) << " will abort" << endl;
exit(1);
}
// read the image buffer as a jpg picture and decode it
Mat img_input = imdecode(Mat(vec), 1);
cout << "\t" << frameCounter << "\tof \t" << amountFiles << " load file :" << filename << endl;
//of data is present
if(img_input.data )
{
//! step 0 correct lense distortion
Mat imgLenseCorrection = img_input.clone();
//see https://docs.opencv.org/2.4/modules/imgproc/doc/geometric_transformations.html#undistort
cv::undistort(img_input, imgLenseCorrection, intrinsicsCameraMatrix, distortionCoeff);
//! step 1) cut out a smaller ROI
img_input = TToolBox::cropImageCircle(imgLenseCorrection,circleCenterX,circleCenterY,circleRadius);
//! step 2) normal bgs processing
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
//! step 3) apply 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;
vector<vector<Point> > contours = TToolBox::applyCannyEdgeAndCalcCountours(img_mask,threshholdMin,threshholdMax,apertureSize);
//define what will be written
vector<vector<Point> > contourSelection;
vector<Point2f> massCenters;
vector<Point> conHull;
Point2f muConvexHullMassCenter(0.0,0.0);
if(!contours.empty())
{
//! step 4) we make a selection out of all contours with area sizes
//******************************
//calc all min rotated rectangles for all contour from canny edge detect
//exclude very small/big
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
//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 );
//calc the min circle around
// Point roiCenter;
// float roiRadius;
//minEnclosingCircle(conHull,roiCenter,roiRadius);
// 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 );
}
}
else //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); //fill the picture
polylines(imgConvexHull, hullComplete, true, color_red, 1, 8);
//draw circle around
//circle( imgConvexHull, roiCenter, (int) roiRadius, color_red, 2, 8, 0 );
//we draw it
cv::String outpath2 = outputDir;
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 << " found center at : " << massCenters.at(0).x << ";" << massCenters.at(0).y << endl;
//! step 8: we write down all our results in yml file
string nameOutPutFileData = outputDir + TToolBox::mNzero(frameCounter) + ".yml";
//cout << "output file:" << nameOutPutFileData;
FileStorage fs(nameOutPutFileData.c_str(), FileStorage::WRITE);
fs << "masscenters" << massCenters;
fs << "polygonselection" << contourSelection;
fs << "convexhull" << conHull;
fs << "masscenterconvexhull" << muConvexHullMassCenter;
fs.release();
//! occasionaly write a dbg picture
if(frameCounter%everyPic==0)
{
RNG rng(4344234);
Mat imgDebugPaint2 = Mat::zeros( img_input.size(), CV_8UC3 );
imgDebugPaint2 = Scalar(255,255,255); //fill the picture white
// 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 );
}
// write the convex hull
if(!conHull.empty())
{
//the poly
polylines(imgDebugPaint2, conHull, true, color_red, 1, 8);
//the center
circle( imgDebugPaint2,muConvexHullMassCenter, 4, color_red, -1, 8, 0 );
}
// copy
Mat imgOverlay2 = img_input.clone();
// add overlay of paintings
addWeighted( imgDebugPaint2, 0.7, imgOverlay2, 0.3, 0.0, imgOverlay2);
// writeout file
string nameOutPutFileDBGpic = outputDir + TToolBox::mNzero(frameCounter) + string(".jpg");
imwrite(nameOutPutFileDBGpic.c_str(),imgOverlay2);
}//end if dbg picture
}//end if the loaded picture has data
else
{
cerr << "error loading file: " << filename << ", will skip this file" << endl;
myFileErrorList.push_back(filename);
}
//calc the time which we used for a picture //TODO move out of loop
clock_t end = clock();
double elapsedSecs = double(end - begin) / CLOCKS_PER_SEC;
//calc the time which was used for all pictures
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;
if(g_badSignalFlagAbort)
frameCounter = amountFiles; // abort
//if(frameCounter>10)exit(0); //the test abort function
}//end for ever loop
//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
// string nameOutRandomFile = outputDir + "randlist.yml";
// FileStorage fs(nameOutRandomFile.c_str(), FileStorage::WRITE);
// fs << "randomlist" << myRandomTrainList;
// fs.release();
//TODO we should merge the file
cout << "amount of libarchive read header errors :" << myFileTarWriterHeaderCounter;
// write the random file list to a file
string nameOutErrorList = outputDir + "fileErrorList.yml";
cout << "amount of file errors: " << myFileErrorList.size()<< endl;
FileStorage fs2(nameOutErrorList.c_str(), FileStorage::WRITE);
fs2 << "fileErrorIOs" << myFileErrorList;
// write error list no contours found in file
cout << "amount contour errors with canny edge: " << myFileListNoContour.size() << endl;
fs2 << "fileErrorNoContours" << myFileListNoContour;
// write error list no contours found in file
cout << "amount contour errors after selection: " << myFileListAfterContourSelection.size() << endl;
fs2 << "fileErrorNoContoursAfterSelections" << myFileListAfterContourSelection;
// bgs related things
delete bgs;
// opencv related things
fs2.release();
cvDestroyAllWindows();
//close lib archive related things
archive_read_close(archive);
archive_read_free(archive);
archive_write_close(ext);
archive_write_free(ext);
return 0;
}
vector<char> copyDataInBuffer(struct archive *aw)
{
int r;
const void *buff;
vector<char> vec;
size_t size;
#if ARCHIVE_VERSION_NUMBER >= 3000000
int64_t offset;
#else
off_t offset;
#endif
//forever till we get a specific return
for (;;) {
r = archive_read_data_block(aw, &buff, &size, &offset);
if (r == ARCHIVE_EOF)
{
return vec; // everything fine, were are just at the end
}
if (r != ARCHIVE_OK)
{
cerr << "error during read archive " << endl;
return vec;
}
//a good discussion : https://stackoverflow.com/questions/259297/how-do-you-copy-the-contents-of-an-array-to-a-stdvector-in-c-without-looping
// Method 4: vector::insert
{
//we rename our pointer to avoid a weird compiler warning
char *foo = (char*) buff;
vec.insert(vec.end(), &foo[0], &foo[size]);
}
}
return vec;
}
void my_handler(int signum)
{
if (signum == SIGUSR1)
{
g_badSignalFlagAbort = 1;
cerr << "receive signal to abort" << endl;
}
}
char* getCmdOption(char ** begin, char ** end, const string & option)
{
char ** itr = find(begin, end, option);
if (itr != end && ++itr != end)
{
return *itr;
}
return 0;
}
bool cmdOptionExists(char** begin, char** end, const string& option)
{
return find(begin, end, option) != end;
}
int toFrameNumber(string filename)
{
int retVal = -1;
//we cut out all non needed substrings
filename = regex_replace(filename, regex("/"), "");
filename = regex_replace(filename, regex("data_sized"), "");
filename = regex_replace(filename, regex("jpg"), "");
filename = regex_replace(filename, regex("\\."), "");
retVal = stoi( filename );
//cout << "filename out:" << filename << " number: " << retVal << endl;
return retVal;
}
......@@ -236,7 +236,7 @@ int main(int argc, char * argv[])
cout << "distortion_coefficients = " << distortionCoeff << endl;
}
cout << "a) we process all frames " << endl;
cout << "a) process all frames " << endl;
int everyPic= 60*5;
//string fileName;
......@@ -247,7 +247,7 @@ int main(int argc, char * argv[])
vector<string> myFileListNoContour; //list for no contours found;
vector<string> myFileListAfterContourSelection; //list for no contours found after selection;
//loop over _all_ picture of the tar archive
//loop over _all_ pictures in the tar archive
for (;;)
{
......@@ -257,7 +257,7 @@ int main(int argc, char * argv[])
clock_t begin = clock(); //for every single file
vector<char> vec;
//we read the next header
//read the next header
r = archive_read_next_header(archive, &entry);
if (r == ARCHIVE_EOF)
break;
......@@ -277,7 +277,7 @@ int main(int argc, char * argv[])
if(frameCounterOld>frameCounter)
{
cerr << " error during read in the file number, we do have non montonic order, will abort";
cerr << " error during read in the file number, found non-monotonic order, will abort";
exit(1);
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment