Commit 579dd923923df24348f9e55c730a91e2031d7e93

Authored by Josh Klontz
1 parent 66458eae

progress on br-search

app/br-download/br-download.cpp
... ... @@ -61,7 +61,7 @@ static bool processReply(QNetworkReply* reply)
61 61 return false;
62 62  
63 63 const QByteArray hash = QCryptographicHash::hash(data, QCryptographicHash::Md5);
64   - br_append_utemplate_contents(stdout, reinterpret_cast<const int8_t*>(hash.data()), reinterpret_cast<const int8_t*>(hash.data()), 3, data.size(), reinterpret_cast<const unsigned char*>(data.data()));
  64 + br_append_utemplate_contents(stdout, reinterpret_cast<const unsigned char*>(hash.data()), reinterpret_cast<const unsigned char*>(hash.data()), 3, data.size(), reinterpret_cast<const unsigned char*>(data.data()));
65 65 return true;
66 66 }
67 67  
... ...
app/br-enroll/br-enroll.cpp
... ... @@ -54,7 +54,7 @@ static void enroll_utemplate(br_const_utemplate utemplate, br_callback_context)
54 54 const Mat &m = t.m();
55 55 const uint32_t size = m.rows * m.cols * m.elemSize();
56 56 const QByteArray templateID = QCryptographicHash::hash(QByteArray((const char*) m.data, size), QCryptographicHash::Md5);
57   - br_append_utemplate_contents(stdout, utemplate->imageID, (const int8_t*) templateID.data(), -1, size, m.data);
  57 + br_append_utemplate_contents(stdout, utemplate->imageID, (const unsigned char*) templateID.data(), -1, size, m.data);
58 58 }
59 59 }
60 60  
... ...
app/br-search/br-search.cpp
... ... @@ -17,12 +17,17 @@
17 17 #include <QtCore>
18 18 #include <cstdio>
19 19 #include <cstring>
  20 +#include <iomanip>
  21 +#include <iostream>
20 22 #include <limits>
  23 +#include <utility>
  24 +#include <vector>
21 25 #include <openbr/openbr_plugin.h>
22 26 #include <openbr/universal_template.h>
23 27  
24 28 using namespace br;
25 29 using namespace cv;
  30 +using namespace std;
26 31  
27 32 static void help()
28 33 {
... ... @@ -34,52 +39,94 @@ static void help()
34 39 "_br-search_ does retrieval by comparing query templates to target gallery(s).\n"
35 40 "The search strategy is implementation defined.\n"
36 41 "\n"
37   - "For every template read from _stdin_, search writes the top sorted matches as JSON objects to _stdout_ by comparing the query template against gallery URLs.\n"
38   - "The JSON objects include `AlgorithmID`, `QueryImageID`, `QueryTemplateID`, `TargetImageID`, `TargetTemplateID`, `Score`, and any algorithm-specific metadata fields set during _enroll_. \n"
  42 + "For every template read from _stdin_, search writes the top sorted matches a newline-terminated JSON object to _stdout_.\n"
  43 + "The JSON object will include at least `AlgorithmID`, (query) `ImageID`, (query) `TemplateID`, `Targets` and any algorithm-specific metadata fields set during _enroll_.\n"
39 44 "\n"
40 45 "Optional Arguments\n"
41 46 "------------------\n"
42   - "* -help - Print usage information.\n"
43   - "* -limit <int> - Maximum number of returns (20 otherwise).\n");
  47 + "* -help - Print usage information.\n"
  48 + "* -limit <int> - Maximum number of returns (20 otherwise).\n"
  49 + "* -threshold <float> - Minimum similarity score (none otherwise).");
44 50 }
45 51  
46   -static int limit = 20;
47   -static float threshold = -std::numeric_limits<float>::max();
  52 +static size_t limit = 20;
  53 +static float threshold = -numeric_limits<float>::max();
48 54  
49   -struct Result
50   -{
51   - int8_t targetImageID[16], targetTemplateID[16], queryImageID[16], queryTemplateID[16];
52   - int32_t algorithmID;
53   - float score;
54   -};
55   -
56   -struct TopTargets : QList< QPair<br_const_utemplate, float> >
  55 +struct SearchResults
57 56 {
  57 + typedef pair<float, br_const_utemplate> Target;
  58 + vector<Target> topTargets;
58 59 br_const_utemplate query;
59 60  
60   - TopTargets(br_const_utemplate query)
  61 + SearchResults(br_const_utemplate query)
61 62 : query(query) {}
62 63  
63   - void tryAdd(br_const_utemplate target, float score)
  64 + virtual ~SearchResults() {}
  65 +
  66 + void consider(br_const_utemplate target)
64 67 {
65   - if ((score < threshold) || ((size() == limit) && (score < last().second)))
  68 + const float score = compare(target, query);
  69 + if ((score < threshold) || ((topTargets.size() == limit) && (score < topTargets.front().first)))
66 70 return;
67   - (void) target;
  71 +
  72 + topTargets.push_back(Target(score, target));
  73 + make_heap(topTargets.begin(), topTargets.end());
  74 +
  75 + if (topTargets.size() == limit + 1)
  76 + pop_heap(topTargets.begin(), topTargets.end());
68 77 }
69 78  
70   - void print() const
  79 + static void writeMD5asHex(const unsigned char *md5)
71 80 {
  81 + cout << hex << setfill('0');
  82 + for (int i=0; i<16; i++)
  83 + cout << setw(2) << md5[i];
  84 + cout << dec;
  85 + }
72 86  
  87 + void print()
  88 + {
  89 + sort_heap(topTargets.begin(), topTargets.end());
  90 +
  91 + cout << "{ \"AlgorithmID\"=" << query->algorithmID;
  92 + cout << ", \"QueryImageID\"=";
  93 + writeMD5asHex(query->imageID);
  94 + cout << ", \"QueryTemplateID\"=";
  95 + writeMD5asHex(query->templateID);
  96 + printMetadata(query);
  97 + cout << ", \"Targets\"=[ ";
  98 + for (int i=topTargets.size()-1; i>=0; i--) {
  99 + Target &target = topTargets[i];
  100 + cout << "{ \"ImageID\"=";
  101 + writeMD5asHex(target.second->imageID);
  102 + cout << ", \"TemplateID\"=";
  103 + writeMD5asHex(target.second->templateID);
  104 + cout << ", \"Score\"=" << target.first;
  105 + printMetadata(target.second);
  106 + cout << " }";
  107 + if (i > 0)
  108 + cout << ", ";
  109 + }
  110 + cout << "]}\n" << flush;
73 111 }
  112 +
  113 + virtual float compare(br_const_utemplate target, br_const_utemplate query) const = 0;
  114 + virtual void printMetadata(br_const_utemplate) const { return; }
74 115 };
75 116  
76   -struct FaceRecognitionResult : public Result
  117 +struct FaceRecognition : public SearchResults
77 118 {
78   - int32_t x, y, width, height;
  119 + QSharedPointer<Distance> algorithm;
  120 +
  121 + FaceRecognition(br_const_utemplate query)
  122 + : SearchResults(query)
  123 + {
  124 + algorithm = Distance::fromAlgorithm("FaceRecognition");
  125 + }
79 126  
80   - FaceRecognitionResult()
  127 + float compare(br_const_utemplate target, br_const_utemplate query) const
81 128 {
82   - algorithmID = -1;
  129 + return algorithm->compare(target->data, query->data, 768);
83 130 }
84 131 };
85 132  
... ... @@ -102,22 +149,21 @@ struct MappedGallery
102 149 }
103 150 };
104 151  
105   -static QSharedPointer<Distance> distance;
106 152 static QList<MappedGallery> galleries;
107 153  
108 154 static void compare_utemplates(br_const_utemplate target, br_callback_context context)
109 155 {
110   - TopTargets *topTargets = (TopTargets*) context;
111   - topTargets->tryAdd(target, distance->compare(target->data, topTargets->query->data, 768));
  156 + SearchResults *searchResults = (SearchResults*) context;
  157 + searchResults->consider(target);
112 158 }
113 159  
114 160 static void search_utemplate(br_const_utemplate query, br_callback_context)
115 161 {
116   - TopTargets *topTargets = new TopTargets(query);
  162 + SearchResults *searchResults = new FaceRecognition(query);
117 163 foreach (const MappedGallery &gallery, galleries)
118   - br_iterate_utemplates(reinterpret_cast<br_const_utemplate>(gallery.data), reinterpret_cast<br_const_utemplate>(gallery.data + gallery.size), compare_utemplates, topTargets);
119   - topTargets->print();
120   - delete topTargets;
  164 + br_iterate_utemplates(reinterpret_cast<br_const_utemplate>(gallery.data), reinterpret_cast<br_const_utemplate>(gallery.data + gallery.size), compare_utemplates, searchResults);
  165 + searchResults->print();
  166 + delete searchResults;
121 167 }
122 168  
123 169 int main(int argc, char *argv[])
... ... @@ -136,7 +182,6 @@ int main(int argc, char *argv[])
136 182 galleries.append(MappedGallery(url));
137 183  
138 184 Globals->quiet = true;
139   - distance = Distance::fromAlgorithm("FaceRecognition");
140 185 br_iterate_utemplates_file(stdin, search_utemplate, NULL);
141 186  
142 187 Context::finalize();
... ...
openbr/universal_template.cpp
... ... @@ -27,7 +27,7 @@ void br_append_utemplate(FILE *file, br_const_utemplate utemplate)
27 27 br_append_utemplate_contents(file, utemplate->imageID, utemplate->templateID, utemplate->algorithmID, utemplate->size, utemplate->data);
28 28 }
29 29  
30   -void br_append_utemplate_contents(FILE *file, const int8_t *imageID, const int8_t *templateID, int32_t algorithmID, uint32_t size, const unsigned char *data)
  30 +void br_append_utemplate_contents(FILE *file, const unsigned char *imageID, const unsigned char *templateID, int32_t algorithmID, uint32_t size, const unsigned char *data)
31 31 {
32 32 static QMutex lock;
33 33 QMutexLocker locker(&lock);
... ...
openbr/universal_template.h
... ... @@ -30,8 +30,8 @@ extern &quot;C&quot; {
30 30 */
31 31 struct br_universal_template
32 32 {
33   - int8_t imageID[16]; /*!< MD5 hash of the undecoded origin file. */
34   - int8_t templateID[16]; /*!< MD5 hash of _data_. */
  33 + unsigned char imageID[16]; /*!< MD5 hash of the undecoded origin file. */
  34 + unsigned char templateID[16]; /*!< MD5 hash of _data_. */
35 35 int32_t algorithmID; /*!< type of _data_. */
36 36 uint32_t size; /*!< length of _data_. */
37 37 unsigned char data[]; /*!< _size_-byte buffer. */
... ... @@ -62,7 +62,7 @@ BR_EXPORT void br_append_utemplate(FILE *file, br_const_utemplate utemplate);
62 62 * \brief Serialize a br_universal_template to a file.
63 63 * \see br_append_utemplate
64 64 */
65   -BR_EXPORT void br_append_utemplate_contents(FILE *file, const int8_t *imageID, const int8_t *templateID, int32_t algorithmID, uint32_t size, const unsigned char *data);
  65 +BR_EXPORT void br_append_utemplate_contents(FILE *file, const unsigned char *imageID, const unsigned char *templateID, int32_t algorithmID, uint32_t size, const unsigned char *data);
66 66  
67 67 /*!
68 68 * \brief br_universal_template iterator callback.
... ...