diff --git a/openbr/core/common.cpp b/openbr/core/common.cpp index 55cbd3e..5f5043b 100644 --- a/openbr/core/common.cpp +++ b/openbr/core/common.cpp @@ -63,3 +63,16 @@ QList Common::RandSample(int n, const QSet &values, bool unique) } return samples; } + +QList linspace(float start, float stop, int n) { + float delta = (stop - start) / (n - 1); + float curValue = start; + QList spaced; + spaced.reserve(n); + spaced.append(start); + for (int i = 1; i < (n - 1); i++) { + spaced.append(curValue += delta); + } + spaced.append(stop); + return spaced; +} diff --git a/openbr/core/common.h b/openbr/core/common.h index bd0b603..15516d0 100644 --- a/openbr/core/common.h +++ b/openbr/core/common.h @@ -253,6 +253,11 @@ QList RandSample(int n, const QList &weights, bool unique = false) } /*! + * \brief See Matlab function linspace() for documentation. + */ +QList linspace(float start, float stop, int n); + +/*! * \brief See Matlab function unique() for documentation. */ template diff --git a/openbr/openbr_plugin.cpp b/openbr/openbr_plugin.cpp index d4df6d1..80f0559 100644 --- a/openbr/openbr_plugin.cpp +++ b/openbr/openbr_plugin.cpp @@ -44,12 +44,6 @@ using namespace cv; Q_DECLARE_METATYPE(QLocalSocket::LocalSocketState) -// Some globals used to transfer data to Context::messageHandler so that -// we can restart the process if we try and fail to create a QApplication. -static bool creating_qapp = false; -static int * argc_ptr = NULL; -static char ** argv_ptr = NULL; - /* File - public methods */ // Note that the convention for displaying metadata is as follows: // [] for lists in which argument order does not matter (e.g. [FTO=false, Index=0]), @@ -848,13 +842,7 @@ int br::Context::blocks(int size) const bool br::Context::contains(const QString &name) { - QByteArray bytes = name.toLocal8Bit(); - const char * c_name = bytes.constData(); - - for (int i=0; ipropertyCount(); i++) - if (!strcmp(c_name, metaObject()->property(i).name())) - return true; - return false; + return property(qPrintable(name)).isValid(); } void br::Context::printStatus() @@ -907,42 +895,26 @@ bool br::Context::checkSDKPath(const QString &sdkPath) // We create our own when the user hasn't static QCoreApplication *application = NULL; -void br::Context::initialize(int &argc, char *argv[], QString sdkPath, bool use_gui) +void br::Context::initialize(int &argc, char *argv[], QString sdkPath, bool useGui) { - for (int i=0; i < argc; i ++) - { - if (strcmp("-useGui", argv[i]) == 0) { - const char * val = i+1 < argc ? argv[i+1] : ""; - if (strcmp(val, "false") ==0 || strcmp(val, "0") == 0) - use_gui = false; - break; - } - } - qInstallMessageHandler(messageHandler); +#ifndef _WIN32 + useGui = useGui && (getenv("DISPLAY") != NULL); +#endif // not _WIN32 + // We take in argc as a reference due to: // https://bugreports.qt-project.org/browse/QTBUG-5637 // QApplication should be initialized before anything else. // Since we can't ensure that it gets deleted last, we never delete it. if (QCoreApplication::instance() == NULL) { #ifndef BR_EMBEDDED - if (use_gui) { - // Set up variables to be used in the message handler if this fails. - // Just so you know, we - creating_qapp = true; - argc_ptr = &argc; - argv_ptr = argv; - - application = new QApplication(argc, argv); - creating_qapp = false; - } - else { - application = new QCoreApplication(argc, argv); - } -#else + if (useGui) application = new QApplication(argc, argv); + else application = new QCoreApplication(argc, argv); +#else // not BR_EMBEDDED + useGui = false; application = new QCoreApplication(argc, argv); -#endif +#endif // BR_EMBEDDED } QCoreApplication::setOrganizationName(COMPANY_NAME); @@ -965,8 +937,7 @@ void br::Context::initialize(int &argc, char *argv[], QString sdkPath, bool use_ Globals = new Context(); Globals->init(File()); - Globals->useGui = use_gui; - + Globals->useGui = useGui; Common::seedRNG(); @@ -1035,26 +1006,6 @@ void br::Context::messageHandler(QtMsgType type, const QMessageLogContext &conte static QMutex generalLock; QMutexLocker locker(&generalLock); - // If we are trying to create a QApplication, and get a fatal, then restart the process - // with useGui set to 0. - if (creating_qapp && type == QtFatalMsg) - { - // re-launch process with useGui = 0 - std::cout << "Failed to initialize gui, restarting with -useGui 0" << std::endl; - QStringList arguments; - arguments.append("-useGui"); - arguments.append("0"); - for (int i=1; i < *argc_ptr; i++) - { - arguments.append(argv_ptr[i]); - } - // QProcess::execute blocks until the other process completes. - QProcess::execute(argv_ptr[0], arguments); - // have to unlock this for some reason - locker.unlock(); - std::exit(0); - } - QString txt; if (type == QtDebugMsg) { if (Globals->quiet) return; @@ -1076,8 +1027,13 @@ void br::Context::messageHandler(QtMsgType type, const QMessageLogContext &conte Globals->logFile.flush(); } - if (type == QtFatalMsg) + if (type == QtFatalMsg) { +#ifdef _WIN32 + QCoreApplication::quit(); // abort() hangs the console on Windows for some reason related to the event loop not being exited +#else // not _WIN32 abort(); // We abort so we can get a stack trace back to the code that triggered the message. +#endif // _WIN32 + } } Context *br::Globals = NULL; diff --git a/openbr/openbr_plugin.h b/openbr/openbr_plugin.h index d74d87e..d50a183 100644 --- a/openbr/openbr_plugin.h +++ b/openbr/openbr_plugin.h @@ -794,12 +794,12 @@ public: * By default share/openbr/openbr.bib will be searched for relative to: * -# The working directory * -# The executable's location - * \param use_gui Create a QApplication instead of a QCoreApplication. + * \param useGui Create a QApplication instead of a QCoreApplication. * \note Tiggers \em abort() on failure to locate share/openbr/openbr.bib. * \note Qt users should instead call this after initializing QApplication. * \see finalize */ - static void initialize(int &argc, char *argv[], QString sdkPath = "", bool use_gui = true); + static void initialize(int &argc, char *argv[], QString sdkPath = "", bool useGui = true); /*! * \brief Call \em once at the end of the application to deallocate global variables. diff --git a/openbr/plugins/draw.cpp b/openbr/plugins/draw.cpp index 3057b8a..0a63e8c 100644 --- a/openbr/plugins/draw.cpp +++ b/openbr/plugins/draw.cpp @@ -40,10 +40,12 @@ class DrawTransform : public UntrainableTransform Q_PROPERTY(bool points READ get_points WRITE set_points RESET reset_points STORED false) Q_PROPERTY(bool rects READ get_rects WRITE set_rects RESET reset_rects STORED false) Q_PROPERTY(bool inPlace READ get_inPlace WRITE set_inPlace RESET reset_inPlace STORED false) + Q_PROPERTY(int lineThickness READ get_lineThickness WRITE set_lineThickness RESET reset_lineThickness STORED false) BR_PROPERTY(bool, verbose, false) BR_PROPERTY(bool, points, true) BR_PROPERTY(bool, rects, true) BR_PROPERTY(bool, inPlace, false) + BR_PROPERTY(int, lineThickness, 1) void project(const Template &src, Template &dst) const { @@ -61,7 +63,7 @@ class DrawTransform : public UntrainableTransform } if (rects) { foreach (const Rect &rect, OpenCVUtils::toRects(src.file.namedRects() + src.file.rects())) - rectangle(dst, rect, color); + rectangle(dst, rect, color, lineThickness); } } }; diff --git a/openbr/plugins/eigen3.cpp b/openbr/plugins/eigen3.cpp index d7ed624..710570e 100644 --- a/openbr/plugins/eigen3.cpp +++ b/openbr/plugins/eigen3.cpp @@ -302,8 +302,8 @@ class LDATransform : public Transform Q_PROPERTY(int directLDA READ get_directLDA WRITE set_directLDA RESET reset_directLDA STORED false) Q_PROPERTY(float directDrop READ get_directDrop WRITE set_directDrop RESET reset_directDrop STORED false) Q_PROPERTY(QString inputVariable READ get_inputVariable WRITE set_inputVariable RESET reset_inputVariable STORED false) - Q_PROPERTY(bool isBinary READ get_isBinary WRITE set_isBinary RESET reset_isBinary STORED true) - Q_PROPERTY(bool normalize READ get_normalize WRITE set_normalize RESET reset_normalize STORED true) + Q_PROPERTY(bool isBinary READ get_isBinary WRITE set_isBinary RESET reset_isBinary STORED false) + Q_PROPERTY(bool normalize READ get_normalize WRITE set_normalize RESET reset_normalize STORED false) BR_PROPERTY(float, pcaKeep, 0.98) BR_PROPERTY(bool, pcaWhiten, false) BR_PROPERTY(int, directLDA, 0) @@ -316,12 +316,6 @@ class LDATransform : public Transform Eigen::VectorXf mean; Eigen::MatrixXf projection; float stdDev; - bool trained; - - void init() - { - trained = false; - } void train(const TemplateList &_trainingSet) { @@ -461,9 +455,9 @@ class LDATransform : public Transform projection = ((space2.eVecs.transpose() * space1.eVecs.transpose()) * pca.eVecs.transpose()).transpose(); dimsOut = dim2; + stdDev = 1; // default initialize if (isBinary) { assert(dimsOut == 1); - TemplateList projected; float posVal = 0; float negVal = 0; Eigen::MatrixXf results(trainingSet.size(),1); @@ -493,8 +487,6 @@ class LDATransform : public Transform if (normalize) stdDev = sqrt(results.array().square().sum() / trainingSet.size()); } - - trained = true; } void project(const Template &src, Template &dst) const @@ -508,18 +500,22 @@ class LDATransform : public Transform // Do projection outMap = projection.transpose() * (inMap - mean); - if (normalize && isBinary && trained) + if (normalize && isBinary) dst.m().at(0,0) = dst.m().at(0,0) / stdDev; } void store(QDataStream &stream) const { - stream << pcaKeep << directLDA << directDrop << dimsOut << mean << projection << stdDev << normalize << isBinary << trained; + stream << pcaKeep << directLDA << directDrop << dimsOut << mean << projection; + if (normalize && isBinary) + stream << stdDev; } void load(QDataStream &stream) { - stream >> pcaKeep >> directLDA >> directDrop >> dimsOut >> mean >> projection >> stdDev >> normalize >> isBinary >> trained; + stream >> pcaKeep >> directLDA >> directDrop >> dimsOut >> mean >> projection; + if (normalize && isBinary) + stream >> stdDev; } }; diff --git a/openbr/plugins/process.cpp b/openbr/plugins/process.cpp index d5c687b..cde5d87 100644 --- a/openbr/plugins/process.cpp +++ b/openbr/plugins/process.cpp @@ -531,8 +531,6 @@ class ProcessWrapperTransform : public TimeVaryingTransform baseKey = id.toString(); QStringList argumentList; - argumentList.append("-useGui"); - argumentList.append("0"); argumentList.append("-algorithm"); argumentList.append(transform); if (!Globals->path.isEmpty()) { diff --git a/openbr/plugins/stream.cpp b/openbr/plugins/stream.cpp index 440ab1c..75ce93f 100644 --- a/openbr/plugins/stream.cpp +++ b/openbr/plugins/stream.cpp @@ -1079,8 +1079,7 @@ public: // Wait for the stream to process the last frame available from // the data source. - bool wait_res = false; - wait_res = readStage->dataSource.waitLast(); + readStage->dataSource.waitLast(); // Now that there are no more incoming frames, call finalize // on each transform in turn to collect any last templates diff --git a/scripts/evalAgeRegression-PCSO.sh b/scripts/evalAgeRegression-PCSO.sh index 9e294fe..2f06c67 100755 --- a/scripts/evalAgeRegression-PCSO.sh +++ b/scripts/evalAgeRegression-PCSO.sh @@ -4,7 +4,7 @@ if [ ! -f evalAgeRegression-PCSO.sh ]; then exit fi -export BR="../build/app/br/br -useGui 0" +export BR=../build/app/br/br export PCSO_DIR=/user/pripshare/Databases/FaceDatabases/PCSO/PCSO/ export ageAlg=AgeRegression diff --git a/scripts/evalFaceRecognition-LFW.sh b/scripts/evalFaceRecognition-LFW.sh index 4f0e6c4..53e5636 100755 --- a/scripts/evalFaceRecognition-LFW.sh +++ b/scripts/evalFaceRecognition-LFW.sh @@ -20,7 +20,7 @@ if [ ! -e Algorithm_Dataset ]; then fi # Run the LFW test protocol -br -useGui 0 -algorithm $ALGORITHM -path ../data/LFW/img/ -crossValidate 10 -pairwiseCompare ../data/LFW/sigset/test_image_restricted_target.xml ../data/LFW/sigset/test_image_restricted_query.xml ${ALGORITHM}_LFW.mtx -convert Output ${ALGORITHM}_lfw.mtx Algorithm_Dataset/${ALGORITHM}_LFW%1.eval +br -algorithm $ALGORITHM -path ../data/LFW/img/ -crossValidate 10 -pairwiseCompare ../data/LFW/sigset/test_image_restricted_target.xml ../data/LFW/sigset/test_image_restricted_query.xml ${ALGORITHM}_LFW.mtx -convert Output ${ALGORITHM}_lfw.mtx Algorithm_Dataset/${ALGORITHM}_LFW%1.eval # Plot results -br -useGui 0 -plot Algorithm_Dataset/* 'lfw_results.pdf[smooth=Dataset,rocOptions[yLimits=(0,1)]]' +br -plot Algorithm_Dataset/* 'lfw_results.pdf[smooth=Dataset,rocOptions[yLimits=(0,1)]]' diff --git a/scripts/evalFaceRecognition-MEDS.sh b/scripts/evalFaceRecognition-MEDS.sh index 673f674..231370f 100755 --- a/scripts/evalFaceRecognition-MEDS.sh +++ b/scripts/evalFaceRecognition-MEDS.sh @@ -20,11 +20,11 @@ if [ ! -e Algorithm_Dataset ]; then fi if [ ! -e MEDS.mask ]; then - br -useGui 0 -makeMask ../data/MEDS/sigset/MEDS_frontal_target.xml ../data/MEDS/sigset/MEDS_frontal_query.xml MEDS.mask + br -makeMask ../data/MEDS/sigset/MEDS_frontal_target.xml ../data/MEDS/sigset/MEDS_frontal_query.xml MEDS.mask fi # Run Algorithm on MEDS -br -useGui 0 -algorithm ${ALGORITHM} -path ../data/MEDS/img -compare ../data/MEDS/sigset/MEDS_frontal_target.xml ../data/MEDS/sigset/MEDS_frontal_query.xml ${ALGORITHM}_MEDS.mtx -eval ${ALGORITHM}_MEDS.mtx MEDS.mask Algorithm_Dataset/${ALGORITHM}_MEDS.csv +br -algorithm ${ALGORITHM} -path ../data/MEDS/img -compare ../data/MEDS/sigset/MEDS_frontal_target.xml ../data/MEDS/sigset/MEDS_frontal_query.xml ${ALGORITHM}_MEDS.mtx -eval ${ALGORITHM}_MEDS.mtx MEDS.mask Algorithm_Dataset/${ALGORITHM}_MEDS.csv # Plot results -br -useGui 0 -plot Algorithm_Dataset/*_MEDS.csv MEDS +br -plot Algorithm_Dataset/*_MEDS.csv MEDS diff --git a/scripts/evalGenderClassification-PCSO.sh b/scripts/evalGenderClassification-PCSO.sh index d8afbbb..b68315e 100755 --- a/scripts/evalGenderClassification-PCSO.sh +++ b/scripts/evalGenderClassification-PCSO.sh @@ -9,7 +9,7 @@ export ALGORITHM=GenderClassification export PCSO_DIR=../data/PCSO/img # Create a file list by querying the database -$BR -useGui 0 -quiet -algorithm Identity -enroll "$PCSO_DIR/PCSO.db[query='SELECT File,Gender,PersonID FROM PCSO', subset=1:8000]" terminal.txt > Input.txt +$BR -quiet -algorithm Identity -enroll "$PCSO_DIR/PCSO.db[query='SELECT File,Gender,PersonID FROM PCSO', subset=1:8000]" terminal.txt > Input.txt # Enroll the file list and evaluate performance -$BR -useGui 0 -algorithm $ALGORITHM -path $PCSO_DIR -enroll Input.txt Output.txt -evalClassification Output.txt Input.txt Gender \ No newline at end of file +$BR -algorithm $ALGORITHM -path $PCSO_DIR -enroll Input.txt Output.txt -evalClassification Output.txt Input.txt Gender \ No newline at end of file diff --git a/scripts/pedestrianBaselineLBP.sh b/scripts/pedestrianBaselineLBP.sh index 1ecbffe..2e02790 100755 --- a/scripts/pedestrianBaselineLBP.sh +++ b/scripts/pedestrianBaselineLBP.sh @@ -27,8 +27,7 @@ else TEST=testSmall.xml fi -br -useGui 0 \ - -algorithm "${ALG}" \ +br -algorithm "${ALG}" \ -path $INRIA_PATH/img \ -train $INRIA_PATH/sigset/train.xml pedModel \ -enroll $INRIA_PATH/sigset/$TEST pedResults.xml diff --git a/scripts/trainAgeRegression-PCSO.sh b/scripts/trainAgeRegression-PCSO.sh index c1f3ef1..4c30f10 100755 --- a/scripts/trainAgeRegression-PCSO.sh +++ b/scripts/trainAgeRegression-PCSO.sh @@ -13,4 +13,4 @@ export ageAlg=AgeRegression export PCSO_DIR=/user/pripshare/Databases/FaceDatabases/PCSO/PCSO/ -$BR -useGui 0 -algorithm $ageAlg -path $PCSO_DIR/Images -train "$PCSO_DIR/PCSO.db[query='SELECT File,Age,PersonID FROM PCSO WHERE Age >= 17 AND AGE <= 68', subset=0:200]" ../share/openbr/models/algorithms/AgeRegression +$BR -algorithm $ageAlg -path $PCSO_DIR/Images -train "$PCSO_DIR/PCSO.db[query='SELECT File,Age,PersonID FROM PCSO WHERE Age >= 17 AND AGE <= 68', subset=0:200]" ../share/openbr/models/algorithms/AgeRegression diff --git a/scripts/trainFaceRecognition-PCSO.sh b/scripts/trainFaceRecognition-PCSO.sh index ebeb056..1ef1153 100755 --- a/scripts/trainFaceRecognition-PCSO.sh +++ b/scripts/trainFaceRecognition-PCSO.sh @@ -14,7 +14,5 @@ export BR=../build/app/br/br export PCSO_DIR=/user/pripshare/Databases/FaceDatabases/PCSO/PCSO/ - - -$BR -useGui 0 -algorithm FaceRecognition -path "$PCSO_DIR/Images/" -train "$PCSO_DIR/PCSO.db[query='SELECT File,PersonID as Label,PersonID FROM PCSO', subset=0:5:6000]" ../share/openbr/models/algorithms/FaceRecognition +$BR -algorithm FaceRecognition -path "$PCSO_DIR/Images/" -train "$PCSO_DIR/PCSO.db[query='SELECT File,PersonID as Label,PersonID FROM PCSO', subset=0:5:6000]" ../share/openbr/models/algorithms/FaceRecognition diff --git a/scripts/trainGenderClassification-PCSO.sh b/scripts/trainGenderClassification-PCSO.sh index acb8146..8875fc9 100755 --- a/scripts/trainGenderClassification-PCSO.sh +++ b/scripts/trainGenderClassification-PCSO.sh @@ -13,4 +13,4 @@ export genderAlg=GenderClassification export PCSO_DIR=/user/pripshare/Databases/FaceDatabases/PCSO/PCSO/ -$BR -useGui 0 -algorithm $genderAlg -path $PCSO_DIR/Images -train "$PCSO_DIR/PCSO.db[query='SELECT File,Gender,PersonID FROM PCSO', subset=0:8000]" ../share/openbr/models/algorithms/GenderClassification +$BR -algorithm $genderAlg -path $PCSO_DIR/Images -train "$PCSO_DIR/PCSO.db[query='SELECT File,Gender,PersonID FROM PCSO', subset=0:8000]" ../share/openbr/models/algorithms/GenderClassification diff --git a/share/openbr/cmake/OpenBRConfig.cmake b/share/openbr/cmake/OpenBRConfig.cmake index f844cfe..03c59fc 100644 --- a/share/openbr/cmake/OpenBRConfig.cmake +++ b/share/openbr/cmake/OpenBRConfig.cmake @@ -8,6 +8,7 @@ # target_link_libraries(MY_TARGET_NAME ${OPENBR_LIBS}) # ================================================================ +string(REPLACE "/share/openbr/cmake" "" OPENBR_DIR ${OPENBR_DIR}) include_directories(${OPENBR_DIR}/include) link_directories(${OPENBR_DIR}/lib) set(OPENBR_LIBS "openbr")