Commit 4d39cf939575e209f8512b8efb5ee42c1e3ae930
Merge branch 'master' of https://github.com/biometrics/openbr
Showing
22 changed files
with
155 additions
and
151 deletions
app/br/br.cpp
| @@ -68,12 +68,13 @@ public: | @@ -68,12 +68,13 @@ public: | ||
| 68 | if (argc == 0) printf("%s\nTry running 'br -help'\n", br_about()); | 68 | if (argc == 0) printf("%s\nTry running 'br -help'\n", br_about()); |
| 69 | 69 | ||
| 70 | bool daemon = false; | 70 | bool daemon = false; |
| 71 | + const char *daemon_pipe = NULL; | ||
| 71 | while (daemon || (argc > 0)) { | 72 | while (daemon || (argc > 0)) { |
| 72 | const char *fun; | 73 | const char *fun; |
| 73 | int parc; | 74 | int parc; |
| 74 | const char **parv; | 75 | const char **parv; |
| 75 | if (argc == 0) | 76 | if (argc == 0) |
| 76 | - br_read_stdin(&argc, &argv); | 77 | + br_read_pipe(daemon_pipe, &argc, &argv); |
| 77 | 78 | ||
| 78 | fun = argv[0]; | 79 | fun = argv[0]; |
| 79 | if (fun[0] == '-') fun++; | 80 | if (fun[0] == '-') fun++; |
| @@ -158,8 +159,9 @@ public: | @@ -158,8 +159,9 @@ public: | ||
| 158 | check(parc == 0, "No parameters expected for 'version'."); | 159 | check(parc == 0, "No parameters expected for 'version'."); |
| 159 | printf("%s\n", br_version()); | 160 | printf("%s\n", br_version()); |
| 160 | } else if (!strcmp(fun, "daemon")) { | 161 | } else if (!strcmp(fun, "daemon")) { |
| 161 | - check(parc == 0, "No parameters expected for 'daemon'."); | 162 | + check(parc == 1, "Incorrect parameter count for 'daemon'."); |
| 162 | daemon = true; | 163 | daemon = true; |
| 164 | + daemon_pipe = parv[0]; | ||
| 163 | } else if (!strcmp(fun, "exit")) { | 165 | } else if (!strcmp(fun, "exit")) { |
| 164 | check(parc == 0, "No parameters expected for 'exit'."); | 166 | check(parc == 0, "No parameters expected for 'exit'."); |
| 165 | daemon = false; | 167 | daemon = false; |
openbr/core/core.cpp
| @@ -275,17 +275,14 @@ private: | @@ -275,17 +275,14 @@ private: | ||
| 275 | return QFileInfo(file).exists() ? file : QString(); | 275 | return QFileInfo(file).exists() ? file : QString(); |
| 276 | } | 276 | } |
| 277 | 277 | ||
| 278 | - void init(QString description) | 278 | + void init(const File &description) |
| 279 | { | 279 | { |
| 280 | // Check if a trained binary already exists for this algorithm | 280 | // Check if a trained binary already exists for this algorithm |
| 281 | const QString file = getFileName(description); | 281 | const QString file = getFileName(description); |
| 282 | - if (!file.isEmpty()) description = file; | 282 | + if (!file.isEmpty()) return init(file); |
| 283 | 283 | ||
| 284 | - File asdf(description); | ||
| 285 | - QString distribute_status = asdf.get<QString>("distribute","true"); | ||
| 286 | - | ||
| 287 | - if (QFileInfo(description).exists()) { | ||
| 288 | - qDebug("Loading %s", qPrintable(QFileInfo(description).fileName())); | 284 | + if (description.exists()) { |
| 285 | + qDebug("Loading %s", qPrintable(description.fileName())); | ||
| 289 | load(description); | 286 | load(description); |
| 290 | return; | 287 | return; |
| 291 | } | 288 | } |
| @@ -294,13 +291,11 @@ private: | @@ -294,13 +291,11 @@ private: | ||
| 294 | if (Globals->abbreviations.contains(description)) | 291 | if (Globals->abbreviations.contains(description)) |
| 295 | return init(Globals->abbreviations[description]); | 292 | return init(Globals->abbreviations[description]); |
| 296 | 293 | ||
| 297 | - QStringList words = QtUtils::parse(description, ':'); | ||
| 298 | - if (words.size() > 2) qFatal("Invalid algorithm format."); | 294 | + QStringList words = QtUtils::parse(description.flat(), ':'); |
| 295 | + if ((words.size() < 1) || (words.size() > 2)) qFatal("Invalid algorithm format."); | ||
| 299 | 296 | ||
| 300 | - if (distribute_status == "true") { | ||
| 301 | - words[0].prepend("DistributeTemplate("); | ||
| 302 | - words[0].append(")"); | ||
| 303 | - } | 297 | + if (description.getBool("distribute", true)) |
| 298 | + words[0] = "DistributeTemplate(" + words[0] + ")"; | ||
| 304 | 299 | ||
| 305 | transform = QSharedPointer<Transform>(Transform::make(words[0], NULL)); | 300 | transform = QSharedPointer<Transform>(Transform::make(words[0], NULL)); |
| 306 | if (words.size() > 1) distance = QSharedPointer<Distance>(Distance::make(words[1], NULL)); | 301 | if (words.size() > 1) distance = QSharedPointer<Distance>(Distance::make(words[1], NULL)); |
openbr/openbr.cpp
| @@ -182,17 +182,23 @@ float br_progress() | @@ -182,17 +182,23 @@ float br_progress() | ||
| 182 | return Globals->progress(); | 182 | return Globals->progress(); |
| 183 | } | 183 | } |
| 184 | 184 | ||
| 185 | -void br_read_stdin(int *argc, char ***argv) | 185 | +void br_read_pipe(const char *pipe, int *argc, char ***argv) |
| 186 | { | 186 | { |
| 187 | static QList<QByteArray> byteArrayList; | 187 | static QList<QByteArray> byteArrayList; |
| 188 | static QVector<char*> rawCharArrayList; | 188 | static QVector<char*> rawCharArrayList; |
| 189 | 189 | ||
| 190 | + QFile file(pipe); | ||
| 191 | + file.open(QFile::ReadOnly); | ||
| 192 | + QTextStream stream(&file); | ||
| 193 | + | ||
| 190 | QStringList args; | 194 | QStringList args; |
| 191 | while (args.isEmpty()) { | 195 | while (args.isEmpty()) { |
| 192 | - args = QtUtils::parse(QTextStream(stdin).readLine(), ' '); | ||
| 193 | - QThread::yieldCurrentThread(); | 196 | + args = QtUtils::parse(stream.readAll(), ' '); |
| 197 | + if (args.isEmpty()) QThread::sleep(100); | ||
| 194 | } | 198 | } |
| 195 | 199 | ||
| 200 | + file.close(); | ||
| 201 | + | ||
| 196 | byteArrayList.clear(); rawCharArrayList.clear(); | 202 | byteArrayList.clear(); rawCharArrayList.clear(); |
| 197 | foreach (const QString &string, args) { | 203 | foreach (const QString &string, args) { |
| 198 | byteArrayList.append(string.toLocal8Bit()); | 204 | byteArrayList.append(string.toLocal8Bit()); |
openbr/openbr.h
| @@ -297,16 +297,15 @@ BR_EXPORT bool br_plot_metadata(int num_files, const char *files[], const char * | @@ -297,16 +297,15 @@ BR_EXPORT bool br_plot_metadata(int num_files, const char *files[], const char * | ||
| 297 | BR_EXPORT float br_progress(); | 297 | BR_EXPORT float br_progress(); |
| 298 | 298 | ||
| 299 | /*! | 299 | /*! |
| 300 | - * \brief Read and parse stdin. | 300 | + * \brief Read and parse arguments from a named pipe. |
| 301 | * | 301 | * |
| 302 | - * Used by the \ref cli to implement \c -daemon. | 302 | + * Used by the \ref cli to implement \c -daemon, generally not useful otherwise. |
| 303 | * Guaranteed to return at least one argument. | 303 | * Guaranteed to return at least one argument. |
| 304 | - * Generally not useful otherwise. | ||
| 305 | * \param[out] argc argument count | 304 | * \param[out] argc argument count |
| 306 | * \param[out] argv argument list | 305 | * \param[out] argv argument list |
| 307 | * \note \ref managed_return_value | 306 | * \note \ref managed_return_value |
| 308 | */ | 307 | */ |
| 309 | -BR_EXPORT void br_read_stdin(int *argc, char ***argv); | 308 | +BR_EXPORT void br_read_pipe(const char *pipe, int *argc, char ***argv); |
| 310 | 309 | ||
| 311 | /*! | 310 | /*! |
| 312 | * \brief Converts a simmat to a new output format. | 311 | * \brief Converts a simmat to a new output format. |
openbr/openbr_plugin.cpp
| @@ -801,8 +801,8 @@ void br::Context::setProperty(const QString &key, const QString &value) | @@ -801,8 +801,8 @@ void br::Context::setProperty(const QString &key, const QString &value) | ||
| 801 | qDebug("Set %s%s", qPrintable(key), value.isEmpty() ? "" : qPrintable(" to " + value)); | 801 | qDebug("Set %s%s", qPrintable(key), value.isEmpty() ? "" : qPrintable(" to " + value)); |
| 802 | 802 | ||
| 803 | if (key == "parallelism") { | 803 | if (key == "parallelism") { |
| 804 | - const int maxThreads = std::max(1, QThread::idealThreadCount()); | ||
| 805 | - QThreadPool::globalInstance()->setMaxThreadCount(parallelism ? std::min(maxThreads, abs(parallelism)) : maxThreads); | 804 | + if (parallelism <= 0) parallelism = 1; |
| 805 | + QThreadPool::globalInstance()->setMaxThreadCount(parallelism); | ||
| 806 | } else if (key == "log") { | 806 | } else if (key == "log") { |
| 807 | logFile.close(); | 807 | logFile.close(); |
| 808 | if (log.isEmpty()) return; | 808 | if (log.isEmpty()) return; |
| @@ -829,8 +829,17 @@ bool br::Context::checkSDKPath(const QString &sdkPath) | @@ -829,8 +829,17 @@ bool br::Context::checkSDKPath(const QString &sdkPath) | ||
| 829 | // We create our own when the user hasn't | 829 | // We create our own when the user hasn't |
| 830 | static QCoreApplication *application = NULL; | 830 | static QCoreApplication *application = NULL; |
| 831 | 831 | ||
| 832 | -void br::Context::initialize(int &argc, char *argv[], QString sdkPath) | 832 | +void br::Context::initialize(int &argc, char *argv[], QString sdkPath, bool use_gui) |
| 833 | { | 833 | { |
| 834 | + for (int i=0; i < argc; i ++) | ||
| 835 | + { | ||
| 836 | + if (strcmp("-useGui", argv[i]) == 0) { | ||
| 837 | + const char * val = i+1 < argc ? argv[i+1] : ""; | ||
| 838 | + if (strcmp(val, "false") ==0 || strcmp(val, "0") == 0) | ||
| 839 | + use_gui = false; | ||
| 840 | + break; | ||
| 841 | + } | ||
| 842 | + } | ||
| 834 | // We take in argc as a reference due to: | 843 | // We take in argc as a reference due to: |
| 835 | // https://bugreports.qt-project.org/browse/QTBUG-5637 | 844 | // https://bugreports.qt-project.org/browse/QTBUG-5637 |
| 836 | // QApplication should be initialized before anything else. | 845 | // QApplication should be initialized before anything else. |
| @@ -861,6 +870,7 @@ void br::Context::initialize(int &argc, char *argv[], QString sdkPath) | @@ -861,6 +870,7 @@ void br::Context::initialize(int &argc, char *argv[], QString sdkPath) | ||
| 861 | 870 | ||
| 862 | Globals = new Context(); | 871 | Globals = new Context(); |
| 863 | Globals->init(File()); | 872 | Globals->init(File()); |
| 873 | + Globals->useGui = use_gui; | ||
| 864 | 874 | ||
| 865 | qInstallMessageHandler(messageHandler); | 875 | qInstallMessageHandler(messageHandler); |
| 866 | 876 | ||
| @@ -885,8 +895,7 @@ void br::Context::initialize(int &argc, char *argv[], QString sdkPath) | @@ -885,8 +895,7 @@ void br::Context::initialize(int &argc, char *argv[], QString sdkPath) | ||
| 885 | } | 895 | } |
| 886 | Globals->sdkPath = sdkPath; | 896 | Globals->sdkPath = sdkPath; |
| 887 | 897 | ||
| 888 | - // Empirical evidence suggests an extra thread helps achieve full CPU utilization | ||
| 889 | - QThreadPool::globalInstance()->releaseThread(); | 898 | + QThreadPool::globalInstance()->setMaxThreadCount(Globals->parallelism); |
| 890 | 899 | ||
| 891 | // Trigger registered initializers | 900 | // Trigger registered initializers |
| 892 | QList< QSharedPointer<Initializer> > initializers = Factory<Initializer>::makeAll(); | 901 | QList< QSharedPointer<Initializer> > initializers = Factory<Initializer>::makeAll(); |
| @@ -896,9 +905,6 @@ void br::Context::initialize(int &argc, char *argv[], QString sdkPath) | @@ -896,9 +905,6 @@ void br::Context::initialize(int &argc, char *argv[], QString sdkPath) | ||
| 896 | 905 | ||
| 897 | void br::Context::finalize() | 906 | void br::Context::finalize() |
| 898 | { | 907 | { |
| 899 | - // Undo the 'releaseThread()' in 'initialize()' | ||
| 900 | - QThreadPool::globalInstance()->reserveThread(); | ||
| 901 | - | ||
| 902 | // Trigger registered finalizers | 908 | // Trigger registered finalizers |
| 903 | QList< QSharedPointer<Initializer> > initializers = Factory<Initializer>::makeAll(); | 909 | QList< QSharedPointer<Initializer> > initializers = Factory<Initializer>::makeAll(); |
| 904 | foreach (const QSharedPointer<Initializer> &initializer, initializers) | 910 | foreach (const QSharedPointer<Initializer> &initializer, initializers) |
| @@ -1192,10 +1198,8 @@ private: | @@ -1192,10 +1198,8 @@ private: | ||
| 1192 | templatesList[i] = Downsample(templatesList[i], transforms[i]); | 1198 | templatesList[i] = Downsample(templatesList[i], transforms[i]); |
| 1193 | 1199 | ||
| 1194 | QFutureSynchronizer<void> futures; | 1200 | QFutureSynchronizer<void> futures; |
| 1195 | - for (int i=0; i<templatesList.size(); i++) { | ||
| 1196 | - if (Globals->parallelism) futures.addFuture(QtConcurrent::run(_train, transforms[i], &templatesList[i])); | ||
| 1197 | - else _train (transforms[i], &templatesList[i]); | ||
| 1198 | - } | 1201 | + for (int i=0; i<templatesList.size(); i++) |
| 1202 | + futures.addFuture(QtConcurrent::run(_train, transforms[i], &templatesList[i])); | ||
| 1199 | futures.waitForFinished(); | 1203 | futures.waitForFinished(); |
| 1200 | } | 1204 | } |
| 1201 | 1205 | ||
| @@ -1308,21 +1312,12 @@ void Transform::project(const TemplateList &src, TemplateList &dst) const | @@ -1308,21 +1312,12 @@ void Transform::project(const TemplateList &src, TemplateList &dst) const | ||
| 1308 | { | 1312 | { |
| 1309 | dst.reserve(src.size()); | 1313 | dst.reserve(src.size()); |
| 1310 | 1314 | ||
| 1311 | - // There are certain conditions where we should process the templates in serial, | ||
| 1312 | - // but generally we'd prefer to process them in parallel. | ||
| 1313 | - if ((src.size() < 2) || (Globals->parallelism == 0)) { | ||
| 1314 | - foreach (const Template &t, src) { | ||
| 1315 | - dst.append(Template()); | ||
| 1316 | - _project(this, &t, &dst.last()); | ||
| 1317 | - } | ||
| 1318 | - } else { | ||
| 1319 | - for (int i=0; i<src.size(); i++) | ||
| 1320 | - dst.append(Template()); | ||
| 1321 | - QFutureSynchronizer<void> futures; | ||
| 1322 | - for (int i=0; i<dst.size(); i++) | ||
| 1323 | - futures.addFuture(QtConcurrent::run(_project, this, &src[i], &dst[i])); | ||
| 1324 | - futures.waitForFinished(); | ||
| 1325 | - } | 1315 | + for (int i=0; i<src.size(); i++) |
| 1316 | + dst.append(Template()); | ||
| 1317 | + QFutureSynchronizer<void> futures; | ||
| 1318 | + for (int i=0; i<dst.size(); i++) | ||
| 1319 | + futures.addFuture(QtConcurrent::run(_project, this, &src[i], &dst[i])); | ||
| 1320 | + futures.waitForFinished(); | ||
| 1326 | } | 1321 | } |
| 1327 | 1322 | ||
| 1328 | static void _backProject(const Transform *transform, const Template *dst, Template *src) | 1323 | static void _backProject(const Transform *transform, const Template *dst, Template *src) |
| @@ -1343,8 +1338,7 @@ void Transform::backProject(const TemplateList &dst, TemplateList &src) const | @@ -1343,8 +1338,7 @@ void Transform::backProject(const TemplateList &dst, TemplateList &src) const | ||
| 1343 | 1338 | ||
| 1344 | QFutureSynchronizer<void> futures; | 1339 | QFutureSynchronizer<void> futures; |
| 1345 | for (int i=0; i<dst.size(); i++) | 1340 | for (int i=0; i<dst.size(); i++) |
| 1346 | - if (Globals->parallelism) futures.addFuture(QtConcurrent::run(_backProject, this, &dst[i], &src[i])); | ||
| 1347 | - else _backProject (this, &dst[i], &src[i]); | 1341 | + futures.addFuture(QtConcurrent::run(_backProject, this, &dst[i], &src[i])); |
| 1348 | futures.waitForFinished(); | 1342 | futures.waitForFinished(); |
| 1349 | } | 1343 | } |
| 1350 | 1344 |
openbr/openbr_plugin.h
| @@ -189,6 +189,7 @@ struct BR_EXPORT File | @@ -189,6 +189,7 @@ struct BR_EXPORT File | ||
| 189 | inline QString baseName() const { const QString baseName = QFileInfo(name).baseName(); | 189 | inline QString baseName() const { const QString baseName = QFileInfo(name).baseName(); |
| 190 | return baseName.isEmpty() ? QDir(name).dirName() : baseName; } /*!< \brief Returns the file's base name. */ | 190 | return baseName.isEmpty() ? QDir(name).dirName() : baseName; } /*!< \brief Returns the file's base name. */ |
| 191 | inline QString suffix() const { return QFileInfo(name).suffix(); } /*!< \brief Returns the file's extension. */ | 191 | inline QString suffix() const { return QFileInfo(name).suffix(); } /*!< \brief Returns the file's extension. */ |
| 192 | + inline QString path() const { return QFileInfo(name).path(); } /*! \brief Returns the file's path excluding its name. */ | ||
| 192 | QString resolved() const; /*!< \brief Returns name prepended with Globals->path if name does not exist. */ | 193 | QString resolved() const; /*!< \brief Returns name prepended with Globals->path if name does not exist. */ |
| 193 | 194 | ||
| 194 | bool contains(const QString &key) const; /*!< \brief Returns \c true if the key has an associated value, \c false otherwise. */ | 195 | bool contains(const QString &key) const; /*!< \brief Returns \c true if the key has an associated value, \c false otherwise. */ |
| @@ -547,7 +548,13 @@ public: | @@ -547,7 +548,13 @@ public: | ||
| 547 | * \brief The number of threads to use. | 548 | * \brief The number of threads to use. |
| 548 | */ | 549 | */ |
| 549 | Q_PROPERTY(int parallelism READ get_parallelism WRITE set_parallelism RESET reset_parallelism) | 550 | Q_PROPERTY(int parallelism READ get_parallelism WRITE set_parallelism RESET reset_parallelism) |
| 550 | - BR_PROPERTY(int, parallelism, std::max(1, QThread::idealThreadCount())) | 551 | + BR_PROPERTY(int, parallelism, std::max(1, QThread::idealThreadCount()+1)) |
| 552 | + | ||
| 553 | + /*! | ||
| 554 | + * \brief Whether or not to use GUI functions | ||
| 555 | + */ | ||
| 556 | + Q_PROPERTY(bool useGui READ get_useGui WRITE set_useGui RESET reset_useGui) | ||
| 557 | + BR_PROPERTY(bool, useGui, true) | ||
| 551 | 558 | ||
| 552 | /*! | 559 | /*! |
| 553 | * \brief The maximum number of templates to process in parallel. | 560 | * \brief The maximum number of templates to process in parallel. |
| @@ -701,7 +708,7 @@ public: | @@ -701,7 +708,7 @@ public: | ||
| 701 | * \note <a href="http://qt-project.org/">Qt</a> users should instead call this <i>after</i> initializing QApplication. | 708 | * \note <a href="http://qt-project.org/">Qt</a> users should instead call this <i>after</i> initializing QApplication. |
| 702 | * \see finalize | 709 | * \see finalize |
| 703 | */ | 710 | */ |
| 704 | - static void initialize(int &argc, char *argv[], QString sdkPath = ""); | 711 | + static void initialize(int &argc, char *argv[], QString sdkPath = "", bool use_gui = true); |
| 705 | 712 | ||
| 706 | /*! | 713 | /*! |
| 707 | * \brief Call \em once at the end of the application to deallocate global variables. | 714 | * \brief Call \em once at the end of the application to deallocate global variables. |
openbr/plugins/algorithms.cpp
| @@ -38,11 +38,11 @@ class AlgorithmsInitializer : public Initializer | @@ -38,11 +38,11 @@ class AlgorithmsInitializer : public Initializer | ||
| 38 | Globals->abbreviations.insert("MedianFace", "Open!Cascade(FrontalFace)+ASEFEyes+Affine(256,256,0.37,0.45)+Center(Median)"); | 38 | Globals->abbreviations.insert("MedianFace", "Open!Cascade(FrontalFace)+ASEFEyes+Affine(256,256,0.37,0.45)+Center(Median)"); |
| 39 | Globals->abbreviations.insert("BlurredFaceDetection", "Open+LimitSize(1024)+SkinMask/(Cvt(Gray)+GradientMask)+And+Morph(Erode,16)+LargestConvexArea"); | 39 | Globals->abbreviations.insert("BlurredFaceDetection", "Open+LimitSize(1024)+SkinMask/(Cvt(Gray)+GradientMask)+And+Morph(Erode,16)+LargestConvexArea"); |
| 40 | Globals->abbreviations.insert("DrawFaceDetection", "Open+Cascade(FrontalFace)!ASEFEyes+Draw"); | 40 | Globals->abbreviations.insert("DrawFaceDetection", "Open+Cascade(FrontalFace)!ASEFEyes+Draw"); |
| 41 | - Globals->abbreviations.insert("ShowFaceDetection", "DrawFaceDetection!Show"); | 41 | + Globals->abbreviations.insert("ShowFaceDetection", "DrawFaceDetection!Show[distribute=false]"); |
| 42 | Globals->abbreviations.insert("OpenBR", "FaceRecognition"); | 42 | Globals->abbreviations.insert("OpenBR", "FaceRecognition"); |
| 43 | Globals->abbreviations.insert("GenderEstimation", "GenderClassification"); | 43 | Globals->abbreviations.insert("GenderEstimation", "GenderClassification"); |
| 44 | Globals->abbreviations.insert("AgeEstimation", "AgeRegression"); | 44 | Globals->abbreviations.insert("AgeEstimation", "AgeRegression"); |
| 45 | - Globals->abbreviations.insert("FaceRecognition2", "{PP5Register+Affine(128,128,0.25,0.35)+Cvt(Gray)}+(Gradient+Bin(0,360,9,true))/(Blur(1)+Gamma(0.2)+DoG(1,2)+ContrastEq(0.1,10)+LBP(1,2,true)+Bin(0,10,10,true))+Merge+Integral+RecursiveIntegralSampler(4,2,8,Center(Hellinger)+LDA(.98)+Normalize(L1)+Cat+PCA(768)+Normalize(L1)+Quantize:UCharL1"); | 45 | + Globals->abbreviations.insert("FaceRecognition2", "{PP5Register+Affine(128,128,0.25,0.35)+Cvt(Gray)}+(Gradient+Bin(0,360,9,true))/(Blur(1)+Gamma(0.2)+DoG(1,2)+ContrastEq(0.1,10)+LBP(1,2,true)+Bin(0,10,10,true))+Merge+Integral+RecursiveIntegralSampler(4,2,8,LDA(.98)+Normalize(L1))+Cat+PCA(768)+Normalize(L1)+Quantize:UCharL1"); |
| 46 | 46 | ||
| 47 | // Generic Image Processing | 47 | // Generic Image Processing |
| 48 | Globals->abbreviations.insert("SIFT", "Open+KeyPointDetector(SIFT)+KeyPointDescriptor(SIFT):KeyPointMatcher(BruteForce)"); | 48 | Globals->abbreviations.insert("SIFT", "Open+KeyPointDetector(SIFT)+KeyPointDescriptor(SIFT):KeyPointMatcher(BruteForce)"); |
openbr/plugins/distance.cpp
| @@ -158,8 +158,7 @@ class PipeDistance : public Distance | @@ -158,8 +158,7 @@ class PipeDistance : public Distance | ||
| 158 | { | 158 | { |
| 159 | QFutureSynchronizer<void> futures; | 159 | QFutureSynchronizer<void> futures; |
| 160 | foreach (br::Distance *distance, distances) | 160 | foreach (br::Distance *distance, distances) |
| 161 | - if (Globals->parallelism) futures.addFuture(QtConcurrent::run(distance, &Distance::train, data)); | ||
| 162 | - else distance->train(data); | 161 | + futures.addFuture(QtConcurrent::run(distance, &Distance::train, data)); |
| 163 | futures.waitForFinished(); | 162 | futures.waitForFinished(); |
| 164 | } | 163 | } |
| 165 | 164 |
openbr/plugins/draw.cpp
| @@ -98,6 +98,8 @@ class DrawGridTransform : public UntrainableTransform | @@ -98,6 +98,8 @@ class DrawGridTransform : public UntrainableTransform | ||
| 98 | 98 | ||
| 99 | BR_REGISTER(Transform, DrawGridTransform) | 99 | BR_REGISTER(Transform, DrawGridTransform) |
| 100 | 100 | ||
| 101 | +// TODO: re-implement EditTransform using Qt | ||
| 102 | +#if 0 | ||
| 101 | /*! | 103 | /*! |
| 102 | * \ingroup transforms | 104 | * \ingroup transforms |
| 103 | * \brief Remove landmarks. | 105 | * \brief Remove landmarks. |
| @@ -162,6 +164,7 @@ Template EditTransform::currentTemplate; | @@ -162,6 +164,7 @@ Template EditTransform::currentTemplate; | ||
| 162 | QMutex EditTransform::currentTemplateLock; | 164 | QMutex EditTransform::currentTemplateLock; |
| 163 | 165 | ||
| 164 | BR_REGISTER(Transform, EditTransform) | 166 | BR_REGISTER(Transform, EditTransform) |
| 167 | +#endif | ||
| 165 | 168 | ||
| 166 | } // namespace br | 169 | } // namespace br |
| 167 | 170 |
openbr/plugins/format.cpp
| @@ -15,6 +15,7 @@ | @@ -15,6 +15,7 @@ | ||
| 15 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | 15 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
| 16 | 16 | ||
| 17 | #include <QDate> | 17 | #include <QDate> |
| 18 | +#include <QSize> | ||
| 18 | #ifndef BR_EMBEDDED | 19 | #ifndef BR_EMBEDDED |
| 19 | #include <QtXml> | 20 | #include <QtXml> |
| 20 | #endif // BR_EMBEDDED | 21 | #endif // BR_EMBEDDED |
| @@ -547,14 +548,43 @@ BR_REGISTER(Format, nullFormat) | @@ -547,14 +548,43 @@ BR_REGISTER(Format, nullFormat) | ||
| 547 | class rawFormat : public Format | 548 | class rawFormat : public Format |
| 548 | { | 549 | { |
| 549 | Q_OBJECT | 550 | Q_OBJECT |
| 551 | + static QHash<QString, QHash<QString,QSize> > imageSizes; // QHash<Path, QHash<File,Size> > | ||
| 550 | 552 | ||
| 551 | Template read() const | 553 | Template read() const |
| 552 | { | 554 | { |
| 555 | + QString path = file.path(); | ||
| 556 | + if (!imageSizes.contains(path)) { | ||
| 557 | + static QMutex mutex; | ||
| 558 | + QMutexLocker locker(&mutex); | ||
| 559 | + | ||
| 560 | + if (!imageSizes.contains(path)) { | ||
| 561 | + const QString imageSize = path+"/ImageSize.txt"; | ||
| 562 | + QStringList lines; | ||
| 563 | + if (QFileInfo(imageSize).exists()) { | ||
| 564 | + lines = QtUtils::readLines(imageSize); | ||
| 565 | + lines.removeFirst(); // Remove header | ||
| 566 | + } | ||
| 567 | + | ||
| 568 | + QHash<QString,QSize> sizes; | ||
| 569 | + QRegExp whiteSpace("\\s+"); | ||
| 570 | + foreach (const QString &line, lines) { | ||
| 571 | + QStringList words = line.split(whiteSpace); | ||
| 572 | + if (words.size() != 3) continue; | ||
| 573 | + sizes.insert(words[0], QSize(words[2].toInt(), words[1].toInt())); | ||
| 574 | + } | ||
| 575 | + | ||
| 576 | + imageSizes.insert(path, sizes); | ||
| 577 | + } | ||
| 578 | + } | ||
| 579 | + | ||
| 553 | QByteArray data; | 580 | QByteArray data; |
| 554 | QtUtils::readFile(file, data); | 581 | QtUtils::readFile(file, data); |
| 555 | - if (data.size() != 768*800) | ||
| 556 | - qFatal("Expected 768*800 bytes."); | ||
| 557 | - return Template(file, Mat(768, 800, CV_8UC1, data.data()).clone()); | 582 | + |
| 583 | + QSize size = imageSizes[path][file.baseName()]; | ||
| 584 | + if (!size.isValid()) size = QSize(800,768); | ||
| 585 | + if (data.size() != size.width() * size.height()) | ||
| 586 | + qFatal("Expected %d*%d bytes, got %d.", size.height(), size.width(), data.size()); | ||
| 587 | + return Template(file, Mat(size.height(), size.width(), CV_8UC1, data.data()).clone()); | ||
| 558 | } | 588 | } |
| 559 | 589 | ||
| 560 | void write(const Template &t) const | 590 | void write(const Template &t) const |
| @@ -563,6 +593,8 @@ class rawFormat : public Format | @@ -563,6 +593,8 @@ class rawFormat : public Format | ||
| 563 | } | 593 | } |
| 564 | }; | 594 | }; |
| 565 | 595 | ||
| 596 | +QHash<QString, QHash<QString,QSize> > rawFormat::imageSizes; | ||
| 597 | + | ||
| 566 | BR_REGISTER(Format, rawFormat) | 598 | BR_REGISTER(Format, rawFormat) |
| 567 | 599 | ||
| 568 | /*! | 600 | /*! |
openbr/plugins/gallery.cpp
| @@ -107,8 +107,7 @@ class EmptyGallery : public Gallery | @@ -107,8 +107,7 @@ class EmptyGallery : public Gallery | ||
| 107 | QList< QFuture<TemplateList> > futures; | 107 | QList< QFuture<TemplateList> > futures; |
| 108 | foreach (const QString &folder, NaturalStringSort(dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot))) { | 108 | foreach (const QString &folder, NaturalStringSort(dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot))) { |
| 109 | const QDir subdir = dir.absoluteFilePath(folder); | 109 | const QDir subdir = dir.absoluteFilePath(folder); |
| 110 | - if (Globals->parallelism) futures.append(QtConcurrent::run(&EmptyGallery::getTemplates, subdir)); | ||
| 111 | - else templates.append(getTemplates(subdir)); | 110 | + futures.append(QtConcurrent::run(&EmptyGallery::getTemplates, subdir)); |
| 112 | } | 111 | } |
| 113 | foreach (const QFuture<TemplateList> &future, futures) | 112 | foreach (const QFuture<TemplateList> &future, futures) |
| 114 | templates.append(future.result()); | 113 | templates.append(future.result()); |
openbr/plugins/gui.cpp
| @@ -94,6 +94,8 @@ public slots: | @@ -94,6 +94,8 @@ public slots: | ||
| 94 | void createWindow() | 94 | void createWindow() |
| 95 | { | 95 | { |
| 96 | delete window; | 96 | delete window; |
| 97 | + QApplication::instance()->removeEventFilter(this); | ||
| 98 | + | ||
| 97 | window = new QLabel(); | 99 | window = new QLabel(); |
| 98 | window->setVisible(true); | 100 | window->setVisible(true); |
| 99 | 101 | ||
| @@ -109,21 +111,25 @@ public slots: | @@ -109,21 +111,25 @@ public slots: | ||
| 109 | * \ingroup transforms | 111 | * \ingroup transforms |
| 110 | * \brief Displays templates in a GUI pop-up window using QT. | 112 | * \brief Displays templates in a GUI pop-up window using QT. |
| 111 | * \author Charles Otto \cite caotto | 113 | * \author Charles Otto \cite caotto |
| 112 | - * Unlike ShowTransform, this can be used with parallelism enabled, although it | ||
| 113 | - * is considered TimeVarying. | 114 | + * Can be used with parallelism enabled, although it is considered TimeVarying. |
| 114 | */ | 115 | */ |
| 115 | -class Show2Transform : public TimeVaryingTransform | 116 | +class ShowTransform : public TimeVaryingTransform |
| 116 | { | 117 | { |
| 117 | Q_OBJECT | 118 | Q_OBJECT |
| 118 | public: | 119 | public: |
| 119 | Q_PROPERTY(bool waitInput READ get_waitInput WRITE set_waitInput RESET reset_waitInput STORED false) | 120 | Q_PROPERTY(bool waitInput READ get_waitInput WRITE set_waitInput RESET reset_waitInput STORED false) |
| 120 | - BR_PROPERTY(bool, waitInput, false) | 121 | + BR_PROPERTY(bool, waitInput, true) |
| 121 | 122 | ||
| 122 | Q_PROPERTY(QStringList keys READ get_keys WRITE set_keys RESET reset_keys STORED false) | 123 | Q_PROPERTY(QStringList keys READ get_keys WRITE set_keys RESET reset_keys STORED false) |
| 123 | BR_PROPERTY(QStringList, keys, QStringList("FrameNumber")) | 124 | BR_PROPERTY(QStringList, keys, QStringList("FrameNumber")) |
| 124 | 125 | ||
| 125 | - Show2Transform() : TimeVaryingTransform(false, false) | 126 | + ShowTransform() : TimeVaryingTransform(false, false) |
| 126 | { | 127 | { |
| 128 | + gui = NULL; | ||
| 129 | + displayBuffer = NULL; | ||
| 130 | + if (!Globals->useGui) | ||
| 131 | + return; | ||
| 132 | + displayBuffer = new QPixmap(); | ||
| 127 | // Create our GUI proxy | 133 | // Create our GUI proxy |
| 128 | gui = new GUIProxy(); | 134 | gui = new GUIProxy(); |
| 129 | // Move it to the main thread, this means signals we send to it will | 135 | // Move it to the main thread, this means signals we send to it will |
| @@ -134,16 +140,17 @@ public: | @@ -134,16 +140,17 @@ public: | ||
| 134 | connect(this, SIGNAL(updateImage(QPixmap)), gui,SLOT(showImage(QPixmap))); | 140 | connect(this, SIGNAL(updateImage(QPixmap)), gui,SLOT(showImage(QPixmap))); |
| 135 | } | 141 | } |
| 136 | 142 | ||
| 137 | - ~Show2Transform() | 143 | + ~ShowTransform() |
| 138 | { | 144 | { |
| 139 | delete gui; | 145 | delete gui; |
| 146 | + delete displayBuffer; | ||
| 140 | } | 147 | } |
| 141 | 148 | ||
| 142 | void train(const TemplateList &data) { (void) data; } | 149 | void train(const TemplateList &data) { (void) data; } |
| 143 | 150 | ||
| 144 | void project(const TemplateList &src, TemplateList &dst) const | 151 | void project(const TemplateList &src, TemplateList &dst) const |
| 145 | { | 152 | { |
| 146 | - Transform * non_const = (Show2Transform *) this; | 153 | + Transform * non_const = (ShowTransform *) this; |
| 147 | non_const->projectUpdate(src,dst); | 154 | non_const->projectUpdate(src,dst); |
| 148 | } | 155 | } |
| 149 | 156 | ||
| @@ -151,7 +158,7 @@ public: | @@ -151,7 +158,7 @@ public: | ||
| 151 | { | 158 | { |
| 152 | dst = src; | 159 | dst = src; |
| 153 | 160 | ||
| 154 | - if (src.empty()) | 161 | + if (src.empty() || !Globals->useGui) |
| 155 | return; | 162 | return; |
| 156 | 163 | ||
| 157 | foreach (const Template & t, src) { | 164 | foreach (const Template & t, src) { |
| @@ -168,12 +175,12 @@ public: | @@ -168,12 +175,12 @@ public: | ||
| 168 | 175 | ||
| 169 | foreach(const cv::Mat & m, t) { | 176 | foreach(const cv::Mat & m, t) { |
| 170 | qImageBuffer = toQImage(m); | 177 | qImageBuffer = toQImage(m); |
| 171 | - displayBuffer.convertFromImage(qImageBuffer); | 178 | + displayBuffer->convertFromImage(qImageBuffer); |
| 172 | 179 | ||
| 173 | // Emit an explicit copy of our pixmap so that the pixmap used | 180 | // Emit an explicit copy of our pixmap so that the pixmap used |
| 174 | // by the main thread isn't damaged when we update displayBuffer | 181 | // by the main thread isn't damaged when we update displayBuffer |
| 175 | // later. | 182 | // later. |
| 176 | - emit updateImage(displayBuffer.copy(displayBuffer.rect())); | 183 | + emit updateImage(displayBuffer->copy(displayBuffer->rect())); |
| 177 | 184 | ||
| 178 | // Blocking wait for a key-press | 185 | // Blocking wait for a key-press |
| 179 | if (this->waitInput) | 186 | if (this->waitInput) |
| @@ -191,6 +198,9 @@ public: | @@ -191,6 +198,9 @@ public: | ||
| 191 | 198 | ||
| 192 | void init() | 199 | void init() |
| 193 | { | 200 | { |
| 201 | + if (!Globals->useGui) | ||
| 202 | + return; | ||
| 203 | + | ||
| 194 | emit needWindow(); | 204 | emit needWindow(); |
| 195 | connect(this, SIGNAL(changeTitle(QString)), gui->window, SLOT(setWindowTitle(QString))); | 205 | connect(this, SIGNAL(changeTitle(QString)), gui->window, SLOT(setWindowTitle(QString))); |
| 196 | connect(this, SIGNAL(hideWindow()), gui->window, SLOT(hide())); | 206 | connect(this, SIGNAL(hideWindow()), gui->window, SLOT(hide())); |
| @@ -199,7 +209,7 @@ public: | @@ -199,7 +209,7 @@ public: | ||
| 199 | protected: | 209 | protected: |
| 200 | GUIProxy * gui; | 210 | GUIProxy * gui; |
| 201 | QImage qImageBuffer; | 211 | QImage qImageBuffer; |
| 202 | - QPixmap displayBuffer; | 212 | + QPixmap * displayBuffer; |
| 203 | 213 | ||
| 204 | signals: | 214 | signals: |
| 205 | void needWindow(); | 215 | void needWindow(); |
| @@ -208,7 +218,7 @@ signals: | @@ -208,7 +218,7 @@ signals: | ||
| 208 | void hideWindow(); | 218 | void hideWindow(); |
| 209 | }; | 219 | }; |
| 210 | 220 | ||
| 211 | -BR_REGISTER(Transform, Show2Transform) | 221 | +BR_REGISTER(Transform, ShowTransform) |
| 212 | 222 | ||
| 213 | class FPSSynch : public TimeVaryingTransform | 223 | class FPSSynch : public TimeVaryingTransform |
| 214 | { | 224 | { |
openbr/plugins/meta.cpp
| @@ -109,8 +109,7 @@ class PipeTransform : public CompositeTransform | @@ -109,8 +109,7 @@ class PipeTransform : public CompositeTransform | ||
| 109 | fprintf(stderr, " projecting..."); | 109 | fprintf(stderr, " projecting..."); |
| 110 | QFutureSynchronizer<void> futures; | 110 | QFutureSynchronizer<void> futures; |
| 111 | for (int j=0; j<copy.size(); j++) | 111 | for (int j=0; j<copy.size(); j++) |
| 112 | - if (Globals->parallelism) futures.addFuture(QtConcurrent::run(this, &PipeTransform::_projectPartial, ©[j], i, nextTrainableTransform)); | ||
| 113 | - else _projectPartial( ©[j], i, nextTrainableTransform); | 112 | + futures.addFuture(QtConcurrent::run(this, &PipeTransform::_projectPartial, ©[j], i, nextTrainableTransform)); |
| 114 | futures.waitForFinished(); | 113 | futures.waitForFinished(); |
| 115 | i = nextTrainableTransform; | 114 | i = nextTrainableTransform; |
| 116 | } | 115 | } |
| @@ -288,10 +287,8 @@ class ForkTransform : public CompositeTransform | @@ -288,10 +287,8 @@ class ForkTransform : public CompositeTransform | ||
| 288 | { | 287 | { |
| 289 | if (!trainable) return; | 288 | if (!trainable) return; |
| 290 | QFutureSynchronizer<void> futures; | 289 | QFutureSynchronizer<void> futures; |
| 291 | - for (int i=0; i<transforms.size(); i++) { | ||
| 292 | - if (Globals->parallelism) futures.addFuture(QtConcurrent::run(_train, transforms[i], &data)); | ||
| 293 | - else _train (transforms[i], &data); | ||
| 294 | - } | 290 | + for (int i=0; i<transforms.size(); i++) |
| 291 | + futures.addFuture(QtConcurrent::run(_train, transforms[i], &data)); | ||
| 295 | futures.waitForFinished(); | 292 | futures.waitForFinished(); |
| 296 | } | 293 | } |
| 297 | 294 |
openbr/plugins/misc.cpp
| @@ -51,46 +51,6 @@ BR_REGISTER(Transform, OpenTransform) | @@ -51,46 +51,6 @@ BR_REGISTER(Transform, OpenTransform) | ||
| 51 | 51 | ||
| 52 | /*! | 52 | /*! |
| 53 | * \ingroup transforms | 53 | * \ingroup transforms |
| 54 | - * \brief Displays templates in a GUI pop-up window. | ||
| 55 | - * \author Josh Klontz \cite jklontz | ||
| 56 | - */ | ||
| 57 | -class ShowTransform : public UntrainableMetaTransform | ||
| 58 | -{ | ||
| 59 | - Q_OBJECT | ||
| 60 | - Q_PROPERTY(bool waitKey READ get_waitKey WRITE set_waitKey RESET reset_waitKey STORED false) | ||
| 61 | - BR_PROPERTY(bool, waitKey, true) | ||
| 62 | - | ||
| 63 | - static int counter; | ||
| 64 | - int uid; | ||
| 65 | - | ||
| 66 | - void init() | ||
| 67 | - { | ||
| 68 | - uid = counter++; | ||
| 69 | - Globals->setProperty("parallelism", "0"); // Can only work in single threaded mode | ||
| 70 | - } | ||
| 71 | - | ||
| 72 | - void project(const Template &src, Template &dst) const | ||
| 73 | - { | ||
| 74 | - dst = src; | ||
| 75 | - | ||
| 76 | - if (Globals->parallelism) { | ||
| 77 | - qWarning("Show::project() only works in single threaded mode."); | ||
| 78 | - return; | ||
| 79 | - } | ||
| 80 | - | ||
| 81 | - for (int i=0; i<src.size(); i++) | ||
| 82 | - OpenCVUtils::showImage(src[i], "Show" + (counter*src.size() > 1 ? "-" + QString::number(uid*src.size()+i) : QString()), false); | ||
| 83 | - | ||
| 84 | - if (waitKey && !src.isEmpty()) cv::waitKey(-1); | ||
| 85 | - } | ||
| 86 | -}; | ||
| 87 | - | ||
| 88 | -int ShowTransform::counter = 0; | ||
| 89 | - | ||
| 90 | -BR_REGISTER(Transform, ShowTransform) | ||
| 91 | - | ||
| 92 | -/*! | ||
| 93 | - * \ingroup transforms | ||
| 94 | * \brief Prints the template's file to stdout or stderr. | 54 | * \brief Prints the template's file to stdout or stderr. |
| 95 | * \author Josh Klontz \cite jklontz | 55 | * \author Josh Klontz \cite jklontz |
| 96 | */ | 56 | */ |
| @@ -368,6 +328,8 @@ class AnonymizeTransform : public UntrainableMetaTransform | @@ -368,6 +328,8 @@ class AnonymizeTransform : public UntrainableMetaTransform | ||
| 368 | 328 | ||
| 369 | BR_REGISTER(Transform, AnonymizeTransform) | 329 | BR_REGISTER(Transform, AnonymizeTransform) |
| 370 | 330 | ||
| 331 | +// TODO: Use a global Mutex to prevent concurrent reads from stdin | ||
| 332 | +#if 0 | ||
| 371 | /*! | 333 | /*! |
| 372 | * \ingroup transforms | 334 | * \ingroup transforms |
| 373 | * \brief Name a point | 335 | * \brief Name a point |
| @@ -415,6 +377,7 @@ class ElicitMetadataTransform : public UntrainableMetaTransform | @@ -415,6 +377,7 @@ class ElicitMetadataTransform : public UntrainableMetaTransform | ||
| 415 | }; | 377 | }; |
| 416 | 378 | ||
| 417 | BR_REGISTER(Transform, ElicitMetadataTransform) | 379 | BR_REGISTER(Transform, ElicitMetadataTransform) |
| 380 | +#endif | ||
| 418 | 381 | ||
| 419 | /*! | 382 | /*! |
| 420 | * \ingroup transforms | 383 | * \ingroup transforms |
openbr/plugins/neclatent1.cpp
| @@ -18,9 +18,12 @@ class NECLatent1Initialier : public Initializer | @@ -18,9 +18,12 @@ class NECLatent1Initialier : public Initializer | ||
| 18 | 18 | ||
| 19 | void initialize() const | 19 | void initialize() const |
| 20 | { | 20 | { |
| 21 | - Globals->abbreviations.insert("NECTenprint1", "Open+Cvt(Gray)+NECLatent1Enroll:NECLatent1Compare"); | ||
| 22 | - Globals->abbreviations.insert("NECLatent1", "Open+Cvt(Gray)+NECLatent1Enroll(true):NECLatent1Compare"); | ||
| 23 | - Globals->abbreviations.insert("NECLatentLFFS1", "Open+NECLatent1Enroll(true,ELFT_M):NECLatent1Compare(ELFT_M)"); | 21 | + Globals->abbreviations.insert("NECTenprintLFML", "Open+Cvt(Gray)+NECLatent1Enroll(false,LFML):NECLatent1Compare(LFML)"); |
| 22 | + Globals->abbreviations.insert("NECTenprintELFT", "Open+Cvt(Gray)+NECLatent1Enroll(false,ELFT):NECLatent1Compare(ELFT)"); | ||
| 23 | + Globals->abbreviations.insert("NECTenprintELFTM", "Open+Cvt(Gray)+NECLatent1Enroll(false,ELFT_M):NECLatent1Compare(ELFT_M)"); | ||
| 24 | + Globals->abbreviations.insert("NECLatentLFML", "Open+Cvt(Gray)+NECLatent1Enroll(true,LFML):NECLatent1Compare(LFML)"); | ||
| 25 | + Globals->abbreviations.insert("NECLatentELFT", "Open+Cvt(Gray)+NECLatent1Enroll(true,ELFT):NECLatent1Compare(ELFT)"); | ||
| 26 | + Globals->abbreviations.insert("NECLatentELFTM", "Open+NECLatent1Enroll(true,ELFT_M):NECLatent1Compare(ELFT_M)"); | ||
| 24 | } | 27 | } |
| 25 | }; | 28 | }; |
| 26 | 29 | ||
| @@ -50,23 +53,25 @@ private: | @@ -50,23 +53,25 @@ private: | ||
| 50 | 53 | ||
| 51 | void project(const Template &src, Template &dst) const | 54 | void project(const Template &src, Template &dst) const |
| 52 | { | 55 | { |
| 56 | + static QMutex mutex; | ||
| 57 | + QMutexLocker locker(&mutex); // It seems that most of the API is not reentrant | ||
| 58 | + | ||
| 53 | if (src.m().type() != CV_8UC1) qFatal("Requires 8UC1 data!"); | 59 | if (src.m().type() != CV_8UC1) qFatal("Requires 8UC1 data!"); |
| 54 | uchar *data = src.m().data; | 60 | uchar *data = src.m().data; |
| 55 | const int rows = src.m().rows; | 61 | const int rows = src.m().rows; |
| 56 | const int columns = src.m().cols; | 62 | const int columns = src.m().cols; |
| 57 | uchar buff[MAX_TEMPLATE_SIZE]; | 63 | uchar buff[MAX_TEMPLATE_SIZE]; |
| 58 | uchar* pBuff = NULL; | 64 | uchar* pBuff = NULL; |
| 59 | - int size = 0; | ||
| 60 | - int error; | ||
| 61 | 65 | ||
| 66 | + int size, error; | ||
| 62 | if (latent) { | 67 | if (latent) { |
| 63 | if (algorithm == LFML) error = NEC_LFML_ExtractLatent(data, rows, columns, 500, buff, &size); | 68 | if (algorithm == LFML) error = NEC_LFML_ExtractLatent(data, rows, columns, 500, buff, &size); |
| 64 | - else if (algorithm == ELFT) error = NEC_ELFT_ExtractLatent(data, rows, columns, 500, 4, buff, &size); | ||
| 65 | - else error = NEC_ELFT_M_ExtractLatent(data, columns, 1, &pBuff, &size); | 69 | + else if (algorithm == ELFT) error = NEC_ELFT_ExtractLatent(data, rows, columns, 500, 32, buff, &size); |
| 70 | + else error = NEC_ELFT_M_ExtractLatent(data, columns, 5, &pBuff, &size); | ||
| 66 | } else { | 71 | } else { |
| 67 | if (algorithm == LFML) error = NEC_LFML_ExtractTenprint(data, rows, columns, 500, buff, &size); | 72 | if (algorithm == LFML) error = NEC_LFML_ExtractTenprint(data, rows, columns, 500, buff, &size); |
| 68 | - else if (algorithm == ELFT) error = NEC_ELFT_ExtractTenprint(data, rows, columns, 500, 2, buff, &size); | ||
| 69 | - else qFatal("ELFT_M Tenprint not implemented."); | 73 | + else if (algorithm == ELFT) error = NEC_ELFT_ExtractTenprint(data, rows, columns, 500, 8, buff, &size); |
| 74 | + else error = NEC_ELFT_M_ExtractTenprint(data, rows, columns, 500, 5, &pBuff, &size); | ||
| 70 | } | 75 | } |
| 71 | 76 | ||
| 72 | if (!error) { | 77 | if (!error) { |
| @@ -109,10 +114,12 @@ private: | @@ -109,10 +114,12 @@ private: | ||
| 109 | uchar *aData = a.m().data; | 114 | uchar *aData = a.m().data; |
| 110 | uchar *bData = b.m().data; | 115 | uchar *bData = b.m().data; |
| 111 | if (!a.m().data || !b.m().data) return -std::numeric_limits<float>::max(); | 116 | if (!a.m().data || !b.m().data) return -std::numeric_limits<float>::max(); |
| 112 | - int score; | ||
| 113 | - if (algorithm == LFML) NEC_LFML_Verify(bData, b.m().total(), aData, a.m().total(), &score); | ||
| 114 | - else if (algorithm == ELFT) NEC_ELFT_Verify(bData, aData, &score, 1); | ||
| 115 | - else NEC_ELFT_M_Verify(bData, aData, &score, 1); | 117 | + int score, error; |
| 118 | + if (algorithm == LFML) error = NEC_LFML_Verify(bData, b.m().total(), aData, a.m().total(), &score); | ||
| 119 | + else if (algorithm == ELFT) error = NEC_ELFT_Verify(bData, aData, &score, 1); | ||
| 120 | + else error = NEC_ELFT_M_Verify(bData, aData, &score, 1); | ||
| 121 | + if (error) | ||
| 122 | + qWarning("NECLatent1CompareDistance error %d", error); | ||
| 116 | return score; | 123 | return score; |
| 117 | } | 124 | } |
| 118 | }; | 125 | }; |
openbr/plugins/normalize.cpp
| @@ -137,11 +137,9 @@ private: | @@ -137,11 +137,9 @@ private: | ||
| 137 | } | 137 | } |
| 138 | 138 | ||
| 139 | QFutureSynchronizer<void> futures; | 139 | QFutureSynchronizer<void> futures; |
| 140 | - const bool parallel = (data.size() > 1000) && Globals->parallelism; | ||
| 141 | for (size_t c = 0; c < mv.size(); c++) { | 140 | for (size_t c = 0; c < mv.size(); c++) { |
| 142 | for (int i=0; i<dims; i++) | 141 | for (int i=0; i<dims; i++) |
| 143 | - if (parallel) futures.addFuture(QtConcurrent::run(_train, method, mv[c].col(i), labels, &av[c].at<double>(0, i), &bv[c].at<double>(0, i))); | ||
| 144 | - else _train (method, mv[c].col(i), labels, &av[c].at<double>(0, i), &bv[c].at<double>(0, i)); | 142 | + futures.addFuture(QtConcurrent::run(_train, method, mv[c].col(i), labels, &av[c].at<double>(0, i), &bv[c].at<double>(0, i))); |
| 145 | av[c] = av[c].reshape(1, data.first().m().rows); | 143 | av[c] = av[c].reshape(1, data.first().m().rows); |
| 146 | bv[c] = bv[c].reshape(1, data.first().m().rows); | 144 | bv[c] = bv[c].reshape(1, data.first().m().rows); |
| 147 | } | 145 | } |
openbr/plugins/openbr_internal.h
| @@ -221,7 +221,7 @@ public: | @@ -221,7 +221,7 @@ public: | ||
| 221 | Transform * maybe_copy = t->smartCopy(); | 221 | Transform * maybe_copy = t->smartCopy(); |
| 222 | if (maybe_copy->parent() == NULL) | 222 | if (maybe_copy->parent() == NULL) |
| 223 | maybe_copy->setParent(output); | 223 | maybe_copy->setParent(output); |
| 224 | - output->transforms.append(t->smartCopy()); | 224 | + output->transforms.append(maybe_copy); |
| 225 | } | 225 | } |
| 226 | 226 | ||
| 227 | output->file = this->file; | 227 | output->file = this->file; |
openbr/plugins/quantize.cpp
| @@ -82,8 +82,7 @@ class HistEqQuantizationTransform : public Transform | @@ -82,8 +82,7 @@ class HistEqQuantizationTransform : public Transform | ||
| 82 | 82 | ||
| 83 | QFutureSynchronizer<void> futures; | 83 | QFutureSynchronizer<void> futures; |
| 84 | for (int i=0; i<data.cols; i++) | 84 | for (int i=0; i<data.cols; i++) |
| 85 | - if (Globals->parallelism) futures.addFuture(QtConcurrent::run(&HistEqQuantizationTransform::computeThresholds, data.col(i), &thresholds.data()[i*256])); | ||
| 86 | - else computeThresholds( data.col(i), &thresholds.data()[i*256]); | 85 | + futures.addFuture(QtConcurrent::run(&HistEqQuantizationTransform::computeThresholds, data.col(i), &thresholds.data()[i*256])); |
| 87 | futures.waitForFinished(); | 86 | futures.waitForFinished(); |
| 88 | } | 87 | } |
| 89 | 88 | ||
| @@ -156,8 +155,7 @@ class BayesianQuantizationDistance : public Distance | @@ -156,8 +155,7 @@ class BayesianQuantizationDistance : public Distance | ||
| 156 | 155 | ||
| 157 | QFutureSynchronizer<void> futures; | 156 | QFutureSynchronizer<void> futures; |
| 158 | for (int i=0; i<data.cols; i++) | 157 | for (int i=0; i<data.cols; i++) |
| 159 | - if (Globals->parallelism) futures.addFuture(QtConcurrent::run(&BayesianQuantizationDistance::computeLogLikelihood, data.col(i), templateLabels, &loglikelihoods.data()[i*256])); | ||
| 160 | - else computeLogLikelihood( data.col(i), templateLabels, &loglikelihoods.data()[i*256]); | 158 | + futures.addFuture(QtConcurrent::run(&BayesianQuantizationDistance::computeLogLikelihood, data.col(i), templateLabels, &loglikelihoods.data()[i*256])); |
| 161 | futures.waitForFinished(); | 159 | futures.waitForFinished(); |
| 162 | } | 160 | } |
| 163 | 161 |
openbr/plugins/quantize2.cpp
| @@ -83,8 +83,7 @@ class BayesianQuantizationTransform : public Transform | @@ -83,8 +83,7 @@ class BayesianQuantizationTransform : public Transform | ||
| 83 | 83 | ||
| 84 | QFutureSynchronizer<void> futures; | 84 | QFutureSynchronizer<void> futures; |
| 85 | for (int i=0; i<data.cols; i++) | 85 | for (int i=0; i<data.cols; i++) |
| 86 | - if (Globals->parallelism) futures.addFuture(QtConcurrent::run(&BayesianQuantizationTransform::computeThresholds, data.col(i), labels, &thresholds.data()[i*256])); | ||
| 87 | - else computeThresholds( data.col(i), labels, &thresholds.data()[i*256]); | 86 | + futures.addFuture(QtConcurrent::run(&BayesianQuantizationTransform::computeThresholds, data.col(i), labels, &thresholds.data()[i*256])); |
| 88 | futures.waitForFinished(); | 87 | futures.waitForFinished(); |
| 89 | } | 88 | } |
| 90 | 89 |
openbr/plugins/stasm.cpp
| @@ -33,7 +33,8 @@ BR_REGISTER(Initializer, StasmInitializer) | @@ -33,7 +33,8 @@ BR_REGISTER(Initializer, StasmInitializer) | ||
| 33 | * \brief Wraps STASM key point detector | 33 | * \brief Wraps STASM key point detector |
| 34 | * \author Scott Klum \cite sklum | 34 | * \author Scott Klum \cite sklum |
| 35 | */ | 35 | */ |
| 36 | - | 36 | +// TODO: Use a global mutex to prevent concurrent calls to AsmSearchDll |
| 37 | +#if 0 | ||
| 37 | class StasmTransform : public UntrainableTransform | 38 | class StasmTransform : public UntrainableTransform |
| 38 | { | 39 | { |
| 39 | Q_OBJECT | 40 | Q_OBJECT |
| @@ -67,6 +68,7 @@ class StasmTransform : public UntrainableTransform | @@ -67,6 +68,7 @@ class StasmTransform : public UntrainableTransform | ||
| 67 | }; | 68 | }; |
| 68 | 69 | ||
| 69 | BR_REGISTER(Transform, StasmTransform) | 70 | BR_REGISTER(Transform, StasmTransform) |
| 71 | +#endif | ||
| 70 | 72 | ||
| 71 | } // namespace br | 73 | } // namespace br |
| 72 | 74 |
openbr/plugins/stream.cpp
| @@ -771,11 +771,6 @@ public: | @@ -771,11 +771,6 @@ public: | ||
| 771 | (void) src; (void) dst; | 771 | (void) src; (void) dst; |
| 772 | qFatal("nope"); | 772 | qFatal("nope"); |
| 773 | } | 773 | } |
| 774 | - void project(const TemplateList & src, TemplateList & dst) const | ||
| 775 | - { | ||
| 776 | - (void) src; (void) dst; | ||
| 777 | - qFatal("nope"); | ||
| 778 | - } | ||
| 779 | 774 | ||
| 780 | void projectUpdate(const Template &src, Template &dst) | 775 | void projectUpdate(const Template &src, Template &dst) |
| 781 | { | 776 | { |
openbr/plugins/validate.cpp
| @@ -46,8 +46,7 @@ class CrossValidateTransform : public MetaTransform | @@ -46,8 +46,7 @@ class CrossValidateTransform : public MetaTransform | ||
| 46 | if (partitions[j] == i) | 46 | if (partitions[j] == i) |
| 47 | partitionedData.removeAt(j); | 47 | partitionedData.removeAt(j); |
| 48 | // Train on the remaining templates | 48 | // Train on the remaining templates |
| 49 | - if (Globals->parallelism) futures.addFuture(QtConcurrent::run(transforms[i], &Transform::train, partitionedData)); | ||
| 50 | - else transforms[i]->train(partitionedData); | 49 | + futures.addFuture(QtConcurrent::run(transforms[i], &Transform::train, partitionedData)); |
| 51 | } | 50 | } |
| 52 | futures.waitForFinished(); | 51 | futures.waitForFinished(); |
| 53 | } | 52 | } |