File indexing completed on 2025-01-19 03:57:56
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2010-09-03 0007 * Description : Integrated, multithread face detection / recognition 0008 * 0009 * SPDX-FileCopyrightText: 2010-2011 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> 0010 * SPDX-FileCopyrightText: 2012-2024 by Gilles Caulier <caulier dot gilles at gmail dot com> 0011 * 0012 * SPDX-License-Identifier: GPL-2.0-or-later 0013 * 0014 * ============================================================ */ 0015 0016 #ifndef DIGIKAM_FACE_PIPELINE_H 0017 #define DIGIKAM_FACE_PIPELINE_H 0018 0019 // Local includes 0020 0021 #include "facepipelinepackage.h" 0022 0023 namespace Digikam 0024 { 0025 0026 class FacePipeline : public QObject 0027 { 0028 Q_OBJECT 0029 0030 public: 0031 0032 enum FilterMode 0033 { 0034 /// Will read any given image 0035 ScanAll, 0036 0037 /// Will skip any image that is already marked as scanned 0038 SkipAlreadyScanned, 0039 0040 /// Will read unconfirmed faces for recognition 0041 ReadUnconfirmedFaces, 0042 0043 /// Will read faces marked for training 0044 ReadFacesForTraining, 0045 0046 /// Will read faces which are confirmed 0047 ReadConfirmedFaces 0048 }; 0049 0050 enum WriteMode 0051 { 0052 /// Write results. Merge with existing entries. 0053 NormalWrite, 0054 0055 /// Add new results. Previous all results will be cleared. 0056 OverwriteAllFaces, 0057 0058 /// Add new results. Previous unconfirmed results will be cleared. 0059 OverwriteUnconfirmed 0060 0061 }; 0062 0063 public: 0064 0065 explicit FacePipeline(); 0066 ~FacePipeline() override; 0067 0068 /** 0069 * You can plug these four different steps in the working pipeline. 0070 * 1) Call any of the four plug...() methods. See below for supported combinations. 0071 * 2) Call construct() to set up the pipeline. 0072 * 0073 * - Database filter: Prepares database records and/or filters out items. 0074 * See FilterMode for specification. 0075 * - Preview loader: If no preview loader is plugged, you must provide 0076 * a DImg for face detection and recognition 0077 * - Face Detector: If no recognizer is plugged, all detected face are marked 0078 * as the unknown person 0079 * - Face Recognizer: If no detector is plugged, only already scanned faces 0080 * marked as unknown will be processed. 0081 * They are implicitly read from the database. 0082 * - DatabaseWriter: Writes the detection and recognition results to the database. 0083 * The trainer works on a completely different storage 0084 * and is not affected by the database writer. 0085 * - DatabaseEditor: Can confirm or reject faces 0086 * 0087 * PlugParallel: You can call this instead of the simple plugging method. 0088 * Depending on the number of processor cores of the machine and the memory cost, 0089 * more than one element may be plugged and process parallelly for this part of the pipeline. 0090 * 0091 * Supported combinations: 0092 * (Database Filter ->) (Preview Loader ->) Detector -> Recognizer (-> DatabaseWriter) 0093 * (Database Filter ->) (Preview Loader ->) Detector (-> DatabaseWriter) 0094 * (Database Filter ->) (Preview Loader ->) Recognizer (-> DatabaseWriter) 0095 * DatabaseEditor 0096 * Trainer 0097 * DatabaseEditor -> Trainer 0098 */ 0099 void plugDatabaseFilter(FilterMode mode); 0100 void plugRerecognizingDatabaseFilter(); 0101 void plugRetrainingDatabaseFilter(); 0102 void plugFacePreviewLoader(); 0103 void plugFaceDetector(); 0104 void plugParallelFaceDetectors(); 0105 void plugFaceRecognizer(); 0106 void plugDatabaseWriter(WriteMode mode); 0107 void plugDatabaseEditor(); 0108 void plugTrainer(); 0109 void plugDetectionBenchmarker(); 0110 void plugRecognitionBenchmarker(); 0111 void construct(); 0112 0113 /** 0114 * Cancels all processing 0115 */ 0116 void cancel(); 0117 0118 /** 0119 * Cancels and waits for the pipeline to finish 0120 */ 0121 void shutDown(); 0122 0123 bool hasFinished() const; 0124 QString benchmarkResult() const; 0125 0126 /** 0127 * Set the priority of the threads used by this pipeline. 0128 * The default setting is QThread::LowPriority. 0129 */ 0130 void setPriority(QThread::Priority priority); 0131 QThread::Priority priority() const; 0132 0133 public Q_SLOTS: 0134 0135 /** 0136 * Processes the given image info. If a filter is installed, 0137 * returns false if the info is skipped, or true if it is processed. 0138 * If no preview loader is plugged, you must provide a DImg for detection or recognition. 0139 * Any of the signals below will only be emitted if true is returned. 0140 */ 0141 bool process(const ItemInfo& info); 0142 bool process(const ItemInfo& info, const DImg& image); 0143 0144 /** 0145 * Confirm the face. Pass the original face, and additionally tag id or region 0146 * if they changed. Returns the confirmed face entry immediately purely for convenience, 0147 * it is not yet in the database (connect to signal processed() to react when the processing finished). 0148 * If a trainer is plugged, the face will be trained. 0149 */ 0150 FaceTagsIface confirm(const ItemInfo& info, 0151 const FaceTagsIface& face, 0152 int assignedTagId = 0, 0153 const TagRegion& assignedRegion = TagRegion()); 0154 FaceTagsIface confirm(const ItemInfo& info, 0155 const FaceTagsIface& face, 0156 const DImg& image, 0157 int assignedTagId = 0, 0158 const TagRegion& assignedRegion = TagRegion()); 0159 /** 0160 * Train the given faces. 0161 */ 0162 void train(const ItemInfo& info, 0163 const QList<FaceTagsIface>& faces); 0164 void train(const ItemInfo& info, 0165 const QList<FaceTagsIface>& faces, 0166 const DImg& image); 0167 0168 /** 0169 * Remove the given face. 0170 */ 0171 void remove(const ItemInfo& info, 0172 const FaceTagsIface& face); 0173 0174 /** 0175 * Add an entry manually. 0176 */ 0177 FaceTagsIface addManually(const ItemInfo& info, 0178 const DImg& image, 0179 const TagRegion& assignedRegion); 0180 0181 /** 0182 * Change the given face's region to newRegion. 0183 * Does not care for training atm. 0184 */ 0185 FaceTagsIface editRegion(const ItemInfo& info, 0186 const DImg& image, 0187 const FaceTagsIface& databaseFace, 0188 const TagRegion& newRegion); 0189 0190 /** 0191 * Changes the given face's tagId to newTagId. 0192 * Used to Reject Facial Recognition suggestions, since 0193 * the tag needs to be converted from Unconfirmed to Unknown. 0194 */ 0195 FaceTagsIface editTag(const ItemInfo& info, 0196 const FaceTagsIface& databaseFace, 0197 int newTagId); 0198 0199 /** 0200 * Batch processing. If a filter is installed, the skipped() signal 0201 * will inform about skipped infos. Filtering is done in a thread, returns immediately. 0202 * Some of the signals below will be emitted in any case. 0203 */ 0204 void process(const QList<ItemInfo>& infos); 0205 0206 void setAccuracyAndModel(double accuracy, bool yolo); 0207 0208 Q_SIGNALS: 0209 0210 /// Emitted when processing is scheduled. 0211 void scheduled(); 0212 0213 /// Emitted when processing has started 0214 void started(const QString& message); 0215 0216 /// Emitted when one package begins processing 0217 void processing(const FacePipelinePackage& package); 0218 0219 /// Emitted when one package has finished processing 0220 void processed(const FacePipelinePackage& package); 0221 void progressValueChanged(float progress); 0222 0223 /// Emitted when the last package has finished processing 0224 void finished(); 0225 0226 /// Emitted when one or several packages were skipped, usually because they have already been scanned. 0227 void skipped(const QList<ItemInfo>& skippedInfos); 0228 0229 public: 0230 0231 class Private; 0232 0233 private: 0234 0235 // Disable 0236 explicit FacePipeline(QObject*) = delete; 0237 FacePipeline(const FacePipeline&) = delete; 0238 FacePipeline& operator=(const FacePipeline&) = delete; 0239 0240 private: 0241 0242 Private* const d; 0243 friend class Private; 0244 }; 0245 0246 } // namespace Digikam 0247 0248 #endif // DIGIKAM_FACE_PIPELINE_H