File indexing completed on 2025-01-19 03:57:55

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2010-08-08
0007  * Description : FacesEngine database interface allowing easy manipulation of face tags
0008  *
0009  * SPDX-FileCopyrightText: 2010-2011 by Aditya Bhatt <adityabhatt1991 at gmail dot com>
0010  * SPDX-FileCopyrightText: 2010-2011 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
0011  * SPDX-FileCopyrightText: 2012-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0012  *
0013  * SPDX-License-Identifier: GPL-2.0-or-later
0014  *
0015  * ============================================================ */
0016 
0017 #ifndef DIGIKAM_FACE_UTILS_H
0018 #define DIGIKAM_FACE_UTILS_H
0019 
0020 // Qt includes
0021 
0022 #include <QStringList>
0023 
0024 // Local includes
0025 
0026 #include "identity.h"
0027 #include "facialrecognition_wrapper.h"
0028 #include "iteminfo.h"
0029 #include "facetagseditor.h"
0030 #include "digikam_export.h"
0031 
0032 class QImage;
0033 
0034 namespace Digikam
0035 {
0036 
0037 class DImg;
0038 class ThumbnailLoadThread;
0039 class ThumbnailImageCatcher;
0040 
0041 class FaceUtils : public QObject,
0042                   public FaceTagsEditor
0043 {
0044     Q_OBJECT
0045 
0046 public:
0047 
0048     enum FaceRecognitionSteps
0049     {
0050         DetectFaceRegions,
0051         DetectAndRecognize
0052     };
0053 
0054 public:
0055 
0056     explicit FaceUtils(QObject* const parent = nullptr);
0057     ~FaceUtils()                                                                              override;
0058 
0059     // --- Face detection and recognition ---
0060 
0061     /**
0062      * The given face list is a result of automatic detection and possibly recognition.
0063      * The results are written to the database and merged with existing entries.
0064      * The returned list contains the faces written to the database and has the same size as the given list.
0065      * If a face was skipped (because of an existing entry), a null FaceTagsIface will be at this place.
0066      */
0067     QList<FaceTagsIface> writeUnconfirmedResults(qlonglong imageid,
0068                                                  const QList<QRectF>& detectedFaces,
0069                                                  const QList<Identity>& recognitionResults,
0070                                                  const QSize& fullSize);
0071 
0072     // --- Status flags ---
0073 
0074     /**
0075      * Tells if the image has been scanned for faces or not
0076      */
0077     bool                hasBeenScanned(const ItemInfo& info)                            const;
0078     bool                hasBeenScanned(qlonglong imageid)                               const;
0079 
0080     /**
0081      * Marks the image as scanned for faces.
0082      */
0083     void                markAsScanned(qlonglong imageid, bool hasBeenScanned = true)    const;
0084     void                markAsScanned(const ItemInfo& info, bool hasBeenScanned = true) const;
0085 
0086     // --- Utilities ---
0087 
0088     /**
0089      * This uses a thumbnail load thread to load the image detail.
0090      * If requested, the faces will be scaled to the given (fixed) size.
0091      */
0092 /*
0093     void                 fillImageInFaces(ThumbnailImageCatcher* const catcher,
0094                                           const QString& filePath,
0095                                           QList<Face>& faceList,
0096                                           const QSize& scaleSize = QSize())             const;
0097 */
0098 
0099     /**
0100      * Store the needed thumbnails for the given faces. This can be a huge optimization
0101      * when the has already been loaded anyway.
0102      */
0103     void                 storeThumbnails(ThumbnailLoadThread* const thread,
0104                                          const QString& filePath,
0105                                          const QList<FaceTagsIface>& databaseFaces,
0106                                          const DImg& image);
0107 
0108     /**
0109      * Conversion
0110      */
0111     QList<FaceTagsIface> toFaceTagsIfaces(qlonglong imageid,
0112                                          const QList<QRectF>& detectedFaces,
0113                                          const QList<Identity>& recognitionResults,
0114                                          const QSize& fullSize)                         const;
0115 
0116     /**
0117      * For display, it may be desirable to display a slightly larger region than the strict
0118      * face rectangle. This returns a pixel margin commonly used to increase the rectangle size
0119      * in all four directions.
0120      */
0121     static QRect         faceRectToDisplayRect(const QRect& rect);
0122 
0123     // TODO: investigate this method
0124     Identity identityForTag(int tagId, FacialRecognitionWrapper& recognizer)            const;
0125     int      tagForIdentity(const Identity& identity)                                   const;
0126 
0127 protected:
0128 
0129     // Reimplemented
0130     void addNormalTag(qlonglong imageId, int tagId)                                           override;
0131     void removeNormalTag(qlonglong imageId, int tagId)                                        override;
0132     void removeNormalTags(qlonglong imageId, const QList<int>& tagIds)                        override;
0133 
0134 private:
0135 
0136     // Disable
0137     FaceUtils(const FaceUtils&)            = delete;
0138     FaceUtils& operator=(const FaceUtils&) = delete;
0139 };
0140 
0141 } // Namespace Digikam
0142 
0143 #endif // DIGIKAM_FACE_UTILS_H