<commit_before>
#include "FaceTracker.hpp"
#include <exception>
#include <cmath>
#include <stdio.h>

using namespace std;

namespace YerFace {

FaceTracker::FaceTracker(string myClassifierFileName, FrameDerivatives *myFrameDerivatives, float myTrackingBoxPercentage, float myMaxFaceSizePercentage, int myOpticalTrackStaleFramesInterval) {
	classifierFileName = myClassifierFileName;
	frameDerivatives = myFrameDerivatives;
	trackerState = DETECTING;
	classificationBoxSet = false;
	trackingBoxSet = false;

	trackingBoxPercentage = myTrackingBoxPercentage;
	if(trackingBoxPercentage <= 0.0 || trackingBoxPercentage > 1.0) {
		throw invalid_argument("trackingBoxPercentage is out of range.");
	}
	maxFaceSizePercentage = myMaxFaceSizePercentage;
	if(maxFaceSizePercentage <= 0.0 || maxFaceSizePercentage > 1.0) {
		throw invalid_argument("maxFaceSizePercentage is out of range.");
	}
	opticalTrackStaleFramesInterval = myOpticalTrackStaleFramesInterval;
	if(opticalTrackStaleFramesInterval <= 0) {
		throw invalid_argument("opticalTrackStaleFramesInterval is out of range.");
	}
	if(!cascadeClassifier.load(classifierFileName)) {
		throw invalid_argument("Unable to load specified classifier.");
	}
	fprintf(stderr, "FaceTracker object constructed and ready to go!\n");
}

TrackerState FaceTracker::processCurrentFrame(void) {
	if(trackerState == DETECTING || trackerState == LOST || trackerState == STALE) {
		classificationBoxSet = false;
		std::vector<Rect> faces;
		Mat classificationFrame = frameDerivatives->getClassificationFrame();
		double classificationFrameArea = (double)classificationFrame.size().area();
		double maxFaceSize = sqrt(classificationFrameArea * maxFaceSizePercentage);
		cascadeClassifier.detectMultiScale(classificationFrame, faces, 1.1, 3, 0|CASCADE_SCALE_IMAGE, Size(maxFaceSize, maxFaceSize));

		int largestFace = -1;
		int largestFaceArea = -1;
		for( size_t i = 0; i < faces.size(); i++ ) {
			if(faces[i].area() > largestFaceArea) {
				largestFace = i;
				largestFaceArea = faces[i].area();
			}
		}
		if(largestFace >= 0) {
			classificationBoxSet = true;
			double classificationScaleFactor = frameDerivatives->getClassificationScaleFactor();
			classificationBox = faces[largestFace];
			classificationBoxNormalSize = Rect(
				(double)classificationBox.x / classificationScaleFactor,
				(double)classificationBox.y / classificationScaleFactor,
				(double)classificationBox.width / classificationScaleFactor,
				(double)classificationBox.height / classificationScaleFactor);
			//Switch to TRACKING
			trackerState = TRACKING;
			#if (CV_MINOR_VERSION < 3)
			tracker = Tracker::create("KCF");
			#else
			tracker = TrackerKCF::create();
			#endif
			double trackingBoxWidth = (double)classificationBoxNormalSize.width * trackingBoxPercentage;
			double trackingBoxHeight = (double)classificationBoxNormalSize.height * trackingBoxPercentage;
			Rect trackingBox = Rect(
				(double)classificationBoxNormalSize.x + (((double)classificationBoxNormalSize.width - trackingBoxWidth) / 2.0),
				(double)classificationBoxNormalSize.y + (((double)classificationBoxNormalSize.height - trackingBoxHeight) / 2.0),
				trackingBoxWidth,
				trackingBoxHeight);
			tracker->init(frameDerivatives->getCurrentFrame(), trackingBox);
			staleCounter = opticalTrackStaleFramesInterval;
		}
	} else if(trackerState == TRACKING) {
		bool trackSuccess = tracker->update(frameDerivatives->getCurrentFrame(), trackingBox);
		if(!trackSuccess) {
			fprintf(stderr, "FaceTracker WARNING! Track lost. Will keep searching...\n");
			trackingBoxSet = false;
			trackerState = LOST;
			//Attempt to re-process this same frame in LOST mode.
			return this->processCurrentFrame();
		} else {
			trackingBoxSet = true;
			staleCounter--;
			if(staleCounter <= 0) {
				trackerState = STALE;
			}
		}<commit_msg>fix an issue where stale state would prevent optical tracking from proceeding<commit_after>
#include "FaceTracker.hpp"
#include <exception>
#include <cmath>
#include <stdio.h>

using namespace std;

namespace YerFace {

FaceTracker::FaceTracker(string myClassifierFileName, FrameDerivatives *myFrameDerivatives, float myTrackingBoxPercentage, float myMaxFaceSizePercentage, int myOpticalTrackStaleFramesInterval) {
	classifierFileName = myClassifierFileName;
	frameDerivatives = myFrameDerivatives;
	trackerState = DETECTING;
	classificationBoxSet = false;
	trackingBoxSet = false;

	trackingBoxPercentage = myTrackingBoxPercentage;
	if(trackingBoxPercentage <= 0.0 || trackingBoxPercentage > 1.0) {
		throw invalid_argument("trackingBoxPercentage is out of range.");
	}
	maxFaceSizePercentage = myMaxFaceSizePercentage;
	if(maxFaceSizePercentage <= 0.0 || maxFaceSizePercentage > 1.0) {
		throw invalid_argument("maxFaceSizePercentage is out of range.");
	}
	opticalTrackStaleFramesInterval = myOpticalTrackStaleFramesInterval;
	if(opticalTrackStaleFramesInterval <= 0) {
		throw invalid_argument("opticalTrackStaleFramesInterval is out of range.");
	}
	if(!cascadeClassifier.load(classifierFileName)) {
		throw invalid_argument("Unable to load specified classifier.");
	}
	fprintf(stderr, "FaceTracker object constructed and ready to go!\n");
}

TrackerState FaceTracker::processCurrentFrame(void) {
	if(trackerState == DETECTING || trackerState == LOST || trackerState == STALE) {
		classificationBoxSet = false;
		std::vector<Rect> faces;
		Mat classificationFrame = frameDerivatives->getClassificationFrame();
		double classificationFrameArea = (double)classificationFrame.size().area();
		double maxFaceSize = sqrt(classificationFrameArea * maxFaceSizePercentage);
		cascadeClassifier.detectMultiScale(classificationFrame, faces, 1.1, 3, 0|CASCADE_SCALE_IMAGE, Size(maxFaceSize, maxFaceSize));

		int largestFace = -1;
		int largestFaceArea = -1;
		for( size_t i = 0; i < faces.size(); i++ ) {
			if(faces[i].area() > largestFaceArea) {
				largestFace = i;
				largestFaceArea = faces[i].area();
			}
		}
		if(largestFace >= 0) {
			classificationBoxSet = true;
			double classificationScaleFactor = frameDerivatives->getClassificationScaleFactor();
			classificationBox = faces[largestFace];
			classificationBoxNormalSize = Rect(
				(double)classificationBox.x / classificationScaleFactor,
				(double)classificationBox.y / classificationScaleFactor,
				(double)classificationBox.width / classificationScaleFactor,
				(double)classificationBox.height / classificationScaleFactor);
			//Switch to TRACKING
			trackerState = TRACKING;
			#if (CV_MINOR_VERSION < 3)
			tracker = Tracker::create("KCF");
			#else
			tracker = TrackerKCF::create();
			#endif
			double trackingBoxWidth = (double)classificationBoxNormalSize.width * trackingBoxPercentage;
			double trackingBoxHeight = (double)classificationBoxNormalSize.height * trackingBoxPercentage;
			Rect trackingBox = Rect(
				(double)classificationBoxNormalSize.x + (((double)classificationBoxNormalSize.width - trackingBoxWidth) / 2.0),
				(double)classificationBoxNormalSize.y + (((double)classificationBoxNormalSize.height - trackingBoxHeight) / 2.0),
				trackingBoxWidth,
				trackingBoxHeight);
			tracker->init(frameDerivatives->getCurrentFrame(), trackingBox);
			staleCounter = opticalTrackStaleFramesInterval;
		}
	}
	if(trackerState == TRACKING || trackerState == STALE) {
		bool trackSuccess = tracker->update(frameDerivatives->getCurrentFrame(), trackingBox);
		if(!trackSuccess) {
			fprintf(stderr, "FaceTracker WARNING! Track lost. Will keep searching...\n");
			trackingBoxSet = false;
			trackerState = LOST;
			//Attempt to re-process this same frame in LOST mode.
			return this->processCurrentFrame();
		} else {
			trackingBoxSet = true;
			staleCounter--;
			if(staleCounter <= 0) {
				trackerState = STALE;
			}
		}
{'fraction_non_alphanumeric': 0.10350627506792599, 'fraction_numerical': 0.005951610816405745, 'mean_word_length': 5.686851211072664, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 33, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2182411', 'n_tokens_mistral': 2554, 'n_tokens_neox': 2215, 'n_words': 468}