diff --git a/doc/tutorials/dnn/dnn_face/dnn_face.markdown b/doc/tutorials/dnn/dnn_face/dnn_face.markdown index d85eb3c2ee..e55f0d1bc2 100644 --- a/doc/tutorials/dnn/dnn_face/dnn_face.markdown +++ b/doc/tutorials/dnn/dnn_face/dnn_face.markdown @@ -8,19 +8,19 @@ | | | | -: | :- | | Original Author | Chengrui Wang, Yuantao Feng | -| Compatibility | OpenCV >= 4.5.1 | +| Compatibility | OpenCV >= 4.5.4 | ## Introduction -In this section, we introduce the DNN-based module for face detection and face recognition. Models can be obtained in [Models](#Models). The usage of `FaceDetectorYN` and `FaceRecognizerSF` are presented in [Usage](#Usage). +In this section, we introduce cv::FaceDetectorYN class for face detection and cv::FaceRecognizerSF class for face recognition. ## Models There are two models (ONNX format) pre-trained and required for this module: -- [Face Detection](https://github.com/ShiqiYu/libfacedetection.train/tree/master/tasks/task1/onnx): - - Size: 337KB +- [Face Detection](https://github.com/opencv/opencv_zoo/tree/master/models/face_detection_yunet): + - Size: 338KB - Results on WIDER Face Val set: 0.830(easy), 0.824(medium), 0.708(hard) -- [Face Recognition](https://drive.google.com/file/d/1ClK9WiB492c5OZFKveF3XiHCejoOxINW/view?usp=sharing) +- [Face Recognition](https://github.com/opencv/opencv_zoo/tree/master/models/face_recognition_sface) - Size: 36.9MB - Results: @@ -32,9 +32,7 @@ There are two models (ONNX format) pre-trained and required for this module: | AgeDB-30 | 94.90% | 1.202 | 0.277 | | CFP-FP | 94.80% | 1.253 | 0.212 | -## Usage - -### DNNFaceDetector +## Code @add_toggle_cpp - **Downloadable code**: Click diff --git a/modules/objdetect/include/opencv2/objdetect.hpp b/modules/objdetect/include/opencv2/objdetect.hpp index 3592255791..5ba7cf7bd2 100644 --- a/modules/objdetect/include/opencv2/objdetect.hpp +++ b/modules/objdetect/include/opencv2/objdetect.hpp @@ -49,8 +49,8 @@ /** @defgroup objdetect Object Detection -Haar Feature-based Cascade Classifier for Object Detection ----------------------------------------------------------- +@{ + @defgroup objdetect_cascade_classifier Cascade Classifier for Object Detection The object detector described below has been initially proposed by Paul Viola @cite Viola01 and improved by Rainer Lienhart @cite Lienhart02 . @@ -90,8 +90,7 @@ middle) and the sum of the image pixels under the black stripe multiplied by 3 i compensate for the differences in the size of areas. The sums of pixel values over a rectangular regions are calculated rapidly using integral images (see below and the integral description). -To see the object detector at work, have a look at the facedetect demo: - +Check @ref tutorial_cascade_classifier "the corresponding tutorial" for more details. The following reference is for the detection part only. There is a separate application called opencv_traincascade that can train a cascade of boosted classifiers from a set of samples. @@ -99,10 +98,13 @@ opencv_traincascade that can train a cascade of boosted classifiers from a set o @note In the new C++ interface it is also possible to use LBP (local binary pattern) features in addition to Haar-like features. .. [Viola01] Paul Viola and Michael J. Jones. Rapid Object Detection using a Boosted Cascade of Simple Features. IEEE CVPR, 2001. The paper is available online at - + -@{ - @defgroup objdetect_c C API + @defgroup objdetect_hog HOG (Histogram of Oriented Gradients) descriptor and object detector + @defgroup objdetect_qrcode QRCode detection and encoding + @defgroup objdetect_dnn_face DNN-based face detection and recognition +Check @ref tutorial_dnn_face "the corresponding tutorial" for more details. + @defgroup objdetect_common Common functions and classes @} */ @@ -111,13 +113,15 @@ typedef struct CvHaarClassifierCascade CvHaarClassifierCascade; namespace cv { -//! @addtogroup objdetect +//! @addtogroup objdetect_common //! @{ ///////////////////////////// Object Detection //////////////////////////// -//! class for grouping object candidates, detected by Cascade Classifier, HOG etc. -//! instance of the class is to be passed to cv::partition (see cxoperations.hpp) +/** @brief This class is used for grouping object candidates detected by Cascade Classifier, HOG etc. + +instance of the class is to be passed to cv::partition + */ class CV_EXPORTS SimilarRects { public: @@ -162,6 +166,10 @@ CV_EXPORTS void groupRectangles(std::vector& rectList, std::vector& CV_EXPORTS void groupRectangles_meanshift(std::vector& rectList, std::vector& foundWeights, std::vector& foundScales, double detectThreshold = 0.0, Size winDetSize = Size(64, 128)); +//! @} + +//! @addtogroup objdetect_cascade_classifier +//! @{ template<> struct DefaultDeleter{ CV_EXPORTS void operator ()(CvHaarClassifierCascade* obj) const; }; @@ -243,7 +251,7 @@ public: CV_WRAP bool load( const String& filename ); /** @brief Reads a classifier from a FileStorage node. - @note The file may contain a new cascade classifier (trained traincascade application) only. + @note The file may contain a new cascade classifier (trained by the traincascade application) only. */ CV_WRAP bool read( const FileNode& node ); @@ -260,12 +268,6 @@ public: cvHaarDetectObjects. It is not used for a new cascade. @param minSize Minimum possible object size. Objects smaller than that are ignored. @param maxSize Maximum possible object size. Objects larger than that are ignored. If `maxSize == minSize` model is evaluated on single scale. - - The function is parallelized with the TBB library. - - @note - - (Python) A face detection example using cascade classifiers can be found at - opencv_source_code/samples/python/facedetect.py */ CV_WRAP void detectMultiScale( InputArray image, CV_OUT std::vector& objects, @@ -338,7 +340,10 @@ public: }; CV_EXPORTS Ptr createFaceDetectionMaskGenerator(); +//! @} +//! @addtogroup objdetect_hog +//! @{ //////////////// HOG (Histogram-of-Oriented-Gradients) Descriptor and Object Detector ////////////// //! struct for detection region of interest (ROI) @@ -666,6 +671,10 @@ public: */ void groupRectangles(std::vector& rectList, std::vector& weights, int groupThreshold, double eps) const; }; +//! @} + +//! @addtogroup objdetect_qrcode +//! @{ class CV_EXPORTS_W QRCodeEncoder { protected: @@ -827,7 +836,7 @@ protected: Ptr p; }; -//! @} objdetect +//! @} } #include "opencv2/objdetect/detection_based_tracker.hpp" diff --git a/modules/objdetect/include/opencv2/objdetect/detection_based_tracker.hpp b/modules/objdetect/include/opencv2/objdetect/detection_based_tracker.hpp index 18cde13eab..fb96c668a5 100644 --- a/modules/objdetect/include/opencv2/objdetect/detection_based_tracker.hpp +++ b/modules/objdetect/include/opencv2/objdetect/detection_based_tracker.hpp @@ -51,7 +51,7 @@ namespace cv { -//! @addtogroup objdetect +//! @addtogroup objdetect_cascade_classifier //! @{ class CV_EXPORTS DetectionBasedTracker @@ -215,7 +215,7 @@ class CV_EXPORTS DetectionBasedTracker void detectInRegion(const cv::Mat& img, const cv::Rect& r, std::vector& detectedObjectsInRegions); }; -//! @} objdetect +//! @} } //end of cv namespace diff --git a/modules/objdetect/include/opencv2/objdetect/face.hpp b/modules/objdetect/include/opencv2/objdetect/face.hpp index f2429c5f31..1b3681c652 100644 --- a/modules/objdetect/include/opencv2/objdetect/face.hpp +++ b/modules/objdetect/include/opencv2/objdetect/face.hpp @@ -7,13 +7,15 @@ #include -/** @defgroup dnn_face DNN-based face detection and recognition - */ - namespace cv { -/** @brief DNN-based face detector, model download link: https://github.com/ShiqiYu/libfacedetection.train/tree/master/tasks/task1/onnx. +//! @addtogroup objdetect_dnn_face +//! @{ + +/** @brief DNN-based face detector + +model download link: https://github.com/opencv/opencv_zoo/tree/master/models/face_detection_yunet */ class CV_EXPORTS_W FaceDetectorYN { @@ -80,7 +82,9 @@ public: int target_id = 0); }; -/** @brief DNN-based face recognizer, model download link: https://drive.google.com/file/d/1ClK9WiB492c5OZFKveF3XiHCejoOxINW/view. +/** @brief DNN-based face recognizer + +model download link: https://github.com/opencv/opencv_zoo/tree/master/models/face_recognition_sface */ class CV_EXPORTS_W FaceRecognizerSF { @@ -105,11 +109,11 @@ public: CV_WRAP virtual void feature(InputArray aligned_img, OutputArray face_feature) = 0; /** @brief Calculating the distance between two face features - * @param _face_feature1 the first input feature - * @param _face_feature2 the second input feature of the same size and the same type as _face_feature1 + * @param face_feature1 the first input feature + * @param face_feature2 the second input feature of the same size and the same type as face_feature1 * @param dis_type defining the similarity with optional values "FR_OSINE" or "FR_NORM_L2" */ - CV_WRAP virtual double match(InputArray _face_feature1, InputArray _face_feature2, int dis_type = FaceRecognizerSF::FR_COSINE) const = 0; + CV_WRAP virtual double match(InputArray face_feature1, InputArray face_feature2, int dis_type = FaceRecognizerSF::FR_COSINE) const = 0; /** @brief Creates an instance of this class with given parameters * @param model the path of the onnx model used for face recognition @@ -120,6 +124,7 @@ public: CV_WRAP static Ptr create(const String& model, const String& config, int backend_id = 0, int target_id = 0); }; +//! @} } // namespace cv #endif diff --git a/samples/dnn/face_detect.cpp b/samples/dnn/face_detect.cpp index 161940cb4a..d1e6314969 100644 --- a/samples/dnn/face_detect.cpp +++ b/samples/dnn/face_detect.cpp @@ -44,8 +44,8 @@ int main(int argc, char** argv) "{image2 i2 | | Path to the input image2. When image1 and image2 parameters given then the program try to find a face on both images and runs face recognition algorithm}" "{video v | 0 | Path to the input video}" "{scale sc | 1.0 | Scale factor used to resize input video frames}" - "{fd_model fd | yunet.onnx | Path to the model. Download yunet.onnx in https://github.com/ShiqiYu/libfacedetection.train/tree/master/tasks/task1/onnx }" - "{fr_model fr | face_recognizer_fast.onnx | Path to the face recognition model. Download the model at https://drive.google.com/file/d/1ClK9WiB492c5OZFKveF3XiHCejoOxINW/view}" + "{fd_model fd | face_detection_yunet_2021dec.onnx| Path to the model. Download yunet.onnx in https://github.com/opencv/opencv_zoo/tree/master/models/face_detection_yunet}" + "{fr_model fr | face_recognition_sface_2021dec.onnx | Path to the face recognition model. Download the model at https://github.com/opencv/opencv_zoo/tree/master/models/face_recognition_sface}" "{score_threshold | 0.9 | Filter out faces of score < score_threshold}" "{nms_threshold | 0.3 | Suppress bounding boxes of iou >= nms_threshold}" "{top_k | 5000 | Keep top_k bounding boxes before NMS}" @@ -65,6 +65,7 @@ int main(int argc, char** argv) int topK = parser.get("top_k"); bool save = parser.get("save"); + float scale = parser.get("scale"); double cosine_similar_thresh = 0.363; double l2norm_similar_thresh = 1.128; @@ -87,6 +88,9 @@ int main(int argc, char** argv) return 2; } + int imageWidth = int(image1.cols * scale); + int imageHeight = int(image1.rows * scale); + resize(image1, image1, Size(imageWidth, imageHeight)); tm.start(); //! [inference] @@ -199,7 +203,6 @@ int main(int argc, char** argv) else { int frameWidth, frameHeight; - float scale = parser.get("scale"); VideoCapture capture; std::string video = parser.get("video"); if (video.size() == 1 && isdigit(video[0])) diff --git a/samples/dnn/face_detect.py b/samples/dnn/face_detect.py index 8900a7f7ad..9cf38b5d5f 100644 --- a/samples/dnn/face_detect.py +++ b/samples/dnn/face_detect.py @@ -16,8 +16,8 @@ parser.add_argument('--image1', '-i1', type=str, help='Path to the input image1. parser.add_argument('--image2', '-i2', type=str, help='Path to the input image2. When image1 and image2 parameters given then the program try to find a face on both images and runs face recognition algorithm.') parser.add_argument('--video', '-v', type=str, help='Path to the input video.') parser.add_argument('--scale', '-sc', type=float, default=1.0, help='Scale factor used to resize input video frames.') -parser.add_argument('--face_detection_model', '-fd', type=str, default='yunet.onnx', 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, default='face_recognizer_fast.onnx', help='Path to the face recognition model. Download the model at https://drive.google.com/file/d/1ClK9WiB492c5OZFKveF3XiHCejoOxINW/view.') +parser.add_argument('--face_detection_model', '-fd', type=str, default='face_detection_yunet_2021dec.onnx', help='Path to the face detection model. Download the model at https://github.com/opencv/opencv_zoo/tree/master/models/face_detection_yunet') +parser.add_argument('--face_recognition_model', '-fr', type=str, default='face_recognition_sface_2021dec.onnx', help='Path to the face recognition model. Download the model at https://github.com/opencv/opencv_zoo/tree/master/models/face_recognition_sface') parser.add_argument('--score_threshold', type=float, default=0.9, help='Filtering out faces of score < score_threshold.') parser.add_argument('--nms_threshold', type=float, default=0.3, help='Suppress bounding boxes of iou >= nms_threshold.') parser.add_argument('--top_k', type=int, default=5000, help='Keep top_k bounding boxes before NMS.') @@ -56,11 +56,15 @@ if __name__ == '__main__': # If input is an image if args.image1 is not None: img1 = cv.imread(cv.samples.findFile(args.image1)) + img1Width = int(img1.shape[1]*args.scale) + img1Height = int(img1.shape[0]*args.scale) + img1 = cv.resize(img1, (img1Width, img1Height)) tm.start() + ## [inference] # Set input size before inference - detector.setInputSize((img1.shape[1], img1.shape[0])) + detector.setInputSize((img1Width, img1Height)) faces1 = detector.detect(img1) ## [inference]