Commit 6daa71e1af6096c461ad8704298c7acaa763b28f
1 parent
4fa20c4f
Add janus_flatten_gallery, remove janus_compare, update janus_search to work on flat_gallery.
Showing
2 changed files
with
91 additions
and
66 deletions
openbr/janus.cpp
| 1 | -#include "janus.h" | ||
| 2 | -#include "janus_io.h" | 1 | +#include "iarpa_janus.h" |
| 2 | +#include "iarpa_janus_io.h" | ||
| 3 | #include "openbr_plugin.h" | 3 | #include "openbr_plugin.h" |
| 4 | #include "openbr/core/opencvutils.h" | 4 | #include "openbr/core/opencvutils.h" |
| 5 | #include "openbr/core/common.h" | 5 | #include "openbr/core/common.h" |
| 6 | - | ||
| 7 | using namespace br; | 6 | using namespace br; |
| 8 | 7 | ||
| 9 | static QSharedPointer<Transform> transform; | 8 | static QSharedPointer<Transform> transform; |
| @@ -11,15 +10,16 @@ static QSharedPointer<Distance> distance; | @@ -11,15 +10,16 @@ static QSharedPointer<Distance> distance; | ||
| 11 | 10 | ||
| 12 | size_t janus_max_template_size() | 11 | size_t janus_max_template_size() |
| 13 | { | 12 | { |
| 14 | - return 33554432; // 32 MB | 13 | + return 102400;// 100 KB |
| 15 | } | 14 | } |
| 16 | 15 | ||
| 17 | -janus_error janus_initialize(const char *sdk_path, const char *model_file) | 16 | +janus_error janus_initialize(const char *sdk_path, const char *temp_path, const char *model_file) |
| 18 | { | 17 | { |
| 19 | int argc = 1; | 18 | int argc = 1; |
| 20 | const char *argv[1] = { "janus" }; | 19 | const char *argv[1] = { "janus" }; |
| 21 | Context::initialize(argc, (char**)argv, sdk_path, false); | 20 | Context::initialize(argc, (char**)argv, sdk_path, false); |
| 22 | Globals->quiet = true; | 21 | Globals->quiet = true; |
| 22 | + Globals->file.set(QString("temp_path"), QString(temp_path)); | ||
| 23 | const QString algorithm = model_file; | 23 | const QString algorithm = model_file; |
| 24 | if (algorithm.isEmpty()) { | 24 | if (algorithm.isEmpty()) { |
| 25 | transform.reset(Transform::make("Cvt(Gray)+Affine(88,88,0.25,0.35)+<FaceRecognitionExtraction>+<FaceRecognitionEmbedding>+<FaceRecognitionQuantization>", NULL)); | 25 | transform.reset(Transform::make("Cvt(Gray)+Affine(88,88,0.25,0.35)+<FaceRecognitionExtraction>+<FaceRecognitionEmbedding>+<FaceRecognitionQuantization>", NULL)); |
| @@ -42,7 +42,7 @@ janus_error janus_finalize() | @@ -42,7 +42,7 @@ janus_error janus_finalize() | ||
| 42 | struct janus_template_type : public Template | 42 | struct janus_template_type : public Template |
| 43 | {}; | 43 | {}; |
| 44 | 44 | ||
| 45 | -janus_error janus_allocate(janus_template *template_) | 45 | +janus_error janus_allocate_template(janus_template *template_) |
| 46 | { | 46 | { |
| 47 | *template_ = new janus_template_type(); | 47 | *template_ = new janus_template_type(); |
| 48 | return JANUS_SUCCESS; | 48 | return JANUS_SUCCESS; |
| @@ -74,7 +74,7 @@ janus_error janus_augment(const janus_image image, const janus_attribute_list at | @@ -74,7 +74,7 @@ janus_error janus_augment(const janus_image image, const janus_attribute_list at | ||
| 74 | return (u.isEmpty() || !u.first().data) ? JANUS_FAILURE_TO_ENROLL : JANUS_SUCCESS; | 74 | return (u.isEmpty() || !u.first().data) ? JANUS_FAILURE_TO_ENROLL : JANUS_SUCCESS; |
| 75 | } | 75 | } |
| 76 | 76 | ||
| 77 | -janus_error janus_flatten(janus_template template_, janus_flat_template flat_template, size_t *bytes) | 77 | +janus_error janus_flatten_template(janus_template template_, janus_flat_template flat_template, size_t *bytes) |
| 78 | { | 78 | { |
| 79 | *bytes = 0; | 79 | *bytes = 0; |
| 80 | foreach (const cv::Mat &m, *template_) { | 80 | foreach (const cv::Mat &m, *template_) { |
| @@ -99,12 +99,58 @@ janus_error janus_flatten(janus_template template_, janus_flat_template flat_tem | @@ -99,12 +99,58 @@ janus_error janus_flatten(janus_template template_, janus_flat_template flat_tem | ||
| 99 | return JANUS_SUCCESS; | 99 | return JANUS_SUCCESS; |
| 100 | } | 100 | } |
| 101 | 101 | ||
| 102 | -janus_error janus_free(janus_template template_) | 102 | +janus_error janus_free_template(janus_template template_) |
| 103 | { | 103 | { |
| 104 | delete template_; | 104 | delete template_; |
| 105 | return JANUS_SUCCESS; | 105 | return JANUS_SUCCESS; |
| 106 | } | 106 | } |
| 107 | 107 | ||
| 108 | +struct janus_gallery_type : public QList<janus_template> | ||
| 109 | +{}; | ||
| 110 | + | ||
| 111 | +janus_error janus_allocate_gallery(janus_gallery *gallery_) | ||
| 112 | +{ | ||
| 113 | + *gallery_ = new janus_gallery_type(); | ||
| 114 | + return JANUS_SUCCESS; | ||
| 115 | +} | ||
| 116 | + | ||
| 117 | +janus_error janus_enroll(const janus_template template_, const janus_template_id template_id, janus_gallery gallery) | ||
| 118 | +{ | ||
| 119 | + template_->file.set("TEMPLATE_ID", template_id); | ||
| 120 | + gallery->push_back(template_); | ||
| 121 | + return JANUS_SUCCESS; | ||
| 122 | +} | ||
| 123 | + | ||
| 124 | +janus_error janus_free_gallery(janus_gallery gallery_) { | ||
| 125 | + delete gallery_; | ||
| 126 | + return JANUS_SUCCESS; | ||
| 127 | +} | ||
| 128 | + | ||
| 129 | +janus_error janus_flatten_gallery(janus_gallery gallery, janus_flat_gallery flat_gallery, size_t *bytes) | ||
| 130 | +{ | ||
| 131 | + *bytes = 0; | ||
| 132 | + foreach (const janus_template &t, *gallery) { | ||
| 133 | + janus_template_id template_id = t->file.get<janus_template_id>("TEMPLATE_ID"); | ||
| 134 | + | ||
| 135 | + janus_flat_template u = new janus_data[janus_max_template_size()]; | ||
| 136 | + size_t t_bytes = 0; | ||
| 137 | + JANUS_ASSERT(janus_flatten_template(t, u, &t_bytes)) | ||
| 138 | + memcpy(flat_gallery, &template_id, sizeof(template_id)); | ||
| 139 | + flat_gallery += sizeof(template_id); | ||
| 140 | + *bytes += sizeof(template_id); | ||
| 141 | + | ||
| 142 | + memcpy(flat_gallery, &t_bytes, sizeof(t_bytes)); | ||
| 143 | + flat_gallery += sizeof(t_bytes); | ||
| 144 | + *bytes += sizeof(t_bytes); | ||
| 145 | + | ||
| 146 | + memcpy(flat_gallery, u, t_bytes); | ||
| 147 | + flat_gallery += t_bytes; | ||
| 148 | + *bytes += t_bytes; | ||
| 149 | + delete[] u; | ||
| 150 | + } | ||
| 151 | + return JANUS_SUCCESS; | ||
| 152 | +} | ||
| 153 | + | ||
| 108 | janus_error janus_verify(const janus_flat_template a, const size_t a_bytes, const janus_flat_template b, const size_t b_bytes, float *similarity) | 154 | janus_error janus_verify(const janus_flat_template a, const size_t a_bytes, const janus_flat_template b, const size_t b_bytes, float *similarity) |
| 109 | { | 155 | { |
| 110 | *similarity = 0; | 156 | *similarity = 0; |
| @@ -114,12 +160,10 @@ janus_error janus_verify(const janus_flat_template a, const size_t a_bytes, cons | @@ -114,12 +160,10 @@ janus_error janus_verify(const janus_flat_template a, const size_t a_bytes, cons | ||
| 114 | while (a_template < a + a_bytes) { | 160 | while (a_template < a + a_bytes) { |
| 115 | const size_t a_template_bytes = *reinterpret_cast<size_t*>(a_template); | 161 | const size_t a_template_bytes = *reinterpret_cast<size_t*>(a_template); |
| 116 | a_template += sizeof(a_template_bytes); | 162 | a_template += sizeof(a_template_bytes); |
| 117 | - | ||
| 118 | janus_flat_template b_template = b; | 163 | janus_flat_template b_template = b; |
| 119 | while (b_template < b + b_bytes) { | 164 | while (b_template < b + b_bytes) { |
| 120 | const size_t b_template_bytes = *reinterpret_cast<size_t*>(b_template); | 165 | const size_t b_template_bytes = *reinterpret_cast<size_t*>(b_template); |
| 121 | b_template += sizeof(b_template_bytes); | 166 | b_template += sizeof(b_template_bytes); |
| 122 | - | ||
| 123 | *similarity += distance->compare(cv::Mat(1, a_template_bytes, CV_8UC1, a_template), | 167 | *similarity += distance->compare(cv::Mat(1, a_template_bytes, CV_8UC1, a_template), |
| 124 | cv::Mat(1, b_template_bytes, CV_8UC1, b_template)); | 168 | cv::Mat(1, b_template_bytes, CV_8UC1, b_template)); |
| 125 | comparisons++; | 169 | comparisons++; |
| @@ -138,62 +182,43 @@ janus_error janus_verify(const janus_flat_template a, const size_t a_bytes, cons | @@ -138,62 +182,43 @@ janus_error janus_verify(const janus_flat_template a, const size_t a_bytes, cons | ||
| 138 | return JANUS_SUCCESS; | 182 | return JANUS_SUCCESS; |
| 139 | } | 183 | } |
| 140 | 184 | ||
| 141 | -janus_error janus_enroll(const janus_template template_, const janus_template_id template_id, janus_gallery gallery) | ||
| 142 | -{ | ||
| 143 | - template_->file.set("TEMPLATE_ID", template_id); | ||
| 144 | - QFile file(gallery); | ||
| 145 | - if (!file.open(QFile::WriteOnly | QFile::Append)) | ||
| 146 | - return JANUS_WRITE_ERROR; | ||
| 147 | - QDataStream stream(&file); | ||
| 148 | - stream << *template_; | ||
| 149 | - file.close(); | ||
| 150 | - return JANUS_SUCCESS; | ||
| 151 | -} | ||
| 152 | - | ||
| 153 | -janus_error janus_gallery_size(janus_gallery gallery, size_t *size) | ||
| 154 | -{ | ||
| 155 | - *size = TemplateList::fromGallery(gallery).size(); | ||
| 156 | - return JANUS_SUCCESS; | ||
| 157 | -} | ||
| 158 | - | ||
| 159 | -janus_error janus_search(const janus_template template_, janus_gallery gallery, int requested_returns, janus_template_id *template_ids, float *similarities, int *actual_returns) | 185 | +janus_error janus_search(const janus_flat_template probe, const size_t probe_bytes, const janus_flat_gallery gallery, const size_t gallery_bytes, int requested_returns, janus_template_id *template_ids, float *similarities, int *actual_returns) |
| 160 | { | 186 | { |
| 161 | - TemplateList query; | ||
| 162 | - query.append(*template_); | ||
| 163 | - | ||
| 164 | - const TemplateList targets = TemplateList::fromGallery(gallery); | ||
| 165 | - | ||
| 166 | - if (targets.size() < requested_returns) *actual_returns = targets.size(); | ||
| 167 | - else *actual_returns = requested_returns; | ||
| 168 | - | ||
| 169 | - QScopedPointer<MatrixOutput> matrix(MatrixOutput::make(targets.files(), query.files())); | ||
| 170 | - distance->compare(targets, query, matrix.data()); | ||
| 171 | - | ||
| 172 | - typedef QPair<float,int> Pair; | ||
| 173 | - QList<Pair> sortedSimilarities = Common::Sort(OpenCVUtils::matrixToVector<float>(matrix.data()->data.row(0)), true, *actual_returns); | ||
| 174 | - | ||
| 175 | - FileList targetFiles; | ||
| 176 | - for (int i=0; i<sortedSimilarities.size(); i++) { | ||
| 177 | - matrix.data()->data.at<float>(0,i) = sortedSimilarities[i].first; | ||
| 178 | - targetFiles.append(targets[sortedSimilarities[i].second]); | 187 | + typedef QPair<float, int> Pair; |
| 188 | + QList<Pair> comparisons; comparisons.reserve(requested_returns); | ||
| 189 | + janus_flat_gallery target_gallery = gallery; | ||
| 190 | + while (target_gallery < gallery + gallery_bytes) { | ||
| 191 | + janus_template_id target_id = *reinterpret_cast<janus_template_id*>(target_gallery); | ||
| 192 | + target_gallery += sizeof(target_id); | ||
| 193 | + | ||
| 194 | + const size_t target_template_bytes = *reinterpret_cast<size_t*>(target_gallery); | ||
| 195 | + target_gallery += sizeof(target_template_bytes); | ||
| 196 | + janus_flat_template target_template_flat = new janus_data[target_template_bytes]; | ||
| 197 | + memcpy(target_template_flat, target_gallery, target_template_bytes); | ||
| 198 | + target_gallery += target_template_bytes; | ||
| 199 | + | ||
| 200 | + float similarity; | ||
| 201 | + JANUS_ASSERT(janus_verify(probe, probe_bytes, target_template_flat, target_template_bytes, &similarity)) | ||
| 202 | + if (comparisons.size() < requested_returns) { | ||
| 203 | + comparisons.append(Pair(similarity, target_id)); | ||
| 204 | + std::sort(comparisons.begin(), comparisons.end()); | ||
| 205 | + } else { | ||
| 206 | + Pair temp = comparisons.first(); | ||
| 207 | + if (temp.first < similarity) { | ||
| 208 | + comparisons.removeFirst(); | ||
| 209 | + comparisons.append(Pair(similarity, target_id)); | ||
| 210 | + std::sort(comparisons.begin(), comparisons.end()); | ||
| 211 | + } | ||
| 212 | + } | ||
| 213 | + delete[] target_template_flat; | ||
| 214 | + } | ||
| 215 | + *actual_returns = comparisons.size(); | ||
| 216 | + QList<Pair> temp; temp.reserve(comparisons.size()); | ||
| 217 | + std::reverse_copy(comparisons.begin(), comparisons.end(), std::back_inserter(temp)); | ||
| 218 | + comparisons = temp; | ||
| 219 | + foreach(const Pair &comparison, comparisons) { | ||
| 220 | + *similarities = comparison.first; similarities++; | ||
| 221 | + *template_ids = comparison.second; template_ids++; | ||
| 179 | } | 222 | } |
| 180 | - const QVector<janus_template_id> targetIds = File::get<janus_template_id,File>(targetFiles, "TEMPLATE_ID").toVector(); | ||
| 181 | - | ||
| 182 | - memcpy(similarities, matrix->data.data, *actual_returns * sizeof(float)); | ||
| 183 | - memcpy(template_ids, targetIds.data(), *actual_returns * sizeof(janus_template_id)); | ||
| 184 | - return JANUS_SUCCESS; | ||
| 185 | -} | ||
| 186 | - | ||
| 187 | -janus_error janus_compare(janus_gallery target, janus_gallery query, float *similarity_matrix, janus_template_id *target_ids, janus_template_id *query_ids) | ||
| 188 | -{ | ||
| 189 | - const TemplateList targets = TemplateList::fromGallery(target); | ||
| 190 | - const TemplateList queries = TemplateList::fromGallery(query); | ||
| 191 | - QScopedPointer<MatrixOutput> matrix(MatrixOutput::make(targets.files(), queries.files())); | ||
| 192 | - distance->compare(targets, queries, matrix.data()); | ||
| 193 | - const QVector<janus_template_id> targetIds = File::get<janus_template_id,File>(matrix->targetFiles, "TEMPLATE_ID").toVector(); | ||
| 194 | - const QVector<janus_template_id> queryIds = File::get<janus_template_id,File>(matrix->queryFiles, "TEMPLATE_ID").toVector(); | ||
| 195 | - memcpy(similarity_matrix, matrix->data.data, matrix->data.rows * matrix->data.cols * sizeof(float)); | ||
| 196 | - memcpy(target_ids, targetIds.data(), targetIds.size() * sizeof(janus_template_id)); | ||
| 197 | - memcpy(query_ids, queryIds.data(), queryIds.size() * sizeof(janus_template_id)); | ||
| 198 | return JANUS_SUCCESS; | 223 | return JANUS_SUCCESS; |
| 199 | } | 224 | } |