Commit ef45e04258bf85a32079e832cff7178be09a0e4e
Merge branch 'master' of https://github.com/biometrics/openbr
Showing
4 changed files
with
66 additions
and
67 deletions
openbr/core/bee.cpp
| @@ -172,6 +172,8 @@ Mat BEE::readMat(const br::File &matrix, QString *targetSigset, QString *querySi | @@ -172,6 +172,8 @@ Mat BEE::readMat(const br::File &matrix, QString *targetSigset, QString *querySi | ||
| 172 | qint64 read = file.read((char*)m.data, bytesExpected); | 172 | qint64 read = file.read((char*)m.data, bytesExpected); |
| 173 | if (read != bytesExpected) | 173 | if (read != bytesExpected) |
| 174 | qFatal("Invalid matrix size."); | 174 | qFatal("Invalid matrix size."); |
| 175 | + if (!file.atEnd()) | ||
| 176 | + qFatal("Expected matrix end of file."); | ||
| 175 | file.close(); | 177 | file.close(); |
| 176 | 178 | ||
| 177 | Mat result; | 179 | Mat result; |
openbr/janus.cpp
| @@ -3,30 +3,42 @@ | @@ -3,30 +3,42 @@ | ||
| 3 | #endif | 3 | #endif |
| 4 | 4 | ||
| 5 | #include "janus.h" | 5 | #include "janus.h" |
| 6 | +#include "janus_io.h" | ||
| 6 | #include "openbr_plugin.h" | 7 | #include "openbr_plugin.h" |
| 7 | 8 | ||
| 8 | -// Use the provided default implementation of some functions | ||
| 9 | -#include "janus/src/janus.cpp" | ||
| 10 | - | ||
| 11 | using namespace br; | 9 | using namespace br; |
| 12 | 10 | ||
| 13 | static QSharedPointer<Transform> transform; | 11 | static QSharedPointer<Transform> transform; |
| 14 | static QSharedPointer<Distance> distance; | 12 | static QSharedPointer<Distance> distance; |
| 15 | 13 | ||
| 14 | +size_t janus_max_template_size() | ||
| 15 | +{ | ||
| 16 | + return JANUS_MAX_TEMPLATE_SIZE_LIMIT; | ||
| 17 | +} | ||
| 18 | + | ||
| 16 | janus_error janus_initialize(const char *sdk_path, const char *model_file) | 19 | janus_error janus_initialize(const char *sdk_path, const char *model_file) |
| 17 | { | 20 | { |
| 18 | int argc = 1; | 21 | int argc = 1; |
| 19 | const char *argv[1] = { "janus" }; | 22 | const char *argv[1] = { "janus" }; |
| 20 | Context::initialize(argc, (char**)argv, sdk_path); | 23 | Context::initialize(argc, (char**)argv, sdk_path); |
| 21 | QString algorithm = model_file; | 24 | QString algorithm = model_file; |
| 22 | - if (algorithm.isEmpty()) algorithm = "Cvt(Gray)+Affine(88,88,0.25,0.35)+<FaceRecognitionExtraction>+<FaceRecognitionEmbedding>+<FaceRecognitionQuantization>:ByteL1"; | ||
| 23 | - transform = Transform::fromAlgorithm(algorithm, false); | ||
| 24 | - distance = Distance::fromAlgorithm(algorithm); | 25 | + if (algorithm.isEmpty()) { |
| 26 | + transform = Transform::fromAlgorithm("Cvt(Gray)+Affine(88,88,0.25,0.35)+<FaceRecognitionExtraction>+<FaceRecognitionEmbedding>+<FaceRecognitionQuantization>", false); | ||
| 27 | + distance = Distance::fromAlgorithm("FaceRecognition"); | ||
| 28 | + } else if (algorithm == "PP5") { | ||
| 29 | + transform.reset(Transform::make("PP5Enroll", NULL)); | ||
| 30 | + distance.reset(Distance::make("PP5Compare", NULL)); | ||
| 31 | + } else { | ||
| 32 | + transform = Transform::fromAlgorithm(algorithm, false); | ||
| 33 | + distance = Distance::fromAlgorithm(algorithm); | ||
| 34 | + } | ||
| 25 | return JANUS_SUCCESS; | 35 | return JANUS_SUCCESS; |
| 26 | } | 36 | } |
| 27 | 37 | ||
| 28 | janus_error janus_finalize() | 38 | janus_error janus_finalize() |
| 29 | { | 39 | { |
| 40 | + transform.reset(); | ||
| 41 | + distance.reset(); | ||
| 30 | Context::finalize(); | 42 | Context::finalize(); |
| 31 | return JANUS_SUCCESS; | 43 | return JANUS_SUCCESS; |
| 32 | } | 44 | } |
| @@ -40,24 +52,24 @@ janus_error janus_initialize_template(janus_template *template_) | @@ -40,24 +52,24 @@ janus_error janus_initialize_template(janus_template *template_) | ||
| 40 | return JANUS_SUCCESS; | 52 | return JANUS_SUCCESS; |
| 41 | } | 53 | } |
| 42 | 54 | ||
| 43 | -janus_error janus_add_image(const janus_image image, const janus_attribute_list attributes, janus_template template_) | 55 | +janus_error janus_augment(const janus_image image, const janus_attribute_list attributes, janus_template template_) |
| 44 | { | 56 | { |
| 45 | Template t; | 57 | Template t; |
| 46 | t.append(cv::Mat(image.height, | 58 | t.append(cv::Mat(image.height, |
| 47 | image.width, | 59 | image.width, |
| 48 | - image.color_space == JANUS_GRAY8 ? CV_8UC1 : CV_8UC1, | 60 | + image.color_space == JANUS_GRAY8 ? CV_8UC1 : CV_8UC3, |
| 49 | image.data)); | 61 | image.data)); |
| 50 | for (size_t i=0; i<attributes.size; i++) | 62 | for (size_t i=0; i<attributes.size; i++) |
| 51 | t.file.set(janus_attribute_to_string(attributes.attributes[i]), attributes.values[i]); | 63 | t.file.set(janus_attribute_to_string(attributes.attributes[i]), attributes.values[i]); |
| 52 | 64 | ||
| 53 | - if (!t.file.contains("JANUS_RIGHT_EYE_X") || | ||
| 54 | - !t.file.contains("JANUS_RIGHT_EYE_Y") || | ||
| 55 | - !t.file.contains("JANUS_LEFT_EYE_X") || | ||
| 56 | - !t.file.contains("JANUS_LEFT_EYE_Y")) | 65 | + if (!t.file.contains("RIGHT_EYE_X") || |
| 66 | + !t.file.contains("RIGHT_EYE_Y") || | ||
| 67 | + !t.file.contains("LEFT_EYE_X") || | ||
| 68 | + !t.file.contains("LEFT_EYE_Y")) | ||
| 57 | return JANUS_SUCCESS; | 69 | return JANUS_SUCCESS; |
| 58 | 70 | ||
| 59 | - t.file.set("Affine_0", QPointF(t.file.get<float>("JANUS_RIGHT_EYE_X"), t.file.get<float>("JANUS_RIGHT_EYE_Y"))); | ||
| 60 | - t.file.set("Affine_1", QPointF(t.file.get<float>("JANUS_LEFT_EYE_X"), t.file.get<float>("JANUS_LEFT_EYE_Y"))); | 71 | + t.file.set("Affine_0", QPointF(t.file.get<float>("RIGHT_EYE_X"), t.file.get<float>("RIGHT_EYE_Y"))); |
| 72 | + t.file.set("Affine_1", QPointF(t.file.get<float>("LEFT_EYE_X"), t.file.get<float>("LEFT_EYE_Y"))); | ||
| 61 | Template u; | 73 | Template u; |
| 62 | transform->project(t, u); | 74 | transform->project(t, u); |
| 63 | template_->append(u); | 75 | template_->append(u); |
| @@ -66,78 +78,63 @@ janus_error janus_add_image(const janus_image image, const janus_attribute_list | @@ -66,78 +78,63 @@ janus_error janus_add_image(const janus_image image, const janus_attribute_list | ||
| 66 | 78 | ||
| 67 | janus_error janus_finalize_template(janus_template template_, janus_flat_template flat_template, size_t *bytes) | 79 | janus_error janus_finalize_template(janus_template template_, janus_flat_template flat_template, size_t *bytes) |
| 68 | { | 80 | { |
| 69 | - size_t templateBytes = 0; | ||
| 70 | - size_t numTemplates = 0; | ||
| 71 | - *bytes = sizeof(templateBytes) + sizeof(numTemplates); | ||
| 72 | - janus_flat_template pos = flat_template + *bytes; | ||
| 73 | - | ||
| 74 | foreach (const cv::Mat &m, *template_) { | 81 | foreach (const cv::Mat &m, *template_) { |
| 75 | assert(m.isContinuous()); | 82 | assert(m.isContinuous()); |
| 76 | - const size_t currentTemplateBytes = m.rows * m.cols * m.elemSize(); | ||
| 77 | - if (templateBytes == 0) | ||
| 78 | - templateBytes = currentTemplateBytes; | ||
| 79 | - if (templateBytes != currentTemplateBytes) | ||
| 80 | - return JANUS_UNKNOWN_ERROR; | ||
| 81 | - if (*bytes + templateBytes > janus_max_template_size()) | 83 | + const size_t templateBytes = m.rows * m.cols * m.elemSize(); |
| 84 | + if (*bytes + sizeof(size_t) + templateBytes > janus_max_template_size()) | ||
| 82 | break; | 85 | break; |
| 83 | - memcpy(pos, m.data, templateBytes); | ||
| 84 | - *bytes += templateBytes; | ||
| 85 | - pos = pos + templateBytes; | ||
| 86 | - numTemplates++; | 86 | + memcpy(flat_template, &templateBytes, sizeof(templateBytes)); |
| 87 | + flat_template += sizeof(templateBytes); | ||
| 88 | + memcpy(flat_template, m.data, templateBytes); | ||
| 89 | + flat_template += templateBytes; | ||
| 90 | + *bytes += sizeof(size_t) + templateBytes; | ||
| 87 | } | 91 | } |
| 88 | 92 | ||
| 89 | - *(reinterpret_cast<size_t*>(flat_template)+0) = templateBytes; | ||
| 90 | - *(reinterpret_cast<size_t*>(flat_template)+1) = numTemplates; | ||
| 91 | delete template_; | 93 | delete template_; |
| 92 | return JANUS_SUCCESS; | 94 | return JANUS_SUCCESS; |
| 93 | } | 95 | } |
| 94 | 96 | ||
| 95 | janus_error janus_verify(const janus_flat_template a, const size_t a_bytes, const janus_flat_template b, const size_t b_bytes, double *similarity) | 97 | janus_error janus_verify(const janus_flat_template a, const size_t a_bytes, const janus_flat_template b, const size_t b_bytes, double *similarity) |
| 96 | { | 98 | { |
| 97 | - (void) a_bytes; | ||
| 98 | - (void) b_bytes; | ||
| 99 | - | ||
| 100 | - size_t a_template_bytes, a_templates, b_template_bytes, b_templates; | ||
| 101 | - a_template_bytes = *(reinterpret_cast<size_t*>(a)+0); | ||
| 102 | - a_templates = *(reinterpret_cast<size_t*>(a)+1); | ||
| 103 | - b_template_bytes = *(reinterpret_cast<size_t*>(b)+0); | ||
| 104 | - b_templates = *(reinterpret_cast<size_t*>(b)+1); | ||
| 105 | - if (a_template_bytes != b_template_bytes) | ||
| 106 | - return JANUS_UNKNOWN_ERROR; | 99 | + *similarity = 0; |
| 107 | 100 | ||
| 108 | - float dist = 0; | ||
| 109 | - for (size_t i=0; i<a_templates; i++) | ||
| 110 | - for (size_t j=0; j<b_templates; j++) | ||
| 111 | - dist += distance->compare(cv::Mat(1, a_template_bytes, CV_8UC1, a+2*sizeof(size_t)+i*a_template_bytes), | ||
| 112 | - cv::Mat(1, b_template_bytes, CV_8UC1, b+2*sizeof(size_t)+i*b_template_bytes)); | ||
| 113 | - *similarity = a_templates * b_templates / dist; | ||
| 114 | - return JANUS_SUCCESS; | ||
| 115 | -} | 101 | + int comparisons = 0; |
| 102 | + janus_flat_template a_template = a; | ||
| 103 | + while (a_template < a + a_bytes) { | ||
| 104 | + const size_t a_template_bytes = *reinterpret_cast<size_t*>(a_template); | ||
| 105 | + a_template += sizeof(a_template_bytes); | ||
| 116 | 106 | ||
| 117 | -struct janus_gallery_type : public TemplateList | ||
| 118 | -{}; | 107 | + janus_flat_template b_template = b; |
| 108 | + while (b_template < b + b_bytes) { | ||
| 109 | + const size_t b_template_bytes = *reinterpret_cast<size_t*>(b_template); | ||
| 110 | + b_template += sizeof(b_template_bytes); | ||
| 119 | 111 | ||
| 120 | -janus_error janus_initialize_gallery(janus_gallery *gallery) | ||
| 121 | -{ | ||
| 122 | - *gallery = new janus_gallery_type(); | ||
| 123 | - return JANUS_SUCCESS; | ||
| 124 | -} | 112 | + *similarity += distance->compare(cv::Mat(1, a_template_bytes, CV_8UC1, a_template), |
| 113 | + cv::Mat(1, b_template_bytes, CV_8UC1, b_template)); | ||
| 114 | + comparisons++; | ||
| 125 | 115 | ||
| 126 | -janus_error janus_enroll(const janus_template template_, const janus_template_id template_id, janus_gallery gallery) | ||
| 127 | -{ | ||
| 128 | - template_->file.set("Template_ID", template_id); | ||
| 129 | - gallery->append(*template_); | ||
| 130 | - delete template_; | 116 | + b_template += b_template_bytes; |
| 117 | + } | ||
| 118 | + | ||
| 119 | + a_template += a_template_bytes; | ||
| 120 | + } | ||
| 121 | + | ||
| 122 | + if (*similarity != *similarity) // True for NaN | ||
| 123 | + return JANUS_UNKNOWN_ERROR; | ||
| 124 | + | ||
| 125 | + *similarity /= comparisons; | ||
| 131 | return JANUS_SUCCESS; | 126 | return JANUS_SUCCESS; |
| 132 | } | 127 | } |
| 133 | 128 | ||
| 134 | -janus_error janus_finalize_gallery(janus_gallery gallery, janus_gallery_file gallery_file) | 129 | +janus_error janus_enroll(const janus_template template_, const janus_template_id template_id, janus_gallery gallery) |
| 135 | { | 130 | { |
| 136 | - QFile file(gallery_file); | ||
| 137 | - if (!file.open(QFile::WriteOnly)) | 131 | + template_->file.set("TEMPLATE_ID", template_id); |
| 132 | + QFile file(gallery); | ||
| 133 | + if (!file.open(QFile::WriteOnly | QFile::Append)) | ||
| 138 | return JANUS_WRITE_ERROR; | 134 | return JANUS_WRITE_ERROR; |
| 139 | QDataStream stream(&file); | 135 | QDataStream stream(&file); |
| 140 | - stream << gallery; | 136 | + stream << *template_; |
| 141 | file.close(); | 137 | file.close(); |
| 138 | + delete template_; | ||
| 142 | return JANUS_SUCCESS; | 139 | return JANUS_SUCCESS; |
| 143 | } | 140 | } |
openbr/plugins/algorithms.cpp
| @@ -79,7 +79,7 @@ class AlgorithmsInitializer : public Initializer | @@ -79,7 +79,7 @@ class AlgorithmsInitializer : public Initializer | ||
| 79 | Globals->abbreviations.insert("ColoredLBP", "Open+Affine(128,128,0.37,0.45)+Cvt(Gray)+Blur(1.1)+Gamma(0.2)+DoG(1,2)+ContrastEq(0.1,10)+LBP(1,2)+ColoredU2"); | 79 | Globals->abbreviations.insert("ColoredLBP", "Open+Affine(128,128,0.37,0.45)+Cvt(Gray)+Blur(1.1)+Gamma(0.2)+DoG(1,2)+ContrastEq(0.1,10)+LBP(1,2)+ColoredU2"); |
| 80 | 80 | ||
| 81 | // Transforms | 81 | // Transforms |
| 82 | - Globals->abbreviations.insert("FaceDetection", "(Open+Cvt(Gray)+Cascade(FrontalFace))"); | 82 | + Globals->abbreviations.insert("FaceDetection", "Open+Cvt(Gray)+Cascade(FrontalFace)"); |
| 83 | Globals->abbreviations.insert("DenseLBP", "(Blur(1.1)+Gamma(0.2)+DoG(1,2)+ContrastEq(0.1,10)+LBP(1,2)+RectRegions(8,8,6,6)+Hist(59))"); | 83 | Globals->abbreviations.insert("DenseLBP", "(Blur(1.1)+Gamma(0.2)+DoG(1,2)+ContrastEq(0.1,10)+LBP(1,2)+RectRegions(8,8,6,6)+Hist(59))"); |
| 84 | Globals->abbreviations.insert("DenseSIFT", "(Grid(10,10)+SIFTDescriptor(12)+ByRow)"); | 84 | Globals->abbreviations.insert("DenseSIFT", "(Grid(10,10)+SIFTDescriptor(12)+ByRow)"); |
| 85 | Globals->abbreviations.insert("FaceRecognitionRegistration", "(ASEFEyes+Affine(88,88,0.25,0.35)+DownsampleTraining(FTE(DFFS),instances=1))"); | 85 | Globals->abbreviations.insert("FaceRecognitionRegistration", "(ASEFEyes+Affine(88,88,0.25,0.35)+DownsampleTraining(FTE(DFFS),instances=1))"); |