Commit 3ef48e1b097ba0f9cd9d3d88d134417e83254d3d
1 parent
278fa768
removed public support for br-search and br-serve
Showing
5 changed files
with
0 additions
and
407 deletions
app/CMakeLists.txt
| @@ -8,6 +8,4 @@ add_subdirectory(examples) | @@ -8,6 +8,4 @@ add_subdirectory(examples) | ||
| 8 | if(NOT ${BR_EMBEDDED}) | 8 | if(NOT ${BR_EMBEDDED}) |
| 9 | add_subdirectory(br-crawl) | 9 | add_subdirectory(br-crawl) |
| 10 | add_subdirectory(br-gui) | 10 | add_subdirectory(br-gui) |
| 11 | - add_subdirectory(br-search) | ||
| 12 | - add_subdirectory(br-serve) | ||
| 13 | endif() | 11 | endif() |
app/br-search/CMakeLists.txt deleted
app/br-search/br-search.cpp deleted
| 1 | -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * | ||
| 2 | - * Copyright 2014 Noblis * | ||
| 3 | - * * | ||
| 4 | - * Licensed under the Apache License, Version 2.0 (the "License"); * | ||
| 5 | - * you may not use this file except in compliance with the License. * | ||
| 6 | - * You may obtain a copy of the License at * | ||
| 7 | - * * | ||
| 8 | - * http://www.apache.org/licenses/LICENSE-2.0 * | ||
| 9 | - * * | ||
| 10 | - * Unless required by applicable law or agreed to in writing, software * | ||
| 11 | - * distributed under the License is distributed on an "AS IS" BASIS, * | ||
| 12 | - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * | ||
| 13 | - * See the License for the specific language governing permissions and * | ||
| 14 | - * limitations under the License. * | ||
| 15 | - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | ||
| 16 | - | ||
| 17 | -#include <QtCore> | ||
| 18 | -#include <cstdio> | ||
| 19 | -#include <cstring> | ||
| 20 | -#include <iomanip> | ||
| 21 | -#include <iostream> | ||
| 22 | -#include <limits> | ||
| 23 | -#include <utility> | ||
| 24 | -#include <vector> | ||
| 25 | -#include <openbr/openbr_plugin.h> | ||
| 26 | -#include <openbr/universal_template.h> | ||
| 27 | - | ||
| 28 | -using namespace br; | ||
| 29 | -using namespace cv; | ||
| 30 | -using namespace std; | ||
| 31 | - | ||
| 32 | -static void help() | ||
| 33 | -{ | ||
| 34 | - printf("br-search URL(s) [args]\n" | ||
| 35 | - "=======================\n" | ||
| 36 | - "* __stdin__ - Templates (feature vectors)\n" | ||
| 37 | - "* __stdout__ - JSON\n" | ||
| 38 | - "\n" | ||
| 39 | - "_br-search_ does retrieval by comparing query templates to target gallery(s).\n" | ||
| 40 | - "The search strategy is implementation defined.\n" | ||
| 41 | - "\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" | ||
| 44 | - "\n" | ||
| 45 | - "Optional Arguments\n" | ||
| 46 | - "------------------\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)."); | ||
| 50 | -} | ||
| 51 | - | ||
| 52 | -static size_t limit = 20; | ||
| 53 | -static float threshold = -numeric_limits<float>::max(); | ||
| 54 | - | ||
| 55 | -struct MappedGallery | ||
| 56 | -{ | ||
| 57 | - QSharedPointer<QFile> file; | ||
| 58 | - qint64 size; | ||
| 59 | - uchar *data; | ||
| 60 | - | ||
| 61 | - MappedGallery(QString url) | ||
| 62 | - { | ||
| 63 | - if (url.startsWith("file://")) | ||
| 64 | - url = url.mid(7); | ||
| 65 | - file.reset(new QFile(url)); | ||
| 66 | - file->open(QFile::ReadOnly); | ||
| 67 | - size = file->size(); | ||
| 68 | - data = file->map(0, size); | ||
| 69 | - if (data == NULL) | ||
| 70 | - qFatal("Unable to map gallery: %s", qPrintable(url)); | ||
| 71 | - } | ||
| 72 | -}; | ||
| 73 | - | ||
| 74 | -static QList<MappedGallery> galleries; | ||
| 75 | - | ||
| 76 | -struct SearchResults | ||
| 77 | -{ | ||
| 78 | - typedef pair<float, br_const_utemplate> Target; | ||
| 79 | - vector<Target> topTargets; | ||
| 80 | - br_const_utemplate query; | ||
| 81 | - | ||
| 82 | - SearchResults(br_const_utemplate query) | ||
| 83 | - : query(query) {} | ||
| 84 | - | ||
| 85 | - virtual ~SearchResults() {} | ||
| 86 | - | ||
| 87 | - virtual void consider(const MappedGallery &gallery) | ||
| 88 | - { | ||
| 89 | - br_iterate_utemplates(reinterpret_cast<br_const_utemplate>(gallery.data), reinterpret_cast<br_const_utemplate>(gallery.data + gallery.size), compare_utemplates, this); | ||
| 90 | - } | ||
| 91 | - | ||
| 92 | - void print() | ||
| 93 | - { | ||
| 94 | - sort_heap(topTargets.begin(), topTargets.end()); | ||
| 95 | - | ||
| 96 | - cout << "{ \"AlgorithmID\":" << query->algorithmID; | ||
| 97 | - cout << ", \"ImageID\":\""; | ||
| 98 | - writeMD5asHex(query->imageID); | ||
| 99 | - cout << "\", \"TemplateID\":\""; | ||
| 100 | - writeMD5asHex(query->templateID); | ||
| 101 | - cout << "\""; | ||
| 102 | - printMetadata(query); | ||
| 103 | - cout << ", \"Targets\":[ "; | ||
| 104 | - for (int i=topTargets.size()-1; i>=0; i--) { | ||
| 105 | - Target &target = topTargets[i]; | ||
| 106 | - cout << "{ \"ImageID\":\""; | ||
| 107 | - writeMD5asHex(target.second->imageID); | ||
| 108 | - cout << "\", \"TemplateID\":\""; | ||
| 109 | - writeMD5asHex(target.second->templateID); | ||
| 110 | - cout << "\", \"Score\":" << target.first; | ||
| 111 | - printMetadata(target.second); | ||
| 112 | - cout << " }"; | ||
| 113 | - if (i > 0) | ||
| 114 | - cout << ", "; | ||
| 115 | - } | ||
| 116 | - cout << "] }\n" << flush; | ||
| 117 | - } | ||
| 118 | - | ||
| 119 | -private: | ||
| 120 | - void consider(br_const_utemplate target) | ||
| 121 | - { | ||
| 122 | - if (target->algorithmID != query->algorithmID) | ||
| 123 | - return; | ||
| 124 | - | ||
| 125 | - const float score = compare(target, query); | ||
| 126 | - if ((score < threshold) || ((topTargets.size() == limit) && (score < topTargets.front().first))) | ||
| 127 | - return; | ||
| 128 | - | ||
| 129 | - topTargets.push_back(Target(score, target)); | ||
| 130 | - make_heap(topTargets.begin(), topTargets.end()); | ||
| 131 | - | ||
| 132 | - if (topTargets.size() == limit + 1) | ||
| 133 | - pop_heap(topTargets.begin(), topTargets.end()); | ||
| 134 | - } | ||
| 135 | - | ||
| 136 | - static void compare_utemplates(br_const_utemplate target, br_callback_context context) | ||
| 137 | - { | ||
| 138 | - SearchResults *searchResults = (SearchResults*) context; | ||
| 139 | - searchResults->consider(target); | ||
| 140 | - } | ||
| 141 | - | ||
| 142 | - static void writeMD5asHex(const unsigned char *md5) | ||
| 143 | - { | ||
| 144 | - const char prevFill = cout.fill(); | ||
| 145 | - cout << hex << setfill('0'); | ||
| 146 | - for (int i=0; i<16; i++) | ||
| 147 | - cout << setw(2) << int(md5[i]); | ||
| 148 | - cout << dec; | ||
| 149 | - setfill(prevFill); | ||
| 150 | - } | ||
| 151 | - | ||
| 152 | - virtual float compare(br_const_utemplate target, br_const_utemplate query) const = 0; | ||
| 153 | - virtual void printMetadata(br_const_utemplate) const { return; } | ||
| 154 | -}; | ||
| 155 | - | ||
| 156 | -struct VoidSearch : public SearchResults | ||
| 157 | -{ | ||
| 158 | - VoidSearch(br_const_utemplate query) | ||
| 159 | - : SearchResults(query) {} | ||
| 160 | - | ||
| 161 | -private: | ||
| 162 | - void consider(const MappedGallery &) { return; } | ||
| 163 | - float compare(br_const_utemplate, br_const_utemplate) const { return 0; } | ||
| 164 | -}; | ||
| 165 | - | ||
| 166 | -struct ImageID : public SearchResults | ||
| 167 | -{ | ||
| 168 | - ImageID(br_const_utemplate query) | ||
| 169 | - : SearchResults(query) {} | ||
| 170 | - | ||
| 171 | -private: | ||
| 172 | - float compare(br_const_utemplate target, br_const_utemplate query) const | ||
| 173 | - { | ||
| 174 | - return !memcmp(&target->imageID, &query->imageID, sizeof(target->imageID)); | ||
| 175 | - } | ||
| 176 | - | ||
| 177 | - void printMetadata(br_const_utemplate t) const | ||
| 178 | - { | ||
| 179 | - cout << ", \"Data\":\"" << reinterpret_cast<const char*>(&t->data) << "\""; | ||
| 180 | - } | ||
| 181 | -}; | ||
| 182 | - | ||
| 183 | -struct FaceRecognition : public SearchResults | ||
| 184 | -{ | ||
| 185 | - FaceRecognition(br_const_utemplate query) | ||
| 186 | - : SearchResults(query) | ||
| 187 | - { | ||
| 188 | - algorithm = Distance::fromAlgorithm("FaceRecognition"); | ||
| 189 | - } | ||
| 190 | - | ||
| 191 | -private: | ||
| 192 | - QSharedPointer<Distance> algorithm; | ||
| 193 | - | ||
| 194 | - float compare(br_const_utemplate target, br_const_utemplate query) const | ||
| 195 | - { | ||
| 196 | - return algorithm->compare(target->data, query->data, 768); | ||
| 197 | - } | ||
| 198 | - | ||
| 199 | - void printMetadata(br_const_utemplate t) const | ||
| 200 | - { | ||
| 201 | - const float *metadata = reinterpret_cast<const float*>(&t->data[768]); | ||
| 202 | - cout << ", \"X\":" << metadata[0] | ||
| 203 | - << ", \"Y\":" << metadata[1] | ||
| 204 | - << ", \"Width\":" << metadata[2] | ||
| 205 | - << ", \"Height\":" << metadata[3] | ||
| 206 | - << ", \"RightEyeX\":" << metadata[4] | ||
| 207 | - << ", \"RightEyeY\":" << metadata[5] | ||
| 208 | - << ", \"LeftEyeX\":" << metadata[6] | ||
| 209 | - << ", \"LeftEyeY\":" << metadata[7]; | ||
| 210 | - } | ||
| 211 | -}; | ||
| 212 | - | ||
| 213 | -static void search_utemplate(br_const_utemplate query, br_callback_context) | ||
| 214 | -{ | ||
| 215 | - SearchResults *searchResults = NULL; | ||
| 216 | - switch (query->algorithmID) { | ||
| 217 | - case 0: searchResults = new VoidSearch(query); break; | ||
| 218 | - case 2: searchResults = new ImageID(query); break; | ||
| 219 | - case -1: searchResults = new FaceRecognition(query); break; | ||
| 220 | - } | ||
| 221 | - if (!searchResults) | ||
| 222 | - qFatal("Unsupported AlgorithmID: %d", query->algorithmID); | ||
| 223 | - | ||
| 224 | - foreach (const MappedGallery &gallery, galleries) | ||
| 225 | - searchResults->consider(gallery); | ||
| 226 | - searchResults->print(); | ||
| 227 | - delete searchResults; | ||
| 228 | -} | ||
| 229 | - | ||
| 230 | -int main(int argc, char *argv[]) | ||
| 231 | -{ | ||
| 232 | - QStringList urls; | ||
| 233 | - for (int i=1; i<argc; i++) { | ||
| 234 | - if (!strcmp(argv[i], "-help" )) { help(); exit(EXIT_SUCCESS); } | ||
| 235 | - else if (!strcmp(argv[i], "-limit")) limit = atoi(argv[++i]); | ||
| 236 | - else if (!strcmp(argv[i], "-threshold")) threshold = atof(argv[++i]); | ||
| 237 | - else urls.append(argv[i]); | ||
| 238 | - } | ||
| 239 | - | ||
| 240 | - Context::initialize(argc, argv, "", false); | ||
| 241 | - | ||
| 242 | - foreach (const QString &url, urls) | ||
| 243 | - galleries.append(MappedGallery(url)); | ||
| 244 | - | ||
| 245 | - Globals->quiet = true; | ||
| 246 | - br_iterate_utemplates_file(stdin, search_utemplate, NULL, false); | ||
| 247 | - | ||
| 248 | - Context::finalize(); | ||
| 249 | - return EXIT_SUCCESS; | ||
| 250 | -} |
app/br-serve/CMakeLists.txt deleted
| 1 | -set(QHTTPSERVER_DIR "${CMAKE_SOURCE_DIR}/3rdparty/qhttpserver") | ||
| 2 | -set(QHTTPSERVER_SRC ${QHTTPSERVER_DIR}/src/qhttpconnection.cpp | ||
| 3 | - ${QHTTPSERVER_DIR}/src/qhttpresponse.cpp | ||
| 4 | - ${QHTTPSERVER_DIR}/src/qhttprequest.cpp | ||
| 5 | - ${QHTTPSERVER_DIR}/src/qhttpserver.cpp | ||
| 6 | - ${QHTTPSERVER_DIR}/http-parser/http_parser.c) | ||
| 7 | -add_definitions(-DQHTTPSERVER_EXPORT) | ||
| 8 | -include_directories(${CMAKE_SOURCE_DIR}/3rdparty/qhttpserver/src | ||
| 9 | - ${CMAKE_SOURCE_DIR}/3rdparty/qhttpserver/http-parser | ||
| 10 | - ${CMAKE_CURRENT_BINARY_DIR}) | ||
| 11 | -add_executable(br-serve br-serve.cpp ${QHTTPSERVER_SRC} ${BR_RESOURCES}) | ||
| 12 | -target_link_libraries(br-serve openbr ${BR_THIRDPARTY_LIBS}) | ||
| 13 | -qt5_use_modules(br-serve ${QT_DEPENDENCIES}) | ||
| 14 | -install(TARGETS br-serve RUNTIME DESTINATION bin) |
app/br-serve/br-serve.cpp deleted
| 1 | -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * | ||
| 2 | - * Copyright 2014 Noblis * | ||
| 3 | - * * | ||
| 4 | - * Licensed under the Apache License, Version 2.0 (the "License"); * | ||
| 5 | - * you may not use this file except in compliance with the License. * | ||
| 6 | - * You may obtain a copy of the License at * | ||
| 7 | - * * | ||
| 8 | - * http://www.apache.org/licenses/LICENSE-2.0 * | ||
| 9 | - * * | ||
| 10 | - * Unless required by applicable law or agreed to in writing, software * | ||
| 11 | - * distributed under the License is distributed on an "AS IS" BASIS, * | ||
| 12 | - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * | ||
| 13 | - * See the License for the specific language governing permissions and * | ||
| 14 | - * limitations under the License. * | ||
| 15 | - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | ||
| 16 | - | ||
| 17 | -#include <QtCore> | ||
| 18 | -#include <QtNetwork> | ||
| 19 | -#include <cstdio> | ||
| 20 | -#include <cstring> | ||
| 21 | -#include <qhttpserver.h> | ||
| 22 | -#include <qhttprequest.h> | ||
| 23 | -#include <qhttpresponse.h> | ||
| 24 | -#include <openbr/universal_template.h> | ||
| 25 | - | ||
| 26 | -static void help() | ||
| 27 | -{ | ||
| 28 | - printf("br-serve [command]\n" | ||
| 29 | - "==================\n" | ||
| 30 | - "\n" | ||
| 31 | - "_br-serve_ converts the command's stdin/stdout into a web service.\n" | ||
| 32 | - "\n" | ||
| 33 | - "Optional Arguments\n" | ||
| 34 | - "------------------\n" | ||
| 35 | - "* -help - Print usage information.\n" | ||
| 36 | - "* -port <int> - The port to communicate on (80 otherwise)."); | ||
| 37 | -} | ||
| 38 | - | ||
| 39 | -static int port = 80; | ||
| 40 | -static QProcess process; | ||
| 41 | - | ||
| 42 | -class Handler : public QObject | ||
| 43 | -{ | ||
| 44 | - Q_OBJECT | ||
| 45 | - | ||
| 46 | -public slots: | ||
| 47 | - void handle(QHttpRequest *request, QHttpResponse *response) | ||
| 48 | - { | ||
| 49 | - QByteArray message; | ||
| 50 | - | ||
| 51 | - const QUrlQuery urlQuery(request->url()); | ||
| 52 | - if (urlQuery.hasQueryItem("URL")) { | ||
| 53 | - process.write(qPrintable(QString(urlQuery.queryItemValue("URL") + "\n"))); | ||
| 54 | - process.waitForReadyRead(); | ||
| 55 | - if (process.error() != QProcess::UnknownError) | ||
| 56 | - qFatal("%s\n", qPrintable(process.errorString())); | ||
| 57 | - message = process.readLine(); | ||
| 58 | - response->setHeader("Content-Type", "application/json"); | ||
| 59 | - } else if (urlQuery.hasQueryItem("ImageID")) { | ||
| 60 | - const QByteArray imageID = QByteArray::fromHex(urlQuery.queryItemValue("ImageID").toLatin1()); | ||
| 61 | - if (imageID.size() == 16) { | ||
| 62 | - br_universal_template in; | ||
| 63 | - in.algorithmID = 2; | ||
| 64 | - memcpy(&in.imageID, imageID.data(), 16); | ||
| 65 | - memset(in.templateID, 0, 16); | ||
| 66 | - in.size = 0; | ||
| 67 | - | ||
| 68 | - process.write((const char *)&in, sizeof(br_universal_template)); | ||
| 69 | - process.waitForReadyRead(); | ||
| 70 | - if (process.error() != QProcess::UnknownError) | ||
| 71 | - qFatal("%s\n", qPrintable(process.errorString())); | ||
| 72 | - | ||
| 73 | - br_utemplate out = (br_utemplate) malloc(sizeof(br_universal_template)); | ||
| 74 | - if (process.read((char*) out, sizeof(br_universal_template)) == sizeof(br_universal_template)) { | ||
| 75 | - out = (br_utemplate) realloc(out, sizeof(br_universal_template) + out->size); | ||
| 76 | - if (process.read(reinterpret_cast<char*>(out+1), out->size) != out->size) | ||
| 77 | - qFatal("Unexepected EOF when reading universal template data."); | ||
| 78 | - message = QByteArray((char*)&out->data, out->size); | ||
| 79 | - } | ||
| 80 | - free(out); | ||
| 81 | - } | ||
| 82 | - response->setHeader("Content-Type", "image/jpeg"); | ||
| 83 | - } else { | ||
| 84 | - QString path = request->path(); | ||
| 85 | - if (path == "/") | ||
| 86 | - path = "localhost"; | ||
| 87 | - message = QString("<!DOCTYPE html>\n" | ||
| 88 | - "<html>\n" | ||
| 89 | - "<head>\n" | ||
| 90 | - " <title>Web Services API</title>\n" | ||
| 91 | - "</head>\n" | ||
| 92 | - "\n" | ||
| 93 | - "<body>\n" | ||
| 94 | - " <h1><a href=\"http://en.wikipedia.org/wiki/Query_string\">Query String</a> Parameters</h1>" | ||
| 95 | - " <ul>\n" | ||
| 96 | - " <li><b>URL</b> - Query URL for image search.</li>\n" | ||
| 97 | - " <li><b>ImageID</b> - Query ImageID for image retrieval.</li>\n" | ||
| 98 | - " </ul>\n" | ||
| 99 | - " <h1>Examples</h1>\n" | ||
| 100 | - " <ul>\n" | ||
| 101 | - " <li>http://%1%2/?URL=data.liblikely.org/misc/lenna.tiff</li>\n" | ||
| 102 | - " <li>http://%1%2/?ImageID=ecaee0b4cd73a76dd2a8060b2909a4a1</li>\n" | ||
| 103 | - " </ul>\n" | ||
| 104 | - "</body>\n" | ||
| 105 | - "</html>").arg(path, port == 80 ? QString() : (QString(":") + QString::number(port))).toLatin1(); | ||
| 106 | - response->setHeader("Content-Type", "text/html"); | ||
| 107 | - } | ||
| 108 | - | ||
| 109 | - response->setHeader("Content-Length", QString::number(message.size())); | ||
| 110 | - response->writeHead(200); // everything is OK | ||
| 111 | - response->write(message); | ||
| 112 | - response->end(); | ||
| 113 | - } | ||
| 114 | -}; | ||
| 115 | - | ||
| 116 | -int main(int argc, char *argv[]) | ||
| 117 | -{ | ||
| 118 | - QCoreApplication application(argc, argv); | ||
| 119 | - | ||
| 120 | - for (int i=1; i<argc; i++) { | ||
| 121 | - if (!strcmp(argv[i], "-help")) { help(); exit(EXIT_SUCCESS); } | ||
| 122 | - else if (!strcmp(argv[i], "-port")) port = atoi(argv[++i]); | ||
| 123 | - else process.start(argv[i]); | ||
| 124 | - } | ||
| 125 | - | ||
| 126 | - QHttpServer server; | ||
| 127 | - Handler handler; | ||
| 128 | - QObject::connect(&server, SIGNAL(newRequest(QHttpRequest*, QHttpResponse*)), | ||
| 129 | - &handler, SLOT(handle(QHttpRequest*, QHttpResponse*))); | ||
| 130 | - | ||
| 131 | - if (!server.listen(port)) | ||
| 132 | - qFatal("Failed to connect to port: %d.", port); | ||
| 133 | - | ||
| 134 | - return application.exec(); | ||
| 135 | -} | ||
| 136 | - | ||
| 137 | -#include "br-serve.moc" |