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 }