File indexing completed on 2025-01-05 03:58:05

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2010-06-16
0007  * Description : Face alignment CLI tool
0008  *
0009  * SPDX-FileCopyrightText: 2010 by Aditya Bhatt <adityabhatt1991 at gmail dot com>
0010  *
0011  * SPDX-License-Identifier: GPL-2.0-or-later
0012  *
0013  * ============================================================ */
0014 
0015 // Qt includes
0016 
0017 #include <QApplication>
0018 #include <QDir>
0019 #include <QImage>
0020 #include <QElapsedTimer>
0021 #include <QLabel>
0022 #include <QGraphicsScene>
0023 
0024 // Local includes
0025 
0026 #include "qtopencv.h"
0027 #include "funnelreal.h"
0028 #include "digikam_debug.h"
0029 
0030 using namespace Digikam;
0031 
0032 QStringList toPaths(char** const argv, int startIndex, int argc)
0033 {
0034     QStringList files;
0035 
0036     for (int i = startIndex ; i < argc ; ++i)
0037     {
0038         files << QString::fromLocal8Bit(argv[i]);
0039     }
0040 
0041     return files;
0042 }
0043 
0044 QList<cv::Mat> toImages(const QStringList& paths)
0045 {
0046     QList<cv::Mat> images;
0047 
0048     Q_FOREACH (const QString& path, paths)
0049     {
0050         QByteArray s = path.toLocal8Bit();
0051         images << cv::imread(std::string(s.data()));
0052     }
0053 
0054     return images;
0055 }
0056 
0057 // --------------------------------------------------------------------------------------------------
0058 
0059 class Q_DECL_HIDDEN OpenCVSideBySideDisplay
0060 {
0061 public:
0062 
0063     explicit OpenCVSideBySideDisplay(int rows, int uiSize = 200)
0064         : bigImage(cv::Mat::zeros(uiSize*rows, 2*uiSize, CV_8UC3)),
0065           uiSize(uiSize),
0066           currentRow(0)
0067     {
0068     }
0069 
0070     void add(const cv::Mat& left, const cv::Mat& right)
0071     {
0072         // Draw images side-by-side for later display
0073 
0074         QSize size(left.cols, left.rows);
0075         size.scale(uiSize, uiSize, Qt::KeepAspectRatio);
0076         cv::Size scaleSize(size.width(), size.height());
0077 
0078         const int top = currentRow * uiSize;
0079         cv::Mat scaledLeft;
0080         cv::Mat scaledRight;
0081         cv::resize(left,  scaledLeft,  scaleSize);
0082         cv::resize(right, scaledRight, scaleSize);
0083 
0084         if (scaledLeft.channels() == 1)
0085         {
0086             cv::cvtColor(scaledLeft, scaledLeft, CV_GRAY2BGR);
0087         }
0088 
0089         if (scaledRight.channels() == 1)
0090         {
0091             cv::cvtColor(scaledRight, scaledRight, CV_GRAY2BGR);
0092         }
0093 
0094         scaledLeft.copyTo(bigImage.colRange(0, scaledLeft.cols).rowRange(top, top + scaledLeft.rows));
0095         scaledRight.copyTo(bigImage.colRange(uiSize, uiSize + scaledRight.cols).rowRange(top, top + scaledRight.rows));
0096 
0097         ++currentRow;
0098     }
0099 
0100     void show()
0101     {
0102         QLabel label;
0103         label.setPixmap(QtOpenCV::cvMatToQPixmap(bigImage));
0104         label.show();
0105     }
0106 
0107 public:
0108 
0109     cv::Mat   bigImage;
0110     const int uiSize;
0111     int       currentRow;
0112 };
0113 
0114 // --------------------------------------------------------------------------------------------------
0115 
0116 int main(int argc, char** argv)
0117 {
0118     if (argc < 2)
0119     {
0120         qCDebug(DIGIKAM_TESTS_LOG) << "Bad Arguments!!!\nUsage: " << argv[0] << " align <image1> <image2> ... ";
0121         return 0;
0122     }
0123 
0124     QApplication app(argc, argv);
0125 
0126     QStringList paths     = toPaths(argv, 1, argc);
0127     QList<cv::Mat> images = toImages(paths);
0128 
0129     QElapsedTimer timer;
0130     timer.start();
0131 
0132     FunnelReal funnel;
0133     qCDebug(DIGIKAM_TESTS_LOG) << "Setup of Aligner took " << timer.restart();
0134 
0135     OpenCVSideBySideDisplay display(images.size());
0136 
0137     Q_FOREACH (const cv::Mat& image, images)
0138     {
0139         cv::Mat aligned = funnel.align(image);
0140         display.add(image, aligned);
0141     }
0142 
0143     int elapsed = timer.elapsed();
0144     qCDebug(DIGIKAM_TESTS_LOG) << "Alignment took " << elapsed << " for " << images.size() << " , "
0145              << ((float)elapsed/images.size()) << " per image";
0146 
0147     display.show();
0148     app.exec();
0149 
0150     return 0;
0151 }