Add the option to focus on a spcific person
This commit is contained in:
		
							parent
							
								
									f97f4640a9
								
							
						
					
					
						commit
						55953bcdb7
					
				
					 3 changed files with 27 additions and 12 deletions
				
			
		| 
						 | 
					@ -106,28 +106,35 @@ void FaceRecognizer::clearReferances()
 | 
				
			||||||
	referanceFeatures.clear();
 | 
						referanceFeatures.clear();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
std::pair<int, double> FaceRecognizer::isMatch(const cv::Mat& input, bool alone)
 | 
					FaceRecognizer::Detection FaceRecognizer::isMatch(const cv::Mat& input, bool alone)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	cv::Mat faces = detectFaces(input);
 | 
						cv::Mat faces = detectFaces(input);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if(alone && faces.rows > 1)
 | 
						Detection bestMatch;
 | 
				
			||||||
		return {-2, 0};
 | 
						bestMatch.confidence = 0;
 | 
				
			||||||
 | 
						bestMatch.person = -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	std::pair<int, double> bestMatch = {-1, 0};
 | 
						if(alone && faces.rows > 1)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							bestMatch.person = -2;
 | 
				
			||||||
 | 
							return bestMatch;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for(int i = 0; i < faces.rows; ++i)
 | 
						for(int i = 0; i < faces.rows; ++i)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		cv::Mat face;
 | 
							cv::Mat face;
 | 
				
			||||||
		recognizer->alignCrop(input, faces.row(0), face);
 | 
							recognizer->alignCrop(input, faces.row(i), face);
 | 
				
			||||||
		cv::Mat features;
 | 
							cv::Mat features;
 | 
				
			||||||
		recognizer->feature(face, features);
 | 
							recognizer->feature(face, features);
 | 
				
			||||||
		features = features.clone();
 | 
							features = features.clone();
 | 
				
			||||||
		for(size_t referanceIndex = 0; referanceIndex < referanceFeatures.size(); ++referanceIndex)
 | 
							for(size_t referanceIndex = 0; referanceIndex < referanceFeatures.size(); ++referanceIndex)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			double score = recognizer->match(referanceFeatures[referanceIndex], features, cv::FaceRecognizerSF::FR_COSINE);
 | 
								double score = recognizer->match(referanceFeatures[referanceIndex], features, cv::FaceRecognizerSF::FR_COSINE);
 | 
				
			||||||
			if(score > threshold && score > bestMatch.second)
 | 
								if(score > threshold && score > bestMatch.confidence)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				bestMatch = {referanceIndex, score};
 | 
									bestMatch.confidence = score;
 | 
				
			||||||
 | 
									bestMatch.person = referanceIndex;
 | 
				
			||||||
 | 
									bestMatch.rect = cv::Rect(faces.at<int>(i, 0), faces.at<int>(i, 1), faces.at<int>(i, 2), faces.at<int>(i, 3));
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,6 +11,13 @@ class FaceRecognizer
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct Detection
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							int person;
 | 
				
			||||||
 | 
							float confidence;
 | 
				
			||||||
 | 
							cv::Rect rect;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	class LoadException : public std::exception
 | 
						class LoadException : public std::exception
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
	private:
 | 
						private:
 | 
				
			||||||
| 
						 | 
					@ -33,7 +40,7 @@ private:
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
	FaceRecognizer(std::filesystem::path recognizerPath = "", const std::filesystem::path& detectorPath = "", const std::vector<cv::Mat>& referances = std::vector<cv::Mat>());
 | 
						FaceRecognizer(std::filesystem::path recognizerPath = "", const std::filesystem::path& detectorPath = "", const std::vector<cv::Mat>& referances = std::vector<cv::Mat>());
 | 
				
			||||||
	cv::Mat detectFaces(const cv::Mat& input);
 | 
						cv::Mat detectFaces(const cv::Mat& input);
 | 
				
			||||||
	std::pair<int, double> isMatch(const cv::Mat& input, bool alone = false);
 | 
						Detection isMatch(const cv::Mat& input, bool alone = false);
 | 
				
			||||||
	bool addReferances(const std::vector<cv::Mat>& referances);
 | 
						bool addReferances(const std::vector<cv::Mat>& referances);
 | 
				
			||||||
	void setThreshold(double threashold);
 | 
						void setThreshold(double threashold);
 | 
				
			||||||
	double getThreshold();
 | 
						double getThreshold();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -243,12 +243,12 @@ static void reduceSize(cv::Mat& image, const cv::Size& targetSize)
 | 
				
			||||||
		if(image.cols > image.rows)
 | 
							if(image.cols > image.rows)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			double ratio = static_cast<double>(longTargetSize)/image.cols;
 | 
								double ratio = static_cast<double>(longTargetSize)/image.cols;
 | 
				
			||||||
			cv::resize(image, image, {longTargetSize, static_cast<int>(image.rows*ratio)}, 0, 0, cv::INTER_CUBIC);
 | 
								cv::resize(image, image, {longTargetSize, static_cast<int>(image.rows*ratio)}, 0, 0, ratio < 1 ? cv::INTER_AREA : cv::INTER_CUBIC);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			double ratio = static_cast<double>(longTargetSize)/image.rows;
 | 
								double ratio = static_cast<double>(longTargetSize)/image.rows;
 | 
				
			||||||
			cv::resize(image, image, {static_cast<int>(image.cols*ratio), longTargetSize}, 0, 0, cv::INTER_CUBIC);
 | 
								cv::resize(image, image, {static_cast<int>(image.cols*ratio), longTargetSize}, 0, 0, ratio < 1 ? cv::INTER_AREA : cv::INTER_CUBIC);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -276,12 +276,13 @@ void pipeline(const std::filesystem::path& path, const Config& config, Yolo& yol
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			cv::Mat person = image(detection.box);
 | 
								cv::Mat person = image(detection.box);
 | 
				
			||||||
			reconizerMutex.lock();
 | 
								reconizerMutex.lock();
 | 
				
			||||||
			std::pair<int, double> match = recognizer->isMatch(person);
 | 
								FaceRecognizer::Detection match = recognizer->isMatch(person);
 | 
				
			||||||
			reconizerMutex.unlock();
 | 
								reconizerMutex.unlock();
 | 
				
			||||||
			if(match.first >= 0)
 | 
								if(match.person >= 0)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				detection.priority += 10;
 | 
									detection.priority += 10;
 | 
				
			||||||
				hasmatch = true;
 | 
									hasmatch = true;
 | 
				
			||||||
 | 
									detections.push_back({0, "Face", match.confidence, 20, {255, 0, 0}, match.rect});
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		Log(Log::DEBUG)<<detection.class_id<<": "<<detection.className<<" at "<<detection.box<<" with prio "<<detection.priority<<(hasmatch ? " has match" : "");
 | 
							Log(Log::DEBUG)<<detection.class_id<<": "<<detection.className<<" at "<<detection.box<<" with prio "<<detection.priority<<(hasmatch ? " has match" : "");
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue