diff --git a/.gitmodules b/.gitmodules index ab28352..7ffb52b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,9 +1,6 @@ [submodule "share/openbr/models"] path = share/openbr/models url = https://github.com/biometrics/openbr-models.git -[submodule "share/openbr/doc"] - path = share/openbr/doc - url = https://github.com/biometrics/openbr-doc.git [submodule "openbr/janus"] path = openbr/janus url = https://github.com/biometrics/janus.git diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index 119ab3a..0000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,45 +0,0 @@ -0.5.0 - ??/??/?? -================ - -0.4.0 - 9/17/13 -=============== -* Added simple GUI frontend -* Added -evalLandmarking and -plotLandmarking for evaluating and plotting landmarking accuracy (#9) -* Added -evalDetection and -plotDetection for evaluating and plotting object detection accuracy (#9) -* Deprecated Transform::backProject - -0.3.0 - 5/22/13 -=============== -* Added wrapper to NEC Latent SDK -* Enrolling files/folders are now sorted naturally instead of alpha numerically -* YouTubeFacesDBTransform implements Dr. Wolf's experimental protocol -* NEC3 refactored -* Updated transform API to add support for time-varying transforms per issue (#23) -* Refactored File class to improve point and rect storage (#22) -* Added algorithm to show face detection results (#25) -* Reorganized GUI code and include paths (#31) -* 'br -daemon' to listen for commands on stdin -* Generalized 'br -convert', now requires three parameters -* Official icon, thanks @sklum! - -0.2.0 - 2/23/13 -=============== -* FaceRecognition new distance metric - - 0 to 1 range indicating match probability -* Qt 4.8 -> Qt 5.0 -* Cleaner plots generated with 'br -plot' -* Stasm and FLandmark wrappers -* Improved demographic filtering speed - - br::Context::demographicFilters -> br::Context::filters - - MetadataDistance -> FilterDistance -* PipeDistance -* ImpostorUniquenessMeasureTransform -* MatchProbabilityDistance -* CrossValidation framework - - br::Context::crossValidate - - CrossValidationTransform - - CrossValidationDistance - -0.1.0 - 1/27/13 -=============== -First official release! diff --git a/CMakeLists.txt b/CMakeLists.txt index 670834a..4085264 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -176,7 +176,7 @@ foreach(DIR ${BR_THIRDPARTY_APPS_DIR}) endforeach() # Install -install(FILES CHANGELOG.md LICENSE.txt README.md DESTINATION share/openbr) +install(FILES LICENSE.txt README.md DESTINATION share/openbr) install(DIRECTORY share DESTINATION .) install(DIRECTORY ${BR_THIRDPARTY_SHARE} DESTINATION share) diff --git a/CTestConfig.cmake b/CTestConfig.cmake deleted file mode 100644 index e5935c7..0000000 --- a/CTestConfig.cmake +++ /dev/null @@ -1,12 +0,0 @@ -set(CTEST_PROJECT_NAME ${CPACK_PACKAGE_NAME}) -set(CTEST_NIGHTLY_START_TIME "00:00:00 EST") - -if(NOT DEFINED CTEST_DROP_METHOD) - set(CTEST_DROP_METHOD "http") -endif() - -if(CTEST_DROP_METHOD STREQUAL "http") - set(CTEST_DROP_SITE "my.cdash.org") - set(CTEST_DROP_LOCATION "/submit.php?project=OpenBR") - set(CTEST_DROP_SITE_CDASH TRUE) -endif(CTEST_DROP_METHOD STREQUAL "http") diff --git a/openbr/frvt2012.cpp b/openbr/frvt2012.cpp deleted file mode 100644 index 654c108..0000000 --- a/openbr/frvt2012.cpp +++ /dev/null @@ -1,146 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * Copyright 2012 The MITRE Corporation * - * * - * Licensed under the Apache License, Version 2.0 (the "License"); * - * you may not use this file except in compliance with the License. * - * You may obtain a copy of the License at * - * * - * http://www.apache.org/licenses/LICENSE-2.0 * - * * - * Unless required by applicable law or agreed to in writing, software * - * distributed under the License is distributed on an "AS IS" BASIS, * - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * - * See the License for the specific language governing permissions and * - * limitations under the License. * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -#include -#include - -#include "frvt2012.h" -#include "core/distance_sse.h" - -using namespace br; -using namespace std; - -static QSharedPointer frvt2012_transform; -static QSharedPointer frvt2012_age_transform; -static QSharedPointer frvt2012_gender_transform; -static const int frvt2012_template_size = 768; - -static void initialize(const string &configuration_location) -{ - // Fake the command line arguments - int argc = 1; - char arg1[1]; arg1[0]='\0'; - char *argv[] = { arg1 }; - - if (Globals == NULL) Context::initialize(argc, argv, QString::fromStdString(configuration_location)); - Globals->quiet = true; - Globals->parallelism = 0; -} - -static Template templateFromONEFACE(const ONEFACE &oneface) -{ - return Template(QString::fromStdString(oneface.description), - cv::Mat(oneface.image_height, oneface.image_width, oneface.image_depth == 8 ? CV_8UC1 : CV_8UC3, oneface.data)); -} - -int32_t get_pid(string &sdk_identifier, string &email_address) -{ - sdk_identifier = "1338"; - email_address = "jklontz@mitre.org"; - return 0; -} - -int32_t get_max_template_sizes(uint32_t &max_enrollment_template_size, uint32_t &max_recognition_template_size) -{ - max_enrollment_template_size = frvt2012_template_size; - max_recognition_template_size = frvt2012_template_size; - return 0; -} - -int32_t initialize_verification(string &configuration_location, vector &descriptions) -{ - (void) descriptions; - initialize(configuration_location); - frvt2012_transform = QSharedPointer(Transform::make("Cvt(RGBGray)+Cascade(FrontalFace)!!++", NULL)); - return 0; -} - -int32_t convert_multiface_to_enrollment_template(const MULTIFACE &input_faces, uint32_t &template_size, uint8_t *proprietary_template) -{ - uint8_t quality; - return convert_multiface_to_verification_template(input_faces, template_size, proprietary_template, quality); -} - -int32_t convert_multiface_to_verification_template(const MULTIFACE &input_faces, uint32_t &template_size, uint8_t* proprietary_template, uint8_t &quality) -{ - // Enroll templates - TemplateList templates; templates.reserve(input_faces.size()); - foreach (const ONEFACE &oneface, input_faces) - templates.append(templateFromONEFACE(oneface)); - templates >> *frvt2012_transform.data(); - - // Compute template size - template_size = templates.size() * frvt2012_template_size; - - // Create proprietary template - for (int i=0; i(Transform::make("Cvt(RGBGray)+Cascade(FrontalFace)!!++Discard", NULL)); - return 0; -} - -int32_t SdkEstimator::initialize_gender_estimation(const string &configuration_location) -{ - initialize(configuration_location); - frvt2012_gender_transform = QSharedPointer(Transform::make("Cvt(RGBGray)+Cascade(FrontalFace)!!++Discard", NULL)); - return 0; -} - -int32_t SdkEstimator::estimate_age(const ONEFACE &input_face, int32_t &age) -{ - TemplateList templates; - templates.append(templateFromONEFACE(input_face)); - templates >> *frvt2012_age_transform.data(); - age = templates.first().file.get("Age"); - return templates.first().file.fte ? 4 : 0; -} - -int32_t SdkEstimator::estimate_gender(const ONEFACE &input_face, int8_t &gender, double &mf) -{ - TemplateList templates; - templates.append(templateFromONEFACE(input_face)); - templates >> *frvt2012_gender_transform.data(); - mf = gender = templates.first().file.get("Gender") == "Male" ? 0 : 1; - return templates.first().file.fte ? 4 : 0; -} diff --git a/openbr/frvt2012.h b/openbr/frvt2012.h deleted file mode 100644 index 945e9a9..0000000 --- a/openbr/frvt2012.h +++ /dev/null @@ -1,416 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * Copyright 2012 The MITRE Corporation * - * * - * Licensed under the Apache License, Version 2.0 (the "License"); * - * you may not use this file except in compliance with the License. * - * You may obtain a copy of the License at * - * * - * http://www.apache.org/licenses/LICENSE-2.0 * - * * - * Unless required by applicable law or agreed to in writing, software * - * distributed under the License is distributed on an "AS IS" BASIS, * - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * - * See the License for the specific language governing permissions and * - * limitations under the License. * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -#ifndef FRVT2012_H -#define FRVT2012_H - -#include -#include -#include -#include - -/*! - * \defgroup frvt2012 FRVT 2012 - * \brief NIST Face Recognition Vendor Test 2012 API - */ - - /*! - * \addtogroup frvt2012 - * \{ - */ - -/*! - * \brief Data structure representing a single face. - */ -typedef struct sface { - uint16_t image_width; /*!< \brief Number of pixels horizontally. */ - uint16_t image_height; /*!< \brief Number of pixels vertically. */ - uint16_t image_depth; /*!< \brief Number of bits per pixel. Legal values are 8 and 24. */ - uint8_t format; /*!< \brief Flag indicating native format of the image as supplied to NIST: - - 0x01 = JPEG (i.e. compressed data) - - 0x02 = PNG (i.e. never compressed data) */ - uint8_t* data; /*!< \brief Pointer to raster scanned data. Either RGB color or intensity. - - If image_depth == 24 this points to 3WH bytes RGBRGBRGB... - - If image_depth == 8 this points to WH bytes IIIIIII */ - std::string description; /*!< \brief Single description of the image. */ -} ONEFACE; - -/*! - * \brief Data structure representing a set of images from a single person - * - * The set of face objects used to pass the image(s) and attribute(s) to - * the template extraction process. - */ -typedef std::vector MULTIFACE; - -/*! - * \brief Return the identifier and contact email address for the software under test. - * - * All implementations shall support the self-identification function below. - * This function is required to support internal NIST book-keeping. - * The version numbers should be distinct between any versions which offer - * different algorithmic functionality. - * - * \param[out] sdk_identifier - * Version ID code as hexadecimal integer printed to null terminated ASCII - * string. NIST will allocate exactly 5 bytes for this. This will be used to - * identify the SDK in the results reports. This value should be changed every - * time an SDK is submitted to NIST. The value is vendor assigned - format is - * not regulated by NIST. EXAMPLE: "011A" - * - * \param[out] email_address - * Point of contact email address as null terminated ASCII string. - * NIST will allocate at least 64 bytes for this. SDK shall not allocate. - * - * \return - * 0 Success - * Other Vendor-defined failure - */ -BR_EXPORT int32_t get_pid(std::string &sdk_identifier, - std::string &email_address); - -/*! - * \brief Return the maximum template sizes needed during feature extraction. - * - * All implementations shall report the maximum expected template sizes. - * These values will be used by the NIST test harnesses to pre-allocate template - * data. The values should apply to a single image. For a MULTIFACE containing - * K images, NIST will allocate K times the value returned. - * - * \param[out] max_enrollment_template_size - * The maximum possible size, in bytes, of the memory needed to store feature - * data from a single enrollment image. - * - * \param[out] max_recognition_template_size - * The maximum possible size, in bytes, of the memory needed to store feature - * data from a single verification or identification image. - * - * \return - * 0 Success - * Other Vendor-defined failure - */ -BR_EXPORT int32_t get_max_template_sizes(uint32_t &max_enrollment_template_size, - uint32_t &max_recognition_template_size); - -/*! - * \brief This function initializes the SDK under test. - * - * It will be called by the NIST application before any call to the functions - * convert_multiface_to_enrollment_template or - * convert_multiface_to_verification_template. - * The SDK under test should set all parameters. Before any template generation - * or matching calls are made, the NIST test harness will make a call to the - * initialization of the function. - * - * \param[in] configuration_location - * A read-only directory containing any vendor-supplied configuration parameters - * or run-time data files. The name of this directory is assigned by NIST. - * It is not hardwired by the provider. The names of the files in this directory - * are hardwired in the SDK and are unrestricted. - * - * \param[in] descriptions - * A lexicon of labels one of which will be assigned to each image. - * EXAMPLE: The descriptions could be {"mugshot", "visa", "unknown"}. - * These labels are provided to the SDK so that it knows to expect images of - * these kinds. - * - * \return - * 0 Success - * 2 Vendor provided configuration files are not readable in the - * indicated location - * 8 The descriptions are unexpected or unusable - * Other Vendor-defined failure - */ -BR_EXPORT int32_t initialize_verification(std::string &configuration_location, - std::vector &descriptions); - -/*! - * \brief This function takes a MULTIFACE, and outputs a proprietary template for enrollment. - * - * The memory for the output template is allocated by the NIST test harness - * before the call i.e. the implementation shall not allocate memory for the result. - * In all cases, even when unable to extract features, the output shall be a - * template record that may be passed to the match_templates function without - * error. That is, this routine must internally encode "template creation - * failed" and the matcher must transparently handle this. - * - * \param[in] input_faces - * An instance of a MULTIFACE structure. Implementations must alter their - * behavior according to the number of images contained in the structure. - * - * \param[in] template_size - * The size, in bytes, of the output template - * - * \param[out] proprietary_template - * The output template. The format is entirely unregulated. NIST will allocate - * a KT byte buffer for this template: The value K is the number of images in - * the MULTIFACE; the value T is output by get_max_template_sizes. - * - * \return - * 0 Success - * 2 Elective refusal to process this kind of MULTIFACE - * 4 Involuntary failure to extract features (e.g. could not find face in the - * input-image) - * 6 Elective refusal to produce a template (e.g. insufficient pixes between - * the eyes) - * 8 Cannot parse input data (i.e. assertion that input record is - * non-conformant) - * Other Vendor-defined failure. Failure codes must be documented and - * communicated to NIST with the submission of the implementation under test. - */ -BR_EXPORT int32_t convert_multiface_to_enrollment_template(const MULTIFACE &input_faces, - uint32_t &template_size, - uint8_t* proprietary_template); - -/*! - * \brief This function takes a MULTIFACE, and outputs a proprietary template for - * verification. - * - * The memory for the output template is allocated by the NIST test harness - * before the call i.e. the implementation shall not allocate memory for the - * result. In all cases, even when unable to extract features, the output shall - * be a template record that may be passed to the match_templates function - * without error. That is, this routine must internally encode "template - * creation failed" and the matcher must transparently handle this. - * - * \param[in] input_faces - * An instance of a MULTIFACE structure. Implementations must alter their - * behavior according to the number of images contained in the structure. - * - * \param[in] template_size - * The size, in bytes, of the output template - * - * \param[out] proprietary_template - * The output template. The format is entirely unregulated. NIST will allocate - * a KT byte buffer for this template: The value K is the number of images in - * the MULTIFACE; the value T is output by get_max_template_sizes. - * - * \param[out] quality - * An assessment of image quality. This is optional. The legal values are - * - [0,100] - The value should have a monotonic decreasing relationship with - * false non-match rate anticipated for this sample if it was compared with a - * pristine image of the same person. So, a low value indicates high expected - * FNMR. - * - 255 - This value indicates a failed attempt to calculate a quality score. - * - 254 - This values indicates the value was not assigned. - * - * \return - * 0 Success - * 2 Elective refusal to process this kind of MULTIFACE - * 4 Involuntary failure to extract features (e.g. could not find face in the - * input-image) - * 6 Elective refusal to produce a template (e.g. insufficient pixes between - * the eyes) - * 8 Cannot parse input data (i.e. assertion that input record is - * non-conformant) - * Other Vendor-defined failure. Failure codes must be documented and - * communicated to NIST with the submission of the implementation under test. - */ -BR_EXPORT int32_t convert_multiface_to_verification_template(const MULTIFACE &input_faces, - uint32_t &template_size, - uint8_t* proprietary_template, - uint8_t &quality); - -/*! - * \brief - * This function compares two opaque proprietary templates and outputs a - * similarity score which need not satisfy the metric properties. - * - * NIST will allocate memory for this parameter before the call. When either - * or both of the input templates are the result of a failed template - * generation, the similarity score shall be -1 and the function return value - * shall be 2. - * - * \param[in] verification_template - * A template from convert_multiface_to_verification_template(). - * - * \param[in] verification_template_size - * The size, in bytes, of the input verification template 0 <= N <= 2^32 - 1 - * - * \param[in] enrollment_template - * A template from convert_multiface_to_enrollment_template(). - * - * \param[in] enrollment_template_size - * The size, in bytes, of the input enrollment template 0 <= N <= 2^32 - 1 - * - * \param[out] similarity - * A similarity score resulting from comparison of the templates, on the - * range [0,DBL_MAX]. - * - * \return - * 0 Success - * 2 Either or both of the input templates were result of failed feature - * extraction - * Other Vendor-defined failure. - */ -BR_EXPORT int32_t match_templates(const uint8_t* verification_template, - const uint32_t verification_template_size, - const uint8_t* enrollment_template, - const uint32_t enrollment_template_size, - double &similarity); - -/*! - * \brief Class D estimator abstraction. - */ -struct BR_EXPORT Estimator { - /*!< */ - static const int NOTIMPLEMENTED = -1; - virtual ~Estimator() {} - - /*! - * Intialization functions - * - * \param[in] configuration_location - * A read-only directory containing any vendor-supplied configuration - * parameters or run-time data files. - * - * \return - * 0 Success - * 2 Elective refusal to process this kind of MULTIFACE - * 4 Involuntary failure to extract features (e.g. could not find face in - * the input-image) - * 8 Cannot parse input data (i.e. assertion that input record is - * non-conformant) - * Other Vendor-defined failure. Failure codes must be documented and - * communicated to NIST with the submission of the implementation under - * test. - */ - /*!\{*/ - virtual int32_t initialize_frontal_pose_estimation(const std::string &configuration_location) { (void) configuration_location; return NOTIMPLEMENTED; } - virtual int32_t initialize_age_estimation(const std::string &configuration_location) { (void) configuration_location; return NOTIMPLEMENTED; } - virtual int32_t initialize_gender_estimation(const std::string &configuration_location) { (void) configuration_location; return NOTIMPLEMENTED; } - virtual int32_t initialize_expression_estimation(const std::string &configuration_location) { (void) configuration_location; return NOTIMPLEMENTED; } - /*!\}*/ - - /*! - * Frontal Pose estimation function - * - * \param[in] input_face - * An instance of a ONEFACE structure. - * - * \param[out] non_frontality - * Indication of how far from frontal the head pose is. - * The value should be on the range [0,1]. - * - * \return - * 0 Success - * 2 Elective refusal to process this kind of MULTIFACE - * 4 Involuntary failure to extract features (e.g. could not find face in - * the input-image) - * 8 Cannot parse input data (i.e. assertion that input record is - * non-conformant) - * Other Vendor-defined failure. Failure codes must be documented and - * communicated to NIST with the submission of the implementation under - * test. - */ - virtual int32_t estimate_frontal_pose_conformance(const ONEFACE &input_face, double &non_frontality) { (void) input_face; (void) non_frontality; return NOTIMPLEMENTED; } - - /*! - * Age Estimation function - * - * \param[in] input_face - * An instance of a ONEFACE structure. - * - * \param[out] age - * Indication of the age (in years) of the person. - * The value should be on the range [0,100]. - * - * \return - * 0 Success - * 2 Elective refusal to process this kind of MULTIFACE - * 4 Involuntary failure to extract features (e.g. could not find face in - * the input-image) - * 8 Cannot parse input data (i.e. assertion that input record is - * non-conformant) - * Other Vendor-defined failure. Failure codes must be documented and - * communicated to NIST with the submission of the implementation under - * test. - */ - virtual int32_t estimate_age(const ONEFACE &input_face, int32_t &age) { (void) input_face; (void) age; return NOTIMPLEMENTED; } - - /*! - * Gender Estimation function - * - * \param[in] input_face - * An instance of a ONEFACE structure. - * - * \param[out] gender - * Indication of the gender of the person. Valid values are - * 0: Male - * 1: Female - * -1: Unknown - * - * \param[out] mf - * A real-valued measure of maleness-femaleness value on [0,1]. - * A value of 0 indicates certainty that the subject is a male, - * and a value of 1 indicates certainty that the subject is a female. - * - * \return - * 0 Success - * 2 Elective refusal to process this kind of MULTIFACE - * 4 Involuntary failure to extract features (e.g. could not find face - * in the input-image) - * 8 Cannot parse input data (i.e. assertion that input record is - * non-conformant) - * Other Vendor-defined failure. Failure codes must be documented and - * communicated to NIST with the submission of the implementation under test. - */ - virtual int32_t estimate_gender(const ONEFACE &input_face, int8_t &gender, double &mf) { (void) input_face; (void) gender; (void) mf; return NOTIMPLEMENTED; } - - /*! - * Expression neutrality function - * - * \param[in] input_face - * An instance of a ONEFACE structure. - * - * \param[out] expression_neutrality - * A real-valued measure of expression neutrality on [0,1] with 0 - * denoting large deviation from neutral and 1 indicating a fully - * neutral expression. - * - * \return - * 0 Success - * 2 Elective refusal to process this kind of MULTIFACE - * 4 Involuntary failure to extract features (e.g. could not find face in - * the input-image) - * 8 Cannot parse input data (i.e. assertion that input record is - * non-conformant) - * Other Vendor-defined failure. Failure codes must be documented and - * communicated to NIST with the submission of the implementation under - * test. - */ - virtual int32_t estimate_expression_neutrality(const ONEFACE &input_face, double &expression_neutrality) { (void) input_face; (void) expression_neutrality; return NOTIMPLEMENTED; } -}; - -/*! - * \brief Class D estimator implementation. - */ -struct BR_EXPORT SdkEstimator : public Estimator -{ - /*! - * \brief Implemented estimators - */ - /*!\{*/ - int32_t initialize_age_estimation(const std::string &configuration_location); - int32_t initialize_gender_estimation(const std::string &configuration_location); - int32_t estimate_age(const ONEFACE &input_face, int32_t &age); - int32_t estimate_gender(const ONEFACE &input_face, int8_t &gender, double &mf); - /*!\}*/ -}; - -/*! @}*/ - -#endif // FRVT2012_H diff --git a/openbr/openbr_export.cpp b/openbr/openbr_export.cpp deleted file mode 100644 index e69de29..0000000 --- a/openbr/openbr_export.cpp +++ /dev/null diff --git a/openbr/openbr_plugin.cpp b/openbr/openbr_plugin.cpp index 08633bb..9919cb9 100644 --- a/openbr/openbr_plugin.cpp +++ b/openbr/openbr_plugin.cpp @@ -426,7 +426,7 @@ br_utemplate Template::toUniversalTemplate(const Template &t) return br_new_utemplate(algorithmID, x, y, width, height, confidence, metadata.data(), (const char*) m.data, m.rows * m.cols * m.elemSize()); } -Template Template::fromUniversalTemplate(const br_utemplate &ut) +Template Template::fromUniversalTemplate(br_const_utemplate ut) { QVariantMap map = QJsonDocument::fromJson(QByteArray((const char*) ut->data)).object().toVariantMap(); map.insert("AlgorithmID", ut->algorithmID); @@ -435,10 +435,27 @@ Template Template::fromUniversalTemplate(const br_utemplate &ut) map.insert("Width" , ut->width ); map.insert("Height" , ut->height ); map.insert("Confidence" , ut->confidence ); - const Mat m = Mat(1, ut->fvSize, CV_8UC1, ut->data + ut->mdSize).clone(); + const Mat m = Mat(1, ut->fvSize, CV_8UC1, (void*)(ut->data + ut->mdSize)).clone(); return Template(File(map), m); } +br_utemplate Template::readUniversalTemplate(QFile &file) +{ + const size_t headerSize = sizeof(br_universal_template); + br_universal_template *t = (br_universal_template*) malloc(headerSize); + file.read((char*) t, headerSize); + + const size_t dataSize = t->mdSize + t->fvSize; + t = (br_universal_template*) realloc(t, headerSize + dataSize); + file.read((char*) &t->data, dataSize); + return t; +} + +void Template::freeUniversalTemplate(br_const_utemplate t) +{ + free((void*) t); +} + QDataStream &br::operator<<(QDataStream &stream, const Template &t) { return stream << static_cast&>(t) << t.file; diff --git a/openbr/openbr_plugin.h b/openbr/openbr_plugin.h index ac7ef5e..9bc036e 100644 --- a/openbr/openbr_plugin.h +++ b/openbr/openbr_plugin.h @@ -295,7 +295,9 @@ struct Template : public QList } static br_utemplate toUniversalTemplate(const Template &t); - static Template fromUniversalTemplate(const br_utemplate &ut); + static Template fromUniversalTemplate(br_const_utemplate ut); + static br_utemplate readUniversalTemplate(QFile &file); + static void freeUniversalTemplate(br_const_utemplate t); }; BR_EXPORT QDataStream &operator<<(QDataStream &stream, const Template &t); diff --git a/openbr/plugins/classification/lda.cpp b/openbr/plugins/classification/lda.cpp index 4fc9ff5..44917e6 100644 --- a/openbr/plugins/classification/lda.cpp +++ b/openbr/plugins/classification/lda.cpp @@ -478,6 +478,8 @@ class LDATransform : public Transform if (normalize) stdDev = sqrt(results.array().square().sum() / trainingSet.size()); } + + qDebug() << "LDA projection dimensions:" << projection.rows() << "->" << projection.cols(); } void project(const Template &src, Template &dst) const diff --git a/openbr/plugins/gallery/binary.cpp b/openbr/plugins/gallery/binary.cpp index 89bb3e3..49a982e 100644 --- a/openbr/plugins/gallery/binary.cpp +++ b/openbr/plugins/gallery/binary.cpp @@ -204,154 +204,27 @@ BR_REGISTER(Gallery, galGallery) * \brief A contiguous array of br_universal_template. * \author Josh Klontz \cite jklontz */ -class utGallery : public BinaryGallery +class tGallery : public BinaryGallery { Q_OBJECT Template readTemplate() { - Template t; - br_universal_template ut; - if (gallery.read((char*)&ut, sizeof(br_universal_template)) == sizeof(br_universal_template)) { - QByteArray data(ut.mdSize + ut.fvSize, Qt::Uninitialized); - char *dst = data.data(); - qint64 bytesNeeded = ut.mdSize + ut.fvSize; - while (bytesNeeded > 0) { - qint64 bytesRead = gallery.read(dst, bytesNeeded); - if (bytesRead <= 0) { - qDebug() << gallery.errorString(); - qFatal("Unexepected EOF while reading universal template data, needed: %d more of: %d bytes.", int(bytesNeeded), int(ut.mdSize + ut.fvSize)); - } - bytesNeeded -= bytesRead; - dst += bytesRead; - } - - t.file.set("AlgorithmID", ut.algorithmID); - t.file.set("Metadata", QString(data.data())); - char *dataStart = data.data() + ut.mdSize; - uint32_t dataSize = ut.fvSize; - if ((ut.algorithmID <= -1) && (ut.algorithmID >= -3)) { - t.file.set("FrontalFace", QRectF(ut.x, ut.y, ut.width, ut.height)); - uint32_t *rightEyeX = reinterpret_cast(dataStart); - dataStart += sizeof(uint32_t); - uint32_t *rightEyeY = reinterpret_cast(dataStart); - dataStart += sizeof(uint32_t); - uint32_t *leftEyeX = reinterpret_cast(dataStart); - dataStart += sizeof(uint32_t); - uint32_t *leftEyeY = reinterpret_cast(dataStart); - dataStart += sizeof(uint32_t); - dataSize -= sizeof(uint32_t)*4; - t.file.set("First_Eye", QPointF(*rightEyeX, *rightEyeY)); - t.file.set("Second_Eye", QPointF(*leftEyeX, *leftEyeY)); - } else if (ut.algorithmID == 7) { - // binary data consisting of a single channel matrix, of a supported type. - // 4 element header: - // uint16 datatype (single channel opencv datatype code) - // uint32 matrix rows - // uint32 matrix cols - // uint16 matrix depth (max 512) - // Followed by serialized data, in row-major order (in r/c), with depth values - // for each layer listed in order (i.e. rgb, rgb etc.) - // #### NOTE! matlab's default order is col-major, so some work should - // be done on the matlab side to make sure that the initial serialization is correct. - uint16_t dataType = *reinterpret_cast(dataStart); - dataStart += sizeof(uint16_t); - - uint32_t matrixRows = *reinterpret_cast(dataStart); - dataStart += sizeof(uint32_t); - - uint32_t matrixCols = *reinterpret_cast(dataStart); - dataStart += sizeof(uint32_t); - - uint16_t matrixDepth= *reinterpret_cast(dataStart); - dataStart += sizeof(uint16_t); - - // Set metadata - t.file.set("X", ut.x); - t.file.set("Y", ut.y); - t.file.set("Width", ut.width); - t.file.set("Height", ut.height); - t.file.set("Confidence", ut.confidence); - - t.append(cv::Mat(matrixRows, matrixCols, CV_MAKETYPE(dataType, matrixDepth), dataStart).clone() /* We don't want a shallow copy! */); - return t; - } else { - t.file.set("X", ut.x); - t.file.set("Y", ut.y); - t.file.set("Width", ut.width); - t.file.set("Height", ut.height); - t.file.set("Confidence", ut.confidence); - } - t.append(cv::Mat(1, dataSize, CV_8UC1, dataStart).clone() /* We don't want a shallow copy! */); - } else { - if (!gallery.atEnd()) - qWarning("Failed to read universal template header!"); - gallery.close(); - } + const br_const_utemplate ut = Template::readUniversalTemplate(gallery); + const Template t = Template::fromUniversalTemplate(ut); + Template::freeUniversalTemplate(ut); return t; } void writeTemplate(const Template &t) { - const int32_t algorithmID = (t.isEmpty() || t.file.fte) ? 0 : t.file.get("AlgorithmID"); - - // QUrl::fromUserInput provides some nice functionality in terms of completing URLs - // e.g. C:/test.jpg -> file://C:/test.jpg and google.com/image.jpg -> http://google.com/image.jpg - const QByteArray metadata = QUrl::fromUserInput(t.file.get("URL", t.file.name)).toEncoded(); - - int32_t x = 0, y = 0; - uint32_t width = 0, height = 0; - float confidence = 0; - QByteArray header; - if ((algorithmID <= -1) && (algorithmID >= -3)) { - const QRectF frontalFace = t.file.get("FrontalFace"); - x = frontalFace.x(); - y = frontalFace.y(); - width = frontalFace.width(); - height = frontalFace.height(); - - const QPointF firstEye = t.file.get("First_Eye"); - const QPointF secondEye = t.file.get("Second_Eye"); - const uint32_t rightEyeX = firstEye.x(); - const uint32_t rightEyeY = firstEye.y(); - const uint32_t leftEyeX = secondEye.x(); - const uint32_t leftEyeY = secondEye.y(); - - header.append((const char*)&rightEyeX, sizeof(uint32_t)); - header.append((const char*)&rightEyeY, sizeof(uint32_t)); - header.append((const char*)&leftEyeX , sizeof(uint32_t)); - header.append((const char*)&leftEyeY , sizeof(uint32_t)); - } else { - x = t.file.get("X", 0); - y = t.file.get("Y", 0); - width = t.file.get("Width", 0); - height = t.file.get("Height", 0); - confidence = t.file.get("Confidence", 0); - } - - gallery.write((const char*) &algorithmID, sizeof(int32_t)); - gallery.write((const char*) &x , sizeof(int32_t)); - gallery.write((const char*) &y , sizeof(int32_t)); - gallery.write((const char*) &width , sizeof(uint32_t)); - gallery.write((const char*) &height , sizeof(uint32_t)); - gallery.write((const char*) &confidence , sizeof(float)); - - const uint32_t mdSize = metadata.size() + 1; - gallery.write((const char*) &mdSize, sizeof(uint32_t)); - - const uint32_t signatureSize = (algorithmID == 0) ? 0 : t.m().rows * t.m().cols * t.m().elemSize(); - const uint32_t fvSize = header.size() + signatureSize; - gallery.write((const char*) &fvSize, sizeof(uint32_t)); - - gallery.write((const char*) metadata.data(), mdSize); - if (algorithmID != 0) { - gallery.write(header); - gallery.write((const char*) t.m().data, signatureSize); - } + const br_utemplate ut = Template::toUniversalTemplate(t); + gallery.write((const char*) ut, sizeof(br_universal_template) + ut->mdSize + ut->fvSize); + Template::freeUniversalTemplate(ut); } }; -BR_REGISTER(Gallery, utGallery) +BR_REGISTER(Gallery, tGallery) /*! * \ingroup galleries diff --git a/openbr/plugins/gallery/xml.cpp b/openbr/plugins/gallery/xml.cpp index cfe9dbd..4df2e00 100644 --- a/openbr/plugins/gallery/xml.cpp +++ b/openbr/plugins/gallery/xml.cpp @@ -31,7 +31,9 @@ class xmlGallery : public FileGallery { Q_OBJECT Q_PROPERTY(bool ignoreMetadata READ get_ignoreMetadata WRITE set_ignoreMetadata RESET reset_ignoreMetadata STORED false) + Q_PROPERTY(bool skipMissing READ get_skipMissing WRITE set_skipMissing RESET reset_skipMissing STORED false) BR_PROPERTY(bool, ignoreMetadata, false) + BR_PROPERTY(bool, skipMissing, false) FileList files; QXmlStreamReader reader; @@ -116,6 +118,12 @@ class xmlGallery : public FileGallery // we read another complete template count++; + + // optionally remove templates whose files don't exist or are empty + if (skipMissing && !QFileInfo(templates.last().file.resolved()).size()) { + templates.removeLast(); + count--; + } } } } diff --git a/openbr/plugins/imgproc/quantize.cpp b/openbr/plugins/imgproc/quantize.cpp index 9ae313f..fa24cef 100644 --- a/openbr/plugins/imgproc/quantize.cpp +++ b/openbr/plugins/imgproc/quantize.cpp @@ -41,6 +41,7 @@ class QuantizeTransform : public Transform minMaxLoc(OpenCVUtils::toMat(data.data()), &minVal, &maxVal); a = 255.0/(maxVal-minVal); b = -a*minVal; + qDebug() << "Quantized dimensions =" << data.first().m().rows * data.first().m().cols; } void project(const Template &src, Template &dst) const diff --git a/openbr/plugins/imgproc/synthesizekeypoints.cpp b/openbr/plugins/imgproc/synthesizekeypoints.cpp index c11cfcc..9ff68b8 100644 --- a/openbr/plugins/imgproc/synthesizekeypoints.cpp +++ b/openbr/plugins/imgproc/synthesizekeypoints.cpp @@ -155,10 +155,10 @@ class SynthesizePointsTransform : public MetadataTransform // Because not all triangulations are the same, we have to decide on a canonical set of triangles at training time. QHash counts; foreach (const Template &datum, data) { - const QList points = datum.file.points(); - if (points.size() == 0) - continue; + if (points.size() <= 4) + continue; + const QList< QList > triangulation = getTriangulation(points, getBounds(points, 10)); if (triangulation.empty()) continue; @@ -167,6 +167,9 @@ class SynthesizePointsTransform : public MetadataTransform counts[TriangleIndicies(indicies)]++; } + if (counts.empty()) + return; + triangles.clear(); QHash::const_iterator i = counts.constBegin(); while (i != counts.constEnd()) { diff --git a/openbr/plugins/metadata/selectpoints.cpp b/openbr/plugins/metadata/selectpoints.cpp index 2851acf..884fa31 100644 --- a/openbr/plugins/metadata/selectpoints.cpp +++ b/openbr/plugins/metadata/selectpoints.cpp @@ -29,8 +29,20 @@ class SelectPointsTransform : public UntrainableMetadataTransform Q_OBJECT Q_PROPERTY(QList indices READ get_indices WRITE set_indices RESET reset_indices STORED false) Q_PROPERTY(bool invert READ get_invert WRITE set_invert RESET reset_invert STORED false) // keep the points _not_ in the list + Q_PROPERTY(int rangeStart READ get_rangeStart WRITE set_rangeStart RESET reset_rangeStart STORED false) + Q_PROPERTY(int rangeEnd READ get_rangeEnd WRITE set_rangeEnd RESET reset_rangeEnd STORED false) BR_PROPERTY(QList, indices, QList()) BR_PROPERTY(bool, invert, false) + BR_PROPERTY(int, rangeStart, -1) + BR_PROPERTY(int, rangeEnd, -1) + + void init() + { + if ((rangeStart != -1) && (rangeEnd != -1)) + for (int i=rangeStart; i<=rangeEnd; i++) + if (!indices.contains(i)) + indices.append(i); + } void projectMetadata(const File &src, File &dst) const { diff --git a/share/openbr/doc b/share/openbr/doc deleted file mode 160000 index 7236a15..0000000 --- a/share/openbr/doc +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 7236a155867a161b9bf6c801e1d158250e36ebf3