From ee50060ebf68f5c69178ad8cebe5ce02293fde8d Mon Sep 17 00:00:00 2001
From: am0ebe <am0ebe@gmx.de>
Date: Thu, 27 Jan 2022 21:06:25 +0100
Subject: [PATCH] .

---
 examples/Demo.c   | 680 ++++++++++++++++++++++++++++++++++++++++++++++
 examples/Demo.cpp |   8 +-
 2 files changed, 684 insertions(+), 4 deletions(-)
 create mode 100644 examples/Demo.c

diff --git a/examples/Demo.c b/examples/Demo.c
new file mode 100644
index 0000000..1311d95
--- /dev/null
+++ b/examples/Demo.c
@@ -0,0 +1,680 @@
+/*
+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;
+}
diff --git a/examples/Demo.cpp b/examples/Demo.cpp
index 14f6278..1311d95 100644
--- a/examples/Demo.cpp
+++ b/examples/Demo.cpp
@@ -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);
 		}
 
-- 
GitLab