File indexing completed on 2025-03-09 03:55:01

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam
0004  *
0005  * Date        : 2010-06-16
0006  * Description : Training functions of recognition wrapper
0007  *
0008  * SPDX-FileCopyrightText:      2010 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
0009  * SPDX-FileCopyrightText:      2010 by Aditya Bhatt <adityabhatt1991 at gmail dot com>
0010  * SPDX-FileCopyrightText: 2010-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0011  * SPDX-FileCopyrightText:      2019 by Thanh Trung Dinh <dinhthanhtrung1996 at gmail dot com>
0012  * SPDX-FileCopyrightText:      2020 by Nghia Duong <minhnghiaduong997 at gmail dot com>
0013  *
0014  * SPDX-License-Identifier: GPL-2.0-or-later
0015  *
0016  * ============================================================ */
0017 
0018 #include "facialrecognition_wrapper_p.h"
0019 
0020 namespace Digikam
0021 {
0022 
0023 void FacialRecognitionWrapper::Private::trainIdentityBatch(const QList<Identity>&      identitiesToBeTrained,
0024                                                            TrainingDataProvider* const data,
0025                                                            const QString&              trainingContext)
0026 {
0027     Q_FOREACH (const Identity& identity, identitiesToBeTrained)
0028     {
0029         ImageListProvider* const imageList = data->newImages(identity);
0030         QList<QImage*> images              = imageList->images();
0031 
0032         qCDebug(DIGIKAM_FACESENGINE_LOG) << "Training" << images.size() << "images for identity" << identity.id();
0033 
0034         try
0035         {
0036             recognizer->train(images, identity.id(), trainingContext);
0037         }
0038         catch (cv::Exception& e)
0039         {
0040             qCCritical(DIGIKAM_FACESENGINE_LOG) << "cv::Exception training Recognizer:" << e.what();
0041         }
0042         catch (...)
0043         {
0044             qCCritical(DIGIKAM_FACESENGINE_LOG) << "Default exception from OpenCV";
0045         }
0046     }
0047 }
0048 
0049 void FacialRecognitionWrapper::Private::clear(const QList<int>& idsToClear, const QString& trainingContext)
0050 {
0051     recognizer->clearTraining(idsToClear, trainingContext);
0052 
0053     delete recognizer;
0054 
0055     recognizer = new OpenCVDNNFaceRecognizer(OpenCVDNNFaceRecognizer::Tree);
0056 }
0057 
0058 // -------------------------------------------------------------------------------------
0059 
0060 void FacialRecognitionWrapper::train(const QList<Identity>& identitiesToBeTrained,
0061                                      TrainingDataProvider* const data,
0062                                      const QString& trainingContext)
0063 {
0064     if (!d || !d->dbAvailable)
0065     {
0066         return;
0067     }
0068 
0069     QMutexLocker lock(&d->mutex);
0070 
0071     d->trainIdentityBatch(identitiesToBeTrained, data, trainingContext);
0072 }
0073 
0074 void FacialRecognitionWrapper::train(const Identity& identityToBeTrained,
0075                                      TrainingDataProvider* const data,
0076                                      const QString& trainingContext)
0077 {
0078     train((QList<Identity>() << identityToBeTrained), data, trainingContext);
0079 }
0080 
0081 void FacialRecognitionWrapper::train(const Identity& identityToBeTrained,
0082                                      QImage* image,
0083                                      const QString& trainingContext)
0084 {
0085     RecognitionTrainingProvider* const data = new RecognitionTrainingProvider(identityToBeTrained,
0086                                                                               QList<QImage*>() << image);
0087     train(identityToBeTrained, data, trainingContext);
0088     delete data;
0089 }
0090 
0091 void FacialRecognitionWrapper::train(const Identity& identityToBeTrained,
0092                                      const QList<QImage*>& images,
0093                                      const QString& trainingContext)
0094 {
0095     RecognitionTrainingProvider* const data = new RecognitionTrainingProvider(identityToBeTrained, images);
0096     train(identityToBeTrained, data, trainingContext);
0097     delete data;
0098 }
0099 
0100 // -------------------------------------------------------------------------------------
0101 
0102 void FacialRecognitionWrapper::clearAllTraining(const QString& trainingContext)
0103 {
0104     if (!d || !d->dbAvailable)
0105     {
0106         return;
0107     }
0108 
0109     QMutexLocker lock(&d->mutex);
0110 
0111     d->identityCache.clear();
0112     FaceDbAccess().db()->clearIdentities();
0113 
0114     d->clear(QList<int>(), trainingContext);
0115 }
0116 
0117 void FacialRecognitionWrapper::clearTraining(const QList<Identity>& identitiesToClean,
0118                                              const QString& trainingContext)
0119 {
0120     if (!d || !d->dbAvailable || identitiesToClean.isEmpty())
0121     {
0122         return;
0123     }
0124 
0125     QMutexLocker lock(&d->mutex);
0126     QList<int>   ids;
0127 
0128     Q_FOREACH (const Identity& id, identitiesToClean)
0129     {
0130         ids << id.id();
0131     }
0132 
0133     d->clear(ids, trainingContext);
0134 }
0135 
0136 } // namespace Digikam