1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
/* ============================================================
 *
 * This file is a part of digiKam
 *
 * Date        : 02-02-2012
 * Description : Face database interface to train face recognizer.
 *
 * SPDX-FileCopyrightText: 2012-2013 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
 * SPDX-FileCopyrightText: 2010-2026 by Gilles Caulier <caulier dot gilles at gmail dot com>
 * SPDX-FileCopyrightText: 2019      by Thanh Trung Dinh <dinhthanhtrung1996 at gmail dot com>
 * SPDX-FileCopyrightText: 2020      by Nghia Duong <minhnghiaduong997 at gmail dot com>
 * SPDX-FileCopyrightText: 2024-2025 by Michael Miller <michael underscore miller at msn dot com>
 *
 * SPDX-License-Identifier: GPL-2.0-or-later
 *
 * ============================================================ */

#include "facedb_p.h"

namespace Digikam
{

int FaceDb::insertFaceVector(const cv::Mat& faceEmbedding,
                             const int label,
                             const QString& hash) const
{
    QVariantList bindingValues;

    bindingValues << label;
    bindingValues << hash;
    bindingValues << QByteArray::fromRawData(reinterpret_cast<const char*>(faceEmbedding.ptr<float>()), (sizeof(float) * 128));

    QSqlQuery query = d->db->execQuery(QLatin1String("INSERT INTO FaceMatrices (identity, removeHash, embedding) "
                                                     "VALUES (?,?,?);"),
                                              bindingValues);

    if (query.lastInsertId().isNull())
    {
        qCWarning(DIGIKAM_FACEDB_LOG) << "fail to insert face embedding, last query"
                                      << query.lastQuery()
                                      << "bound values" << query.boundValues()
                                      << query.lastError();
    }

    else
    {
        qCDebug(DIGIKAM_FACEDB_LOG) << "Commit face mat data "
                                    << query.lastInsertId().toInt()
                                    << " for identity " << label;
    }

    return query.lastInsertId().toInt();
}

bool FaceDb::removeFaceVector(const int nodeId) const
{
    d->db->execQuery(QLatin1String("DELETE FROM FaceMatrices WHERE id=?;"),
                     nodeId);
    qCDebug(DIGIKAM_FACEDB_LOG) << "Deleted nodeId " << nodeId << " from FaceMatricies";

    return true;
}

bool FaceDb::removeFaceVector(const QString& hash) const
{
    QSqlQuery query = d->db->execQuery(QLatin1String("DELETE FROM FaceMatrices WHERE removeHash=?;"), hash);

    qCDebug(DIGIKAM_FACEDB_LOG) << "Deleted hash " << hash << " from FaceMatricies";

    // TODO: Check query result.
    Q_UNUSED(query);

    return true;
}

cv::Ptr<cv::ml::TrainData> FaceDb::trainData() const
{
    cv::Mat feature, label;
    QSqlQuery query = d->db->execQuery(QLatin1String("SELECT identity, embedding "
                                                     "FROM FaceMatrices;"));

    while (query.next())
    {
        label.push_back(query.value(0).toInt());
        feature.push_back(cv::Mat(1, 128, CV_32F, const_cast<char*>(query.value(1).toByteArray().constData())).clone());
    }

    if (0 == feature.rows)
    {
        return nullptr;
    }
    else
    {
        return cv::ml::TrainData::create(feature, cv::ml::ROW_SAMPLE, label);
    }
}

void FaceDb::clearDNNTraining()
{
    d->db->execSql(QLatin1String("DELETE FROM FaceMatrices;"));
}

void FaceDb::clearDNNTraining(const QList<int>& identities)<--- Shadow argument
{
    for (int id : std::as_const(identities))
    {
        d->db->execSql(QLatin1String("DELETE FROM FaceMatrices WHERE identity=?;"),
                       id);
    }
}

void FaceDb::getTrainingVersionInfo(QString& version, QString& model) const
{
    version = setting(QStringLiteral("TrainingVersion"));
    model   = setting(QStringLiteral("ExtractorModel"));
}

void FaceDb::setTrainingVersionInfo(const QString& version, const QString& model)
{
    setSetting(QStringLiteral("TrainingVersion"), version);
    setSetting(QStringLiteral("ExtractorModel"), model);
}

} // namespace Digikam