diff --git a/.gitmodules b/.gitmodules index 62baac0..1f3bb8c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,3 @@ -[submodule "openbr/janus"] - path = openbr/janus - url = https://github.com/biometrics/janus.git [submodule "3rdparty/qhttpserver"] path = 3rdparty/qhttpserver url = https://github.com/nikhilm/qhttpserver.git diff --git a/openbr/CMakeLists.txt b/openbr/CMakeLists.txt index 8dac64b..fcc7df0 100644 --- a/openbr/CMakeLists.txt +++ b/openbr/CMakeLists.txt @@ -9,17 +9,6 @@ set(SRC openbr.cpp aux_source_directory(core BR_CORE) include(plugins/plugins.cmake) -# Janus API -option(BR_WITH_JANUS "Build IARPA Janus related applications." ON) -if(BR_WITH_JANUS) - include_directories(janus/include) - install(DIRECTORY janus/include DESTINATION .) - set(BR_JANUS janus.cpp - janus_io.cpp - janus/src/opencv_io/opencv_io.cpp) - add_definitions(-DJANUS_LIBRARY) -endif() - # Optional GUI module if(NOT BR_EMBEDDED) aux_source_directory(gui BR_GUI) @@ -46,16 +35,6 @@ if(BR_WITH_DLIB) add_dependencies(openbr dlib) endif() -# Janus implementation -if(BR_WITH_JANUS) - set(JANUS_BUILD_PP5_WRAPPER ${BR_WITH_PP5} CACHE BOOL "Build Janus implementation using PittPatt 5") - set(JANUS_BUILD_DOCS ${BR_BUILD_DOCUMENTATION} CACHE BOOL "Build Janus HTML Doxygen documentation") - mark_as_advanced(JANUS_BUILD_PP5_WRAPPER) - mark_as_advanced(JANUS_BUILD_DOCS) - set(JANUS_IMPLEMENTATION openbr) - add_subdirectory(janus) -endif() - # Install install(TARGETS openbr RUNTIME DESTINATION bin diff --git a/openbr/janus b/openbr/janus deleted file mode 160000 index bab25ea..0000000 --- a/openbr/janus +++ /dev/null @@ -1 +0,0 @@ -Subproject commit bab25ea9b9f26791859415abe953f6df82ace86e diff --git a/openbr/janus.cpp b/openbr/janus.cpp deleted file mode 100644 index 98dae14..0000000 --- a/openbr/janus.cpp +++ /dev/null @@ -1,310 +0,0 @@ -#include "iarpa_janus.h" -#include "iarpa_janus_io.h" -#include "openbr_plugin.h" -#include "openbr/core/opencvutils.h" -#include "openbr/core/common.h" -#include -using namespace br; - -static QSharedPointer detect; -static QSharedPointer augment; -static QSharedPointer distance; - -size_t janus_max_template_size() -{ - return 102400;// 100 KB -} - -janus_error janus_initialize(const char *sdk_path, const char *temp_path, const char *model_file) -{ - int argc = 1; - const char *argv[1] = { "janus" }; - Context::initialize(argc, (char**)argv, sdk_path, false); - Globals->quiet = true; - Globals->enrollAll = true; - Globals->file.set(QString("temp_path"), QString(temp_path)); - const QString algorithm = model_file; - detect.reset(Transform::make("Cvt(Gray)+Cascade(FrontalFace,ROCMode=true)", NULL)); - if (algorithm.isEmpty()) { - augment.reset(Transform::make("Cvt(Gray)+Affine(88,88,0.25,0.35)+++", NULL)); - distance = Distance::fromAlgorithm("FaceRecognition"); - } else { - augment = Transform::fromAlgorithm(algorithm); - distance = Distance::fromAlgorithm(algorithm); - } - return JANUS_SUCCESS; -} - -janus_error janus_finalize() -{ - detect.reset(); - augment.reset(); - distance.reset(); - Context::finalize(); - return JANUS_SUCCESS; -} - -struct janus_template_type : public Template -{}; - -janus_error janus_allocate_template(janus_template *template_) -{ - *template_ = new janus_template_type(); - return JANUS_SUCCESS; -} - -bool compareConfidence(Template a, Template b) { return (a.file.get("Confidence") > b.file.get("Confidence")); } - -janus_error janus_detect(const janus_image image, janus_attributes *attributes_array, const size_t num_requested, size_t *num_actual) -{ - TemplateList src, dst; - - Template t; - cv::Mat input(image.height, - image.width, - image.color_space == JANUS_GRAY8 ? CV_8UC1 : CV_8UC3, - image.data); - - t.append(input); - src.append(t); - detect->project(src, dst); - *num_actual = dst.size(); - if (dst.size() == 0) - return JANUS_FAILURE_TO_DETECT; - - // Sort by confidence, descending - std::sort(dst.begin(), dst.end(), compareConfidence); - - size_t count = 0; - foreach (const Template &temp, dst) { - QRectF rect = temp.file.rects().first(); - attributes_array->face_x = rect.x(); - attributes_array->face_y = rect.y(); - attributes_array->face_width = rect.width(); - attributes_array->face_height = rect.height(); - attributes_array->detection_confidence = temp.file.get("Confidence"); - attributes_array++; - if (++count >= num_requested) - break; - } - attributes_array -= count; - return JANUS_SUCCESS; -} - -janus_error janus_augment(const janus_image image, janus_attributes *attributes, janus_template template_) -{ - Template t; - if (std::isnan(attributes->face_x) || - std::isnan(attributes->face_y) || - std::isnan(attributes->face_width) || - std::isnan(attributes->face_height)) - return JANUS_MISSING_ATTRIBUTES; - - QRectF rect(attributes->face_x, - attributes->face_y, - attributes->face_width, - attributes->face_height); - - if (rect.x() < 0) rect.setX(0); - if (rect.y() < 0) rect.setY(0); - if (rect.x() + rect.width() > image.width) rect.setWidth(image.width - rect.x()); - if (rect.y() + rect.height() > image.height) rect.setHeight(image.height - rect.y()); - - cv::Mat input(image.height, - image.width, - image.color_space == JANUS_GRAY8 ? CV_8UC1 : CV_8UC3, - image.data); - - input = input(cv::Rect(rect.x(), rect.y(), rect.width(), rect.height())).clone(); - t.append(input); - if (!std::isnan(attributes->right_eye_x) && - !std::isnan(attributes->right_eye_y) && - !std::isnan(attributes->left_eye_x) && - !std::isnan(attributes->left_eye_y)) { - t.file.set("Affine_0", QPointF(attributes->right_eye_x - rect.x(), attributes->right_eye_y - rect.y())); - t.file.set("Affine_1", QPointF(attributes->left_eye_x - rect.x(), attributes->left_eye_y - rect.y())); - t.file.set("First_Eye", t.file.get("Affine_0")); - t.file.set("Second_Eye", t.file.get("Affine_1")); - t.file.appendPoint(t.file.get("Affine_0")); - t.file.appendPoint(t.file.get("Affine_1")); - } - Template u; - augment->project(t, u); - if (u.file.fte) u.m() = cv::Mat(); - template_->append(u); - return (u.isEmpty() || !u.first().data) ? JANUS_FAILURE_TO_ENROLL : JANUS_SUCCESS; -} - -janus_error janus_flatten_template(janus_template template_, janus_flat_template flat_template, size_t *bytes) -{ - *bytes = 0; - foreach (const cv::Mat &m, *template_) { - if (!m.data) - continue; - - if (!m.isContinuous()) - return JANUS_UNKNOWN_ERROR; - - const size_t templateBytes = m.rows * m.cols * m.elemSize(); - if (*bytes + sizeof(size_t) + templateBytes > janus_max_template_size()) - break; - - memcpy(flat_template, &templateBytes, sizeof(templateBytes)); - flat_template += sizeof(templateBytes); - *bytes += sizeof(templateBytes); - - memcpy(flat_template, m.data, templateBytes); - flat_template += templateBytes; - *bytes += templateBytes; - } - return JANUS_SUCCESS; -} - -janus_error janus_free_template(janus_template template_) -{ - delete template_; - return JANUS_SUCCESS; -} - -struct janus_gallery_type : public QList -{}; - -void unflatten_template(const janus_flat_template flat_template, const size_t template_bytes, janus_gallery gallery, const janus_template_id template_id) -{ - janus_template t; - JANUS_ASSERT(janus_allocate_template(&t)) - t->file.set("TEMPLATE_ID", QString::number((int)template_id)); - janus_flat_template flat_template_ = flat_template; - - while (flat_template_ < flat_template + template_bytes) { - size_t bytes = *reinterpret_cast(flat_template_); - flat_template_ += sizeof(bytes); - - t->append(cv::Mat(1, bytes, CV_8UC1, flat_template_).clone()); - flat_template_ += bytes; - } - gallery->append(t); -} - -janus_error janus_write_gallery(const janus_flat_template *templates, const size_t *templates_bytes, const janus_template_id *template_ids, const size_t num_templates, janus_gallery_path gallery_path) -{ - std::ofstream file; - file.open(gallery_path, std::ios::out | std::ios::binary); - - for (size_t i=0; i(templates_); - templates_ += sizeof(janus_template_id); - const size_t template_bytes = *reinterpret_cast(templates_); - templates_ += sizeof(size_t); - - janus_flat_template flat_template = new janus_data[template_bytes]; - memcpy(flat_template, templates_, template_bytes); - templates_ += template_bytes; - - unflatten_template(flat_template, template_bytes, *gallery, template_id); - delete[] flat_template; - } - - delete[] templates; - return JANUS_SUCCESS; -} - -janus_error janus_close_gallery(janus_gallery gallery) -{ - delete gallery; - return JANUS_SUCCESS; -} - -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) -{ - *similarity = 0; - - int comparisons = 0; - janus_flat_template a_template = a; - while (a_template < a + a_bytes) { - const size_t a_template_bytes = *reinterpret_cast(a_template); - a_template += sizeof(a_template_bytes); - janus_flat_template b_template = b; - while (b_template < b + b_bytes) { - const size_t b_template_bytes = *reinterpret_cast(b_template); - b_template += sizeof(b_template_bytes); - *similarity += distance->compare(cv::Mat(1, a_template_bytes, CV_8UC1, a_template), - cv::Mat(1, b_template_bytes, CV_8UC1, b_template)); - comparisons++; - - b_template += b_template_bytes; - } - - a_template += a_template_bytes; - } - - if (*similarity != *similarity) // True for NaN - return JANUS_UNKNOWN_ERROR; - - if (comparisons > 0) *similarity /= comparisons; - else *similarity = -std::numeric_limits::max(); - return JANUS_SUCCESS; -} - -janus_error janus_search(const janus_flat_template probe, const size_t probe_bytes, const janus_gallery gallery, const size_t requested_returns, janus_template_id *template_ids, float *similarities, size_t *actual_returns) -{ - typedef QPair Pair; - QList comparisons; comparisons.reserve(requested_returns); - foreach (const janus_template &target_template, *gallery) { - janus_template_id target_id = target_template->file.get("TEMPLATE_ID"); - - size_t target_bytes; - janus_data *buffer = new janus_data[janus_max_template_size()]; - JANUS_ASSERT(janus_flatten_template(target_template, buffer, &target_bytes)) - - janus_flat_template target_flat = new janus_data[target_bytes]; - memcpy(target_flat, buffer, target_bytes); - - float similarity; - JANUS_ASSERT(janus_verify(probe, probe_bytes, target_flat, target_bytes, &similarity)) - if ((size_t)comparisons.size() < requested_returns) { - comparisons.append(Pair(similarity, target_id)); - std::sort(comparisons.begin(), comparisons.end()); - } else { - Pair temp = comparisons.first(); - if (temp.first < similarity) { - comparisons.removeFirst(); - comparisons.append(Pair(similarity, target_id)); - std::sort(comparisons.begin(), comparisons.end()); - } - } - delete[] buffer; - delete[] target_flat; - } - *actual_returns = comparisons.size(); - QList temp; temp.reserve(comparisons.size()); - std::reverse_copy(comparisons.begin(), comparisons.end(), std::back_inserter(temp)); - comparisons = temp; - foreach(const Pair &comparison, comparisons) { - *similarities = comparison.first; similarities++; - *template_ids = comparison.second; template_ids++; - } - return JANUS_SUCCESS; -} diff --git a/openbr/janus_io.cpp b/openbr/janus_io.cpp deleted file mode 100644 index 9895fbf..0000000 --- a/openbr/janus_io.cpp +++ /dev/null @@ -1,79 +0,0 @@ -#include - -#define JANUS_CUSTOM_ADD_SAMPLE -#define JANUS_CUSTOM_CREATE_GALLERY -#define JANUS_CUSTOM_CREATE_TEMPLATES -#include "janus/src/janus_io.cpp" - -static void _janus_add_sample(vector &samples, double sample) -{ - static QMutex sampleLock; - QMutexLocker sampleLocker(&sampleLock); - samples.push_back(sample); -} - -typedef QPair TemplatePair; - -TemplatePair _janus_create_flat_template(const char *data_path, TemplateData templateData, bool verbose) -{ - janus_template template_; - janus_template_id templateID; - JANUS_ASSERT(TemplateIterator::create(data_path, templateData, &template_, &templateID, verbose)) - templateData.release(); - return TemplatePair(templateID, FlatTemplate(template_)); -} - -janus_error janus_create_gallery(const char *data_path, janus_metadata metadata, janus_gallery_path gallery_path, int verbose) -{ - TemplateIterator ti(metadata, true); - TemplateData templateData = ti.next(); - QFutureSynchronizer futures; - while (!templateData.templateIDs.empty()) { - futures.addFuture(QtConcurrent::run(_janus_create_flat_template, data_path, templateData, verbose)); - templateData = ti.next(); - } - futures.waitForFinished(); - QList< QFuture > flat_templates = futures.futures(); - - vector templates; - vector template_bytes; - vector template_ids; - size_t num_templates = 0; - - foreach (const QFuture &future, flat_templates) { - template_ids.push_back(future.result().first); - template_bytes.push_back(future.result().second.data->bytes); - templates.push_back(future.result().second.data->flat_template); - num_templates++; - } - - JANUS_ASSERT(janus_write_gallery(&templates[0], &template_bytes[0], &template_ids[0], num_templates, gallery_path)) - return JANUS_SUCCESS; -} - -janus_error janus_create_templates(const char *data_path, janus_metadata metadata, const char *gallery_file, int verbose) -{ - TemplateIterator ti(metadata, true); - TemplateData templateData = ti.next(); - - QFutureSynchronizer futures; - while (!templateData.templateIDs.empty()) { - futures.addFuture(QtConcurrent::run(_janus_create_flat_template, data_path, templateData, verbose)); - templateData = ti.next(); - } - futures.waitForFinished(); - QList< QFuture > flat_templates = futures.futures(); - - std::ofstream file; - file.open(gallery_file, std::ios::out | std::ios::binary); - foreach (const QFuture &future, flat_templates) { - janus_template_id templateID = future.result().first; - FlatTemplate flatTemplate = future.result().second; - file.write((char*)&templateID, sizeof(templateID)); - file.write((char*)&flatTemplate.data->bytes, sizeof(flatTemplate.data->bytes)); - file.write((char*)flatTemplate.data->flat_template, flatTemplate.data->bytes); - } - - file.close(); - return JANUS_SUCCESS; -}