1 /* ============================================================
2  *
3  * This file is a part of digiKam project
4  * https://www.digikam.org
5  *
6  * Date        : 2010-08-08
7  * Description : FacesEngine database interface allowing easy manipulation of face tags
8  *
9  * Copyright (C) 2010-2011 by Aditya Bhatt <adityabhatt1991 at gmail dot com>
10  * Copyright (C) 2010-2011 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
11  * Copyright (C) 2012-2021 by Gilles Caulier <caulier dot gilles at gmail dot com>
12  *
13  * This program is free software; you can redistribute it
14  * and/or modify it under the terms of the GNU General
15  * Public License as published by the Free Software Foundation;
16  * either version 2, or (at your option)
17  * any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * ============================================================ */
25 
26 #ifndef DIGIKAM_FACE_UTILS_H
27 #define DIGIKAM_FACE_UTILS_H
28 
29 // Qt includes
30 
31 #include <QStringList>
32 
33 // Local includes
34 
35 #include "identity.h"
36 #include "facialrecognition_wrapper.h"
37 #include "iteminfo.h"
38 #include "facetagseditor.h"
39 #include "digikam_export.h"
40 
41 class QImage;
42 
43 namespace Digikam
44 {
45 
46 class DImg;
47 class ThumbnailLoadThread;
48 class ThumbnailImageCatcher;
49 
50 class FaceUtils : public QObject,
51                   public FaceTagsEditor
52 {
53     Q_OBJECT
54 
55 public:
56 
57     enum FaceRecognitionSteps
58     {
59         DetectFaceRegions,
60         DetectAndRecognize
61     };
62 
63 public:
64 
65     explicit FaceUtils(QObject* const parent = nullptr);
66     ~FaceUtils()                                                                              override;
67 
68     // --- Face detection and recognition ---
69 
70     /**
71      * The given face list is a result of automatic detection and possibly recognition.
72      * The results are written to the database and merged with existing entries.
73      * The returned list contains the faces written to the database and has the same size as the given list.
74      * If a face was skipped (because of an existing entry), a null FaceTagsIface will be at this place.
75      */
76     QList<FaceTagsIface> writeUnconfirmedResults(qlonglong imageid,
77                                                  const QList<QRectF>& detectedFaces,
78                                                  const QList<Identity>& recognitionResults,
79                                                  const QSize& fullSize);
80 
81     // --- Status flags ---
82 
83     /**
84      * Tells if the image has been scanned for faces or not
85      */
86     bool                hasBeenScanned(const ItemInfo& info)                            const;
87     bool                hasBeenScanned(qlonglong imageid)                               const;
88 
89     /**
90      * Marks the image as scanned for faces.
91      */
92     void                markAsScanned(qlonglong imageid, bool hasBeenScanned = true)    const;
93     void                markAsScanned(const ItemInfo& info, bool hasBeenScanned = true) const;
94 
95     // --- Utilities ---
96 
97     /**
98      * This uses a thumbnail load thread to load the image detail.
99      * If requested, the faces will be scaled to the given (fixed) size.
100      */
101 /*
102     void                fillImageInFaces(ThumbnailImageCatcher* const catcher,
103                                          const QString& filePath,
104                                          QList<Face>& faceList,
105                                          const QSize& scaleSize = QSize())              const;
106 */
107 
108     /**
109      * Store the needed thumbnails for the given faces. This can be a huge optimization
110      * when the has already been loaded anyway.
111      */
112     void                storeThumbnails(ThumbnailLoadThread* const thread,
113                                         const QString& filePath,
114                                         const QList<FaceTagsIface>& databaseFaces,
115                                         const DImg& image);
116 
117     /**
118      * Conversion
119      */
120     QList<FaceTagsIface> toFaceTagsIfaces(qlonglong imageid,
121                                          const QList<QRectF>& detectedFaces,
122                                          const QList<Identity>& recognitionResults,
123                                          const QSize& fullSize)                         const;
124 
125     /**
126      * Rotate face tags
127      */
128     QSize                rotateFaces(const ItemInfo& info, int newOrientation,
129                                                            int oldOrientation);
130 
131     /**
132      * For display, it may be desirable to display a slightly larger region than the strict
133      * face rectangle. This returns a pixel margin commonly used to increase the rectangle size
134      * in all four directions.
135      */
136     static int          faceRectDisplayMargin(const QRect& rect);
137 
138     // TODO: investigate this method
139     Identity identityForTag(int tagId, FacialRecognitionWrapper& recognizer)            const;
140     int      tagForIdentity(const Identity& identity)                                   const;
141 
142 protected:
143 
144     // Reimplemented
145     void addNormalTag(qlonglong imageid, int tagId)                                           override;
146     void removeNormalTag(qlonglong imageid, int tagId)                                        override;
147     void removeNormalTags(qlonglong imageid, const QList<int>& tagId)                         override;
148 
149 private:
150 
151     // Disable
152     FaceUtils(const FaceUtils&)            = delete;
153     FaceUtils& operator=(const FaceUtils&) = delete;
154 };
155 
156 } // Namespace Digikam
157 
158 #endif // DIGIKAM_FACE_UTILS_H
159