Add the option to focus on a spcific person
This commit is contained in:
@ -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" : "");
|
||||||
|
Reference in New Issue
Block a user