From d6a776c41b86feae0819edbb17273e15f209ae04 Mon Sep 17 00:00:00 2001 From: Norihiro Kamae Date: Wed, 26 Apr 2023 21:32:51 +0900 Subject: [PATCH] Separate detector data from face-detector-dlib-hog --- CMakeLists.txt | 10 ++++++ src/face-detector-dlib-hog-datagen.cpp | 10 ++++++ src/face-detector-dlib-hog.cpp | 50 ++++++++++++++++++-------- src/face-detector-dlib-hog.h | 2 ++ src/face-tracker-manager.cpp | 17 ++++++++- src/face-tracker-manager.hpp | 1 + 6 files changed, 74 insertions(+), 16 deletions(-) create mode 100644 src/face-detector-dlib-hog-datagen.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 3b5e372..2fc0c47 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,6 +11,7 @@ option(WITH_PTZ_TCP "Enable to connect PTZ camera through TCP socket" ON) option(ENABLE_MONITOR_USER "Enable monitor source for user" OFF) option(ENABLE_DEBUG_DATA "Enable property to save error and control data" OFF) option(WITH_DOCK "Enable dock" ON) +option(ENABLE_DATAGEN "Enable generating data" OFF) set(CMAKE_PREFIX_PATH "${QTDIR}") set(CMAKE_AUTOMOC ON) @@ -139,3 +140,12 @@ endif() setup_plugin_target(${CMAKE_PROJECT_NAME}) configure_file(installer/installer-macOS.pkgproj.in installer-macOS.generated.pkgproj) + +if(ENABLE_DATAGEN) + add_executable(face-detector-dlib-hog-datagen + src/face-detector-dlib-hog-datagen.cpp + ) + target_link_libraries(face-detector-dlib-hog-datagen + dlib + ) +endif() diff --git a/src/face-detector-dlib-hog-datagen.cpp b/src/face-detector-dlib-hog-datagen.cpp new file mode 100644 index 0000000..4e17593 --- /dev/null +++ b/src/face-detector-dlib-hog-datagen.cpp @@ -0,0 +1,10 @@ +#include "plugin-macros.generated.h" +#include +#include + +int main() +{ + std::cout << dlib::get_serialized_frontal_faces(); + return 0; +} + diff --git a/src/face-detector-dlib-hog.cpp b/src/face-detector-dlib-hog.cpp index d6e1fde..569363f 100644 --- a/src/face-detector-dlib-hog.cpp +++ b/src/face-detector-dlib-hog.cpp @@ -13,17 +13,17 @@ struct face_detector_dlib_private_s { std::shared_ptr tex; std::vector rects; - dlib::frontal_face_detector *detector; + dlib::frontal_face_detector detector; + bool detector_loaded = false; + bool has_error = false; + std::string model_filename; int crop_l = 0, crop_r = 0, crop_t = 0, crop_b = 0; int n_error = 0; face_detector_dlib_private_s() { - detector = NULL; } ~face_detector_dlib_private_s() { - if (detector) - delete detector; } }; @@ -89,18 +89,30 @@ void face_detector_dlib_hog::detect_main() p->n_error--; } - if (!p->detector) - p->detector = new dlib::frontal_face_detector(dlib::get_frontal_face_detector()); + if (!p->detector_loaded) { + p->detector_loaded = true; + try { + blog(LOG_INFO, "loading file '%s'", p->model_filename.c_str()); + dlib::deserialize(p->model_filename.c_str()) >> p->detector; + p->has_error = false; + } + catch(...) { + blog(LOG_ERROR, "failed to load file '%s'", p->model_filename.c_str()); + p->has_error = true; + } + } - std::vector dets = (*p->detector)(img); - p->rects.resize(dets.size()); - for (size_t i=0; irects[i]; - r.x0 = (dets[i].left() + x0) * p->tex->scale; - r.y0 = (dets[i].top() + y0) * p->tex->scale; - r.x1 = (dets[i].right() + x0) * p->tex->scale; - r.y1 = (dets[i].bottom() + y0) * p->tex->scale; - r.score = 1.0; // TODO: implement me + if (!p->has_error) { + std::vector dets = p->detector(img); + p->rects.resize(dets.size()); + for (size_t i=0; irects[i]; + r.x0 = (dets[i].left() + x0) * p->tex->scale; + r.y0 = (dets[i].top() + y0) * p->tex->scale; + r.x1 = (dets[i].right() + x0) * p->tex->scale; + r.y1 = (dets[i].bottom() + y0) * p->tex->scale; + r.score = 1.0; // TODO: implement me + } } p->tex.reset(); @@ -110,3 +122,11 @@ void face_detector_dlib_hog::get_faces(std::vector &rects) { rects = p->rects; } + +void face_detector_dlib_hog::set_model(const char *filename) +{ + if (p->model_filename != filename) { + p->model_filename = filename; + p->detector_loaded = false; + } +} diff --git a/src/face-detector-dlib-hog.h b/src/face-detector-dlib-hog.h index ccc17c7..5d809f1 100644 --- a/src/face-detector-dlib-hog.h +++ b/src/face-detector-dlib-hog.h @@ -14,4 +14,6 @@ class face_detector_dlib_hog : public face_detector_base virtual ~face_detector_dlib_hog(); void set_texture(std::shared_ptr &, int crop_l, int crop_r, int crop_t, int crop_b) override; void get_faces(std::vector &) override; + + void set_model(const char *filename); }; diff --git a/src/face-tracker-manager.cpp b/src/face-tracker-manager.cpp index 4899b7a..1c52d90 100644 --- a/src/face-tracker-manager.cpp +++ b/src/face-tracker-manager.cpp @@ -13,6 +13,7 @@ #define debug_detect(fmt, ...) #define debug_track_thread(fmt, ...) // blog(LOG_INFO, fmt, __VA_ARGS__) +#define DIR_DLIB_HOG "dlib_hog_model" #define DIR_DLIB_CNN "dlib_cnn_model" #define DIR_DLIB_LANDMARK "dlib_face_landmark_model" @@ -189,7 +190,11 @@ inline void face_tracker_manager::stage_to_detector() detect->set_texture(cvtex, detector_crop_l, detector_crop_r, detector_crop_t, detector_crop_b ); - if (detector_engine == engine_dlib_cnn) { + if (detector_engine == engine_dlib_hog) { + if (auto *d = dynamic_cast(detect)) + d->set_model(detector_dlib_hog_model.c_str()); + } + else if (detector_engine == engine_dlib_cnn) { if (auto *d = dynamic_cast(detect)) d->set_model(detector_dlib_cnn_model.c_str()); } @@ -376,6 +381,7 @@ void face_tracker_manager::update(obs_data_t *settings) auto _detector_engine = (enum detector_engine_e)obs_data_get_int(settings, "detector_engine"); if (_detector_engine != detector_engine) update_detector(this, _detector_engine); + detector_dlib_hog_model = obs_data_get_string(settings, "detector_dlib_hog_model"); detector_dlib_cnn_model = obs_data_get_string(settings, "detector_dlib_cnn_model"); detector_crop_l = obs_data_get_int(settings, "detector_crop_l"); detector_crop_r = obs_data_get_int(settings, "detector_crop_r"); @@ -414,6 +420,8 @@ void face_tracker_manager::get_properties(obs_properties_t *pp) OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT); obs_property_list_add_int(p, obs_module_text("Detector.dlib.hog"), (int)engine_dlib_hog); obs_property_list_add_int(p, obs_module_text("Detector.dlib.cnn"), (int)engine_dlib_cnn); + obs_properties_add_path(pp, "detector_dlib_hog_model", obs_module_text("Dlib HOG model"), + OBS_PATH_FILE, "Data Files (*.dat);;" "All Files (*.*)", (data_path + "/" DIR_DLIB_CNN).c_str() ); obs_properties_add_path(pp, "detector_dlib_cnn_model", obs_module_text("Dlib CNN model"), OBS_PATH_FILE, "Data Files (*.dat);;" "All Files (*.*)", (data_path + "/" DIR_DLIB_CNN).c_str() ); obs_properties_add_int(pp, "detector_crop_l", obs_module_text("Crop left for detector"), 0, 1920, 1); @@ -445,6 +453,13 @@ void face_tracker_manager::get_defaults(obs_data_t *settings) obs_data_set_default_bool(settings, "tracking_th_en", true); obs_data_set_default_double(settings, "tracking_th_dB", -80.0); + if (char *f = obs_module_file(DIR_DLIB_HOG "/frontal_face_detector.dat")) { + obs_data_set_default_string(settings, "detector_dlib_hog_model", f); + bfree(f); + } else { + blog(LOG_ERROR, "frontal_face_detector.dat is not found in the data directory."); + } + if (char *f = obs_module_file(DIR_DLIB_CNN "/mmod_human_face_detector.dat")) { obs_data_set_default_string(settings, "detector_dlib_cnn_model", f); bfree(f); diff --git a/src/face-tracker-manager.hpp b/src/face-tracker-manager.hpp index fbba09f..fffe604 100644 --- a/src/face-tracker-manager.hpp +++ b/src/face-tracker-manager.hpp @@ -45,6 +45,7 @@ class face_tracker_manager volatile bool reset_requested; float tracking_threshold; enum detector_engine_e detector_engine = engine_uninitialized; + std::string detector_dlib_hog_model; std::string detector_dlib_cnn_model; int detector_crop_l, detector_crop_r, detector_crop_t, detector_crop_b; char *landmark_detection_data;