1 /* ============================================================
2  *
3  * This file is a part of digiKam project
4  * https://www.digikam.org
5  *
6  * Date        : 2010-06-16
7  * Description : Face pre-processing CLI tool
8  *
9  * Copyright (C) 2010 by Aditya Bhatt <adityabhatt1991 at gmail dot com>
10  *
11  * This program is free software; you can redistribute it
12  * and/or modify it under the terms of the GNU General
13  * Public License as published by the Free Software Foundation;
14  * either version 2, or (at your option)
15  * any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * ============================================================ */
23 
24 // Qt includes
25 
26 #include <QApplication>
27 #include <QDir>
28 #include <QLabel>
29 #include <QImage>
30 #include <QElapsedTimer>
31 
32 // Local includes
33 
34 #include "digikam_debug.h"
35 #include "qtopencv.h"
36 #include "tantriggspreprocessor.h"
37 
38 using namespace Digikam;
39 
40 // --------------------------------------------------------------------------------------------------
41 
toPaths(char ** const argv,int startIndex,int argc)42 QStringList toPaths(char** const argv, int startIndex, int argc)
43 {
44     QStringList files;
45 
46     for (int i = startIndex ; i < argc ; ++i)
47     {
48         files << QString::fromLocal8Bit(argv[i]);
49     }
50 
51     return files;
52 }
53 
toImages(const QStringList & paths)54 QList<cv::Mat> toImages(const QStringList& paths)
55 {
56     QList<cv::Mat> images;
57 
58     foreach (const QString& path, paths)
59     {
60         QByteArray s = path.toLocal8Bit();
61         images << cv::imread(std::string(s.data()),
62 
63 #if OPENCV_TEST_VERSION(3,99,0)
64 
65             CV_LOAD_IMAGE_GRAYSCALE
66 
67 #else
68 
69             cv::IMREAD_GRAYSCALE
70 
71 #endif
72 
73         );
74     }
75 
76     return images;
77 }
78 
79 // --------------------------------------------------------------------------------------------------
80 
81 class Q_DECL_HIDDEN OpenCVSideBySideDisplay
82 {
83 public:
84 
OpenCVSideBySideDisplay(int rows,int uiSize=200)85     explicit OpenCVSideBySideDisplay(int rows, int uiSize = 200)
86         : bigImage(cv::Mat::zeros(uiSize*rows, 2*uiSize, CV_8UC3)),
87           uiSize(uiSize),
88           currentRow(0)
89     {
90     }
91 
add(const cv::Mat & left,const cv::Mat & right)92     void add(const cv::Mat& left, const cv::Mat& right)
93     {
94         // Draw images side-by-side for later display
95 
96         QSize size(left.cols, left.rows);
97         size.scale(uiSize, uiSize, Qt::KeepAspectRatio);
98         cv::Size scaleSize(size.width(), size.height());
99 
100         const int top = currentRow * uiSize;
101         cv::Mat scaledLeft;
102         cv::Mat scaledRight;
103         cv::resize(left,  scaledLeft,  scaleSize);
104         cv::resize(right, scaledRight, scaleSize);
105 
106         if (scaledLeft.channels() == 1)
107         {
108             cv::cvtColor(scaledLeft, scaledLeft, CV_GRAY2BGR);
109         }
110 
111         if (scaledRight.channels() == 1)
112         {
113             cv::cvtColor(scaledRight, scaledRight, CV_GRAY2BGR);
114         }
115 
116         scaledLeft.copyTo(bigImage.colRange(0, scaledLeft.cols).rowRange(top, top + scaledLeft.rows));
117         scaledRight.copyTo(bigImage.colRange(uiSize, uiSize + scaledRight.cols).rowRange(top, top + scaledRight.rows));
118 
119         ++currentRow;
120     }
121 
show()122     void show()
123     {
124         QLabel label;
125         label.setPixmap(QtOpenCV::cvMatToQPixmap(bigImage));
126         label.show();
127     }
128 
129 public:
130 
131     cv::Mat   bigImage;
132     const int uiSize;
133     int       currentRow;
134 };
135 
136 // --------------------------------------------------------------------------------------------------
137 
main(int argc,char ** argv)138 int main(int argc, char** argv)
139 {
140     if (argc < 2)
141     {
142         qCDebug(DIGIKAM_TESTS_LOG) << "Bad Arguments!!!\nUsage: " << argv[0] << " preprocess <image1> <image2> ... ";
143         return 0;
144     }
145 
146     QApplication app(argc, argv);
147 
148     QStringList paths     = toPaths(argv, 1, argc);
149     QList<cv::Mat> images = toImages(paths);
150 
151     QElapsedTimer timer;
152     timer.start();
153 
154     TanTriggsPreprocessor preprocessor;
155     OpenCVSideBySideDisplay display(images.size());
156 
157     foreach (const cv::Mat& image, images)
158     {
159         qCDebug(DIGIKAM_TESTS_LOG) << "channels " << image.channels();
160         cv::Mat processed = preprocessor.preprocess(image);
161         display.add(image, processed);
162     }
163 
164     int elapsed = timer.elapsed();
165     qCDebug(DIGIKAM_TESTS_LOG) << "Preprocessing took " << elapsed << " for " << images.size() << " , "
166              << ((float)elapsed/images.size()) << " per image";
167 
168     display.show();
169     app.exec();
170 
171     return 0;
172 }
173