Merge pull request #20957 from sturkmen72:update-documentation
Update documentation * Update DNN-based Face Detection And Recognition tutorial * samples(dnn/face): update face_detect.cpp * final changes Co-authored-by: Alexander Alekhin <alexander.a.alekhin@gmail.com>pull/21165/head
parent
b594ed99b8
commit
a97f21ba4e
5 changed files with 333 additions and 275 deletions
@ -1,103 +0,0 @@ |
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#include "opencv2/dnn.hpp" |
||||
#include "opencv2/imgproc.hpp" |
||||
#include "opencv2/highgui.hpp" |
||||
|
||||
#include <iostream> |
||||
|
||||
#include "opencv2/objdetect.hpp" |
||||
|
||||
|
||||
using namespace cv; |
||||
using namespace std; |
||||
|
||||
|
||||
int main(int argc, char ** argv) |
||||
{ |
||||
if (argc != 5) |
||||
{ |
||||
std::cerr << "Usage " << argv[0] << ": " |
||||
<< "<det_onnx_path> " |
||||
<< "<reg_onnx_path> " |
||||
<< "<image1>" |
||||
<< "<image2>\n"; |
||||
return -1; |
||||
} |
||||
|
||||
String det_onnx_path = argv[1]; |
||||
String reg_onnx_path = argv[2]; |
||||
String image1_path = argv[3]; |
||||
String image2_path = argv[4]; |
||||
std::cout<<image1_path<<" "<<image2_path<<std::endl; |
||||
Mat image1 = imread(image1_path); |
||||
Mat image2 = imread(image2_path); |
||||
|
||||
float score_thresh = 0.9f; |
||||
float nms_thresh = 0.3f; |
||||
double cosine_similar_thresh = 0.363; |
||||
double l2norm_similar_thresh = 1.128; |
||||
int top_k = 5000; |
||||
|
||||
// Initialize FaceDetector
|
||||
Ptr<FaceDetectorYN> faceDetector; |
||||
|
||||
faceDetector = FaceDetectorYN::create(det_onnx_path, "", image1.size(), score_thresh, nms_thresh, top_k); |
||||
Mat faces_1; |
||||
faceDetector->detect(image1, faces_1); |
||||
if (faces_1.rows < 1) |
||||
{ |
||||
std::cerr << "Cannot find a face in " << image1_path << "\n"; |
||||
return -1; |
||||
} |
||||
|
||||
faceDetector = FaceDetectorYN::create(det_onnx_path, "", image2.size(), score_thresh, nms_thresh, top_k); |
||||
Mat faces_2; |
||||
faceDetector->detect(image2, faces_2); |
||||
if (faces_2.rows < 1) |
||||
{ |
||||
std::cerr << "Cannot find a face in " << image2_path << "\n"; |
||||
return -1; |
||||
} |
||||
|
||||
// Initialize FaceRecognizerSF
|
||||
Ptr<FaceRecognizerSF> faceRecognizer = FaceRecognizerSF::create(reg_onnx_path, ""); |
||||
|
||||
|
||||
Mat aligned_face1, aligned_face2; |
||||
faceRecognizer->alignCrop(image1, faces_1.row(0), aligned_face1); |
||||
faceRecognizer->alignCrop(image2, faces_2.row(0), aligned_face2); |
||||
|
||||
Mat feature1, feature2; |
||||
faceRecognizer->feature(aligned_face1, feature1); |
||||
feature1 = feature1.clone(); |
||||
faceRecognizer->feature(aligned_face2, feature2); |
||||
feature2 = feature2.clone(); |
||||
|
||||
double cos_score = faceRecognizer->match(feature1, feature2, FaceRecognizerSF::DisType::FR_COSINE); |
||||
double L2_score = faceRecognizer->match(feature1, feature2, FaceRecognizerSF::DisType::FR_NORM_L2); |
||||
|
||||
if(cos_score >= cosine_similar_thresh) |
||||
{ |
||||
std::cout << "They have the same identity;"; |
||||
} |
||||
else |
||||
{ |
||||
std::cout << "They have different identities;"; |
||||
} |
||||
std::cout << " Cosine Similarity: " << cos_score << ", threshold: " << cosine_similar_thresh << ". (higher value means higher similarity, max 1.0)\n"; |
||||
|
||||
if(L2_score <= l2norm_similar_thresh) |
||||
{ |
||||
std::cout << "They have the same identity;"; |
||||
} |
||||
else |
||||
{ |
||||
std::cout << "They have different identities."; |
||||
} |
||||
std::cout << " NormL2 Distance: " << L2_score << ", threshold: " << l2norm_similar_thresh << ". (lower value means higher similarity, min 0.0)\n"; |
||||
|
||||
return 0; |
||||
} |
@ -1,57 +0,0 @@ |
||||
import argparse |
||||
|
||||
import numpy as np |
||||
import cv2 as cv |
||||
|
||||
parser = argparse.ArgumentParser() |
||||
parser.add_argument('--input1', '-i1', type=str, help='Path to the input image1.') |
||||
parser.add_argument('--input2', '-i2', type=str, help='Path to the input image2.') |
||||
parser.add_argument('--face_detection_model', '-fd', type=str, help='Path to the face detection model. Download the model at https://github.com/ShiqiYu/libfacedetection.train/tree/master/tasks/task1/onnx.') |
||||
parser.add_argument('--face_recognition_model', '-fr', type=str, help='Path to the face recognition model. Download the model at https://drive.google.com/file/d/1ClK9WiB492c5OZFKveF3XiHCejoOxINW/view.') |
||||
args = parser.parse_args() |
||||
|
||||
# Read the input image |
||||
img1 = cv.imread(args.input1) |
||||
img2 = cv.imread(args.input2) |
||||
|
||||
# Instantiate face detector and recognizer |
||||
detector = cv.FaceDetectorYN.create( |
||||
args.face_detection_model, |
||||
"", |
||||
(img1.shape[1], img1.shape[0]) |
||||
) |
||||
recognizer = cv.FaceRecognizerSF.create( |
||||
args.face_recognition_model, |
||||
"" |
||||
) |
||||
|
||||
# Detect face |
||||
detector.setInputSize((img1.shape[1], img1.shape[0])) |
||||
face1 = detector.detect(img1) |
||||
detector.setInputSize((img2.shape[1], img2.shape[0])) |
||||
face2 = detector.detect(img2) |
||||
assert face1[1].shape[0] > 0, 'Cannot find a face in {}'.format(args.input1) |
||||
assert face2[1].shape[0] > 0, 'Cannot find a face in {}'.format(args.input2) |
||||
|
||||
# Align faces |
||||
face1_align = recognizer.alignCrop(img1, face1[1][0]) |
||||
face2_align = recognizer.alignCrop(img2, face2[1][0]) |
||||
|
||||
# Extract features |
||||
face1_feature = recognizer.feature(face1_align) |
||||
face2_feature = recognizer.feature(face2_align) |
||||
|
||||
# Calculate distance (0: cosine, 1: L2) |
||||
cosine_similarity_threshold = 0.363 |
||||
cosine_score = recognizer.match(face1_feature, face2_feature, 0) |
||||
msg = 'different identities' |
||||
if cosine_score >= cosine_similarity_threshold: |
||||
msg = 'the same identity' |
||||
print('They have {}. Cosine Similarity: {}, threshold: {} (higher value means higher similarity, max 1.0).'.format(msg, cosine_score, cosine_similarity_threshold)) |
||||
|
||||
l2_similarity_threshold = 1.128 |
||||
l2_score = recognizer.match(face1_feature, face2_feature, 1) |
||||
msg = 'different identities' |
||||
if l2_score <= l2_similarity_threshold: |
||||
msg = 'the same identity' |
||||
print('They have {}. NormL2 Distance: {}, threshold: {} (lower value means higher similarity, min 0.0).'.format(msg, l2_score, l2_similarity_threshold)) |
Loading…
Reference in new issue