diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index 1e94ed9..7d43db1 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -8,6 +8,4 @@ add_subdirectory(examples) if(NOT ${BR_EMBEDDED}) add_subdirectory(br-crawl) add_subdirectory(br-gui) - add_subdirectory(br-search) - add_subdirectory(br-serve) endif() diff --git a/app/br-search/CMakeLists.txt b/app/br-search/CMakeLists.txt deleted file mode 100644 index b1fd566..0000000 --- a/app/br-search/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -add_executable(br-search br-search.cpp ${BR_RESOURCES}) -target_link_libraries(br-search openbr ${BR_THIRDPARTY_LIBS}) -qt5_use_modules(br-search ${QT_DEPENDENCIES}) -install(TARGETS br-search RUNTIME DESTINATION bin) diff --git a/app/br-search/br-search.cpp b/app/br-search/br-search.cpp deleted file mode 100644 index 9c30fd4..0000000 --- a/app/br-search/br-search.cpp +++ /dev/null @@ -1,250 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * Copyright 2014 Noblis * - * * - * 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 -#include -#include -#include -#include -#include -#include -#include - -using namespace br; -using namespace cv; -using namespace std; - -static void help() -{ - printf("br-search URL(s) [args]\n" - "=======================\n" - "* __stdin__ - Templates (feature vectors)\n" - "* __stdout__ - JSON\n" - "\n" - "_br-search_ does retrieval by comparing query templates to target gallery(s).\n" - "The search strategy is implementation defined.\n" - "\n" - "For every template read from _stdin_, search writes the top sorted matches a newline-terminated JSON object to _stdout_.\n" - "The JSON object will include at least `AlgorithmID`, (query) `ImageID`, (query) `TemplateID`, `Targets` and any algorithm-specific metadata fields set during _enroll_.\n" - "\n" - "Optional Arguments\n" - "------------------\n" - "* -help - Print usage information.\n" - "* -limit - Maximum number of returns (20 otherwise).\n" - "* -threshold - Minimum similarity score (none otherwise)."); -} - -static size_t limit = 20; -static float threshold = -numeric_limits::max(); - -struct MappedGallery -{ - QSharedPointer file; - qint64 size; - uchar *data; - - MappedGallery(QString url) - { - if (url.startsWith("file://")) - url = url.mid(7); - file.reset(new QFile(url)); - file->open(QFile::ReadOnly); - size = file->size(); - data = file->map(0, size); - if (data == NULL) - qFatal("Unable to map gallery: %s", qPrintable(url)); - } -}; - -static QList galleries; - -struct SearchResults -{ - typedef pair Target; - vector topTargets; - br_const_utemplate query; - - SearchResults(br_const_utemplate query) - : query(query) {} - - virtual ~SearchResults() {} - - virtual void consider(const MappedGallery &gallery) - { - br_iterate_utemplates(reinterpret_cast(gallery.data), reinterpret_cast(gallery.data + gallery.size), compare_utemplates, this); - } - - void print() - { - sort_heap(topTargets.begin(), topTargets.end()); - - cout << "{ \"AlgorithmID\":" << query->algorithmID; - cout << ", \"ImageID\":\""; - writeMD5asHex(query->imageID); - cout << "\", \"TemplateID\":\""; - writeMD5asHex(query->templateID); - cout << "\""; - printMetadata(query); - cout << ", \"Targets\":[ "; - for (int i=topTargets.size()-1; i>=0; i--) { - Target &target = topTargets[i]; - cout << "{ \"ImageID\":\""; - writeMD5asHex(target.second->imageID); - cout << "\", \"TemplateID\":\""; - writeMD5asHex(target.second->templateID); - cout << "\", \"Score\":" << target.first; - printMetadata(target.second); - cout << " }"; - if (i > 0) - cout << ", "; - } - cout << "] }\n" << flush; - } - -private: - void consider(br_const_utemplate target) - { - if (target->algorithmID != query->algorithmID) - return; - - const float score = compare(target, query); - if ((score < threshold) || ((topTargets.size() == limit) && (score < topTargets.front().first))) - return; - - topTargets.push_back(Target(score, target)); - make_heap(topTargets.begin(), topTargets.end()); - - if (topTargets.size() == limit + 1) - pop_heap(topTargets.begin(), topTargets.end()); - } - - static void compare_utemplates(br_const_utemplate target, br_callback_context context) - { - SearchResults *searchResults = (SearchResults*) context; - searchResults->consider(target); - } - - static void writeMD5asHex(const unsigned char *md5) - { - const char prevFill = cout.fill(); - cout << hex << setfill('0'); - for (int i=0; i<16; i++) - cout << setw(2) << int(md5[i]); - cout << dec; - setfill(prevFill); - } - - virtual float compare(br_const_utemplate target, br_const_utemplate query) const = 0; - virtual void printMetadata(br_const_utemplate) const { return; } -}; - -struct VoidSearch : public SearchResults -{ - VoidSearch(br_const_utemplate query) - : SearchResults(query) {} - -private: - void consider(const MappedGallery &) { return; } - float compare(br_const_utemplate, br_const_utemplate) const { return 0; } -}; - -struct ImageID : public SearchResults -{ - ImageID(br_const_utemplate query) - : SearchResults(query) {} - -private: - float compare(br_const_utemplate target, br_const_utemplate query) const - { - return !memcmp(&target->imageID, &query->imageID, sizeof(target->imageID)); - } - - void printMetadata(br_const_utemplate t) const - { - cout << ", \"Data\":\"" << reinterpret_cast(&t->data) << "\""; - } -}; - -struct FaceRecognition : public SearchResults -{ - FaceRecognition(br_const_utemplate query) - : SearchResults(query) - { - algorithm = Distance::fromAlgorithm("FaceRecognition"); - } - -private: - QSharedPointer algorithm; - - float compare(br_const_utemplate target, br_const_utemplate query) const - { - return algorithm->compare(target->data, query->data, 768); - } - - void printMetadata(br_const_utemplate t) const - { - const float *metadata = reinterpret_cast(&t->data[768]); - cout << ", \"X\":" << metadata[0] - << ", \"Y\":" << metadata[1] - << ", \"Width\":" << metadata[2] - << ", \"Height\":" << metadata[3] - << ", \"RightEyeX\":" << metadata[4] - << ", \"RightEyeY\":" << metadata[5] - << ", \"LeftEyeX\":" << metadata[6] - << ", \"LeftEyeY\":" << metadata[7]; - } -}; - -static void search_utemplate(br_const_utemplate query, br_callback_context) -{ - SearchResults *searchResults = NULL; - switch (query->algorithmID) { - case 0: searchResults = new VoidSearch(query); break; - case 2: searchResults = new ImageID(query); break; - case -1: searchResults = new FaceRecognition(query); break; - } - if (!searchResults) - qFatal("Unsupported AlgorithmID: %d", query->algorithmID); - - foreach (const MappedGallery &gallery, galleries) - searchResults->consider(gallery); - searchResults->print(); - delete searchResults; -} - -int main(int argc, char *argv[]) -{ - QStringList urls; - for (int i=1; iquiet = true; - br_iterate_utemplates_file(stdin, search_utemplate, NULL, false); - - Context::finalize(); - return EXIT_SUCCESS; -} diff --git a/app/br-serve/CMakeLists.txt b/app/br-serve/CMakeLists.txt deleted file mode 100644 index 6e397e4..0000000 --- a/app/br-serve/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -set(QHTTPSERVER_DIR "${CMAKE_SOURCE_DIR}/3rdparty/qhttpserver") -set(QHTTPSERVER_SRC ${QHTTPSERVER_DIR}/src/qhttpconnection.cpp - ${QHTTPSERVER_DIR}/src/qhttpresponse.cpp - ${QHTTPSERVER_DIR}/src/qhttprequest.cpp - ${QHTTPSERVER_DIR}/src/qhttpserver.cpp - ${QHTTPSERVER_DIR}/http-parser/http_parser.c) -add_definitions(-DQHTTPSERVER_EXPORT) -include_directories(${CMAKE_SOURCE_DIR}/3rdparty/qhttpserver/src - ${CMAKE_SOURCE_DIR}/3rdparty/qhttpserver/http-parser - ${CMAKE_CURRENT_BINARY_DIR}) -add_executable(br-serve br-serve.cpp ${QHTTPSERVER_SRC} ${BR_RESOURCES}) -target_link_libraries(br-serve openbr ${BR_THIRDPARTY_LIBS}) -qt5_use_modules(br-serve ${QT_DEPENDENCIES}) -install(TARGETS br-serve RUNTIME DESTINATION bin) diff --git a/app/br-serve/br-serve.cpp b/app/br-serve/br-serve.cpp deleted file mode 100644 index f257f35..0000000 --- a/app/br-serve/br-serve.cpp +++ /dev/null @@ -1,137 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * Copyright 2014 Noblis * - * * - * 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 -#include -#include -#include -#include -#include - -static void help() -{ - printf("br-serve [command]\n" - "==================\n" - "\n" - "_br-serve_ converts the command's stdin/stdout into a web service.\n" - "\n" - "Optional Arguments\n" - "------------------\n" - "* -help - Print usage information.\n" - "* -port - The port to communicate on (80 otherwise)."); -} - -static int port = 80; -static QProcess process; - -class Handler : public QObject -{ - Q_OBJECT - -public slots: - void handle(QHttpRequest *request, QHttpResponse *response) - { - QByteArray message; - - const QUrlQuery urlQuery(request->url()); - if (urlQuery.hasQueryItem("URL")) { - process.write(qPrintable(QString(urlQuery.queryItemValue("URL") + "\n"))); - process.waitForReadyRead(); - if (process.error() != QProcess::UnknownError) - qFatal("%s\n", qPrintable(process.errorString())); - message = process.readLine(); - response->setHeader("Content-Type", "application/json"); - } else if (urlQuery.hasQueryItem("ImageID")) { - const QByteArray imageID = QByteArray::fromHex(urlQuery.queryItemValue("ImageID").toLatin1()); - if (imageID.size() == 16) { - br_universal_template in; - in.algorithmID = 2; - memcpy(&in.imageID, imageID.data(), 16); - memset(in.templateID, 0, 16); - in.size = 0; - - process.write((const char *)&in, sizeof(br_universal_template)); - process.waitForReadyRead(); - if (process.error() != QProcess::UnknownError) - qFatal("%s\n", qPrintable(process.errorString())); - - br_utemplate out = (br_utemplate) malloc(sizeof(br_universal_template)); - if (process.read((char*) out, sizeof(br_universal_template)) == sizeof(br_universal_template)) { - out = (br_utemplate) realloc(out, sizeof(br_universal_template) + out->size); - if (process.read(reinterpret_cast(out+1), out->size) != out->size) - qFatal("Unexepected EOF when reading universal template data."); - message = QByteArray((char*)&out->data, out->size); - } - free(out); - } - response->setHeader("Content-Type", "image/jpeg"); - } else { - QString path = request->path(); - if (path == "/") - path = "localhost"; - message = QString("\n" - "\n" - "\n" - " Web Services API\n" - "\n" - "\n" - "\n" - "

Query String Parameters

" - "
    \n" - "
  • URL - Query URL for image search.
  • \n" - "
  • ImageID - Query ImageID for image retrieval.
  • \n" - "
\n" - "

Examples

\n" - "
    \n" - "
  • http://%1%2/?URL=data.liblikely.org/misc/lenna.tiff
  • \n" - "
  • http://%1%2/?ImageID=ecaee0b4cd73a76dd2a8060b2909a4a1
  • \n" - "
\n" - "\n" - "").arg(path, port == 80 ? QString() : (QString(":") + QString::number(port))).toLatin1(); - response->setHeader("Content-Type", "text/html"); - } - - response->setHeader("Content-Length", QString::number(message.size())); - response->writeHead(200); // everything is OK - response->write(message); - response->end(); - } -}; - -int main(int argc, char *argv[]) -{ - QCoreApplication application(argc, argv); - - for (int i=1; i