From 61307089dfeec291f6482421ec9b25d9c863e8af Mon Sep 17 00:00:00 2001 From: Roy Shilkrot Date: Thu, 9 May 2024 10:47:14 -0400 Subject: [PATCH 1/4] feat: Add support for loading custom ONNX detection models --- README.md | 1 + data/locale/en-US.ini | 2 ++ src/detect-filter.cpp | 53 +++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 54 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ca56ef7..2f7947f 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,7 @@ Current features: - Detect over 80 categories of objects, using an efficient model ([EdgeYOLO](https://github.com/LSH9832/edgeyolo)) - 3 Model sizes: Small, Medium and Large +- Load custom ONNX detection models from disk - Control detection threshold - Select object category filter (e.g. find only "Person") - Masking: Blur, Solid color, Transparent, output binary mask (combine with other plugins!) diff --git a/data/locale/en-US.ini b/data/locale/en-US.ini index fa8f5ee..890e723 100644 --- a/data/locale/en-US.ini +++ b/data/locale/en-US.ini @@ -29,3 +29,5 @@ ZoomObject="Zoom Object" SingleFirst="Single (First)" ZoomSpeed="Zoom Speed" DetectedObject="Detected Object" +ExternalModel="External Model" +ModelPath="Model Path" diff --git a/src/detect-filter.cpp b/src/detect-filter.cpp index a2ec0ca..5988dcf 100644 --- a/src/detect-filter.cpp +++ b/src/detect-filter.cpp @@ -230,6 +230,21 @@ obs_properties_t *detect_filter_properties(void *data) obs_property_list_add_string(model_size, obs_module_text("SmallFast"), "small"); obs_property_list_add_string(model_size, obs_module_text("Medium"), "medium"); obs_property_list_add_string(model_size, obs_module_text("LargeSlow"), "large"); + obs_property_list_add_string(model_size, obs_module_text("ExternalModel"), + "!!!external!!!"); + + // add external model file path + obs_properties_add_path(props, "model_file", obs_module_text("ModelPath"), OBS_PATH_FILE, + "EdgeYOLO onnx files (*.onnx);;all files (*.*)", nullptr); + + // add callback to show/hide the external model file path + obs_property_set_modified_callback(model_size, [](obs_properties_t *props_, + obs_property_t *p, obs_data_t *settings) { + const char *model_size_value = obs_data_get_string(settings, "model_size"); + obs_property_t *prop = obs_properties_get(props_, "model_file"); + obs_property_set_visible(prop, strcmp(model_size_value, "!!!external!!!") == 0); + return true; + }); // Add a informative text about the plugin std::string basic_info = @@ -339,9 +354,15 @@ void detect_filter_update(void *data, obs_data_t *settings) } else if (newModelSize == "medium") { modelFilepath_rawPtr = obs_module_file("models/edgeyolo_tiny_lrelu_coco_480x800.onnx"); - } else { + } else if (newModelSize == "large") { modelFilepath_rawPtr = obs_module_file("models/edgeyolo_tiny_lrelu_coco_736x1280.onnx"); + } else if (newModelSize == "!!!external!!!") { + modelFilepath_rawPtr = bstrdup(obs_data_get_string(settings, "model_file")); + } else { + obs_log(LOG_ERROR, "Invalid model size: %s", newModelSize.c_str()); + tf->isDisabled = true; + return; } if (modelFilepath_rawPtr == nullptr) { @@ -361,6 +382,7 @@ void detect_filter_update(void *data, obs_data_t *settings) #else tf->modelFilepath = std::string(modelFilepath_rawPtr); #endif + bfree(modelFilepath_rawPtr); // Re-initialize model if it's not already the selected one or switching inference device tf->useGPU = newUseGpu; @@ -391,6 +413,33 @@ void detect_filter_update(void *data, obs_data_t *settings) tf->edgeyolo.reset(); return; } + + // If this is an external model - look for the labels file + if (tf->modelSize == "!!!external!!!") { +#ifdef _WIN32 + std::wstring labelsFilepath = tf->modelFilepath; + labelsFilepath.replace(labelsFilepath.find(L".onnx"), 5, L".txt"); +#else + std::string labelsFilepath = tf->modelFilepath; + labelsFilepath.replace(labelsFilepath.find(".onnx"), 5, ".txt"); +#endif + std::ifstream labelsFile(labelsFilepath); + if (labelsFile.is_open()) { + std::string line; + std::vector labels; + while (std::getline(labelsFile, line)) { + labels.push_back(line); + } + labelsFile.close(); + } else { + obs_log(LOG_ERROR, "Failed to load labels file: %s", + labelsFilepath.c_str()); + // disable filter + tf->isDisabled = true; + tf->edgeyolo.reset(); + return; + } + } } // update threshold on edgeyolo @@ -426,7 +475,7 @@ void detect_filter_update(void *data, obs_data_t *settings) obs_data_get_string(settings, "zoom_object")); obs_log(LOG_INFO, " Disabled: %s", tf->isDisabled ? "true" : "false"); #ifdef _WIN32 - obs_log(LOG_INFO, " Model file path: %S", tf->modelFilepath.c_str()); + obs_log(LOG_INFO, " Model file path: %ls", tf->modelFilepath.c_str()); #else obs_log(LOG_INFO, " Model file path: %s", tf->modelFilepath.c_str()); #endif From 94fa2a23f1df0e394f61feca1fbead8484715ddf Mon Sep 17 00:00:00 2001 From: Roy Shilkrot Date: Thu, 9 May 2024 16:35:51 -0400 Subject: [PATCH 2/4] chore: Add classNames vector to FilterData.h and include vendor folder in CMakeLists.txt --- CMakeLists.txt | 3 + docs/train_model.md | 85 +++++++++++++++-- src/FilterData.h | 1 + src/detect-filter.cpp | 217 +++++++++++++++++++++++++++++++----------- 4 files changed, 242 insertions(+), 64 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c52f9a6..b0c0baa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -77,6 +77,9 @@ else() target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE OpenCV) endif() +# add the vendor folder to the include path +target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE vendor) + target_sources(${CMAKE_PROJECT_NAME} PRIVATE src/plugin-main.c src/detect-filter.cpp src/detect-filter-info.c src/obs-utils/obs-utils.cpp src/edgeyolo/edgeyolo_onnxruntime.cpp) diff --git a/docs/train_model.md b/docs/train_model.md index 0b0846d..637de8a 100644 --- a/docs/train_model.md +++ b/docs/train_model.md @@ -9,6 +9,12 @@ In this example we will use a COCO dataset from Roboflow. You can get the datase The dataset is in the COCO format, so we can use it directly with the EdgeYOLO training script. +### Enviroment requirements + +You will need a GPU to train the model. The training process is quite slow on a CPU. + +On Windows you can should the Windows Subsystem for Linux (WSL) to run the training script. + ## Step 1: Unpack the dataset Unzip the dataset to a folder. The dataset should have the following structure: @@ -32,7 +38,15 @@ dataset_folder/ ... ``` -## Step 2: Install the required packages +## Step 2: Install the required files + +Go to the EdgeYOLO repository and clone it to your machine: + +```bash +git clone git@github.com:LSH9832/edgeyolo.git +``` + +The rest of this guide assumes you have the EdgeYOLO repository cloned to your machine and you are in the root of that repository. You need to install the required packages to train the model. You can install them using the following command: @@ -40,16 +54,18 @@ You need to install the required packages to train the model. You can install th pip install -r requirements.txt ``` +**Make sure to download a pretrained model** from the EdgeYOLO repository. You can download e.g. the EdgeYOLO Tiny LRELU model from [here](https://github.com/LSH9832/edgeyolo/releases/download/v0.0.0/edgeyolo_tiny_lrelu_coco.pth). This will speed up your process tremendously. + ## Step 3: Setup the parameters of the training script -You need to set the parameters of the training script. +You need to set the parameters of the training script to train on your data. Make a copy of the configuration file and set the parameters according to your needs. For example for my case, I will set the following parameters in the `params/train/train_coco_aquarium.yaml` file: ```yaml # models & weights------------------------------------------------------------------------------------------------------ -model_cfg: "params/model/edgeyolo_tiny.yaml" # model structure config file -weights: "output/train/edgeyolo_tiny_coco_aquarium/last.pth" # contains model_cfg, set null or a no-exist filename if not use it +model_cfg: "params/model/edgeyolo_tiny_lrelu_aquarium.yaml" # model structure config file +weights: "**!! Set this to the path of your pretrained .pth model !!**" # contains model_cfg, set null or a no-exist filename if not use it use_cfg: false # force using model_cfg instead of cfg in weights to build model # output---------------------------------------------------------------------------------------------------------------- @@ -63,7 +79,26 @@ batch_size_per_gpu: 8 # batch size for each GPU loader_num_workers: 4 # number data loader workers for each GPU num_threads: 1 # pytorch threads number for each GPU -# the rest-------------------------------------------------------------------------------------------------------------- +# device & data type---------------------------------------------------------------------------------------------------- +device: [0] # training device list +fp16: false # train with fp16 precision +cudnn_benchmark: false # it's useful when multiscale_range is set zero + +# the rest of the file ... +``` + +Note the gpu device number in the `device` field. You can set it to `[0]` if you have only one GPU. + +Note that the `model_cfg` field points to the model configuration file. You can find the model configuration files in the `params/model/` folder. This is required to set the model architecture, but mostly the number of classes. Make a copy of one of the architechtures with a new filename. This is an example of the top of my new `edgeyolo_tiny_lrelu_aquarium.yaml` file: + +```yaml +# parameters +nc: 6 # number of classes - match the number of classes in the dataset +depth_multiple: 1.0 # model depth multiple +width_multiple: 1.0 # layer channel multiple + +# anchors +# ... ``` You will also need to set up the dataset configuration file `params/dataset/coco_aquarium.yaml`: @@ -86,13 +121,41 @@ val: label: "<...>/Downloads/edgeyolo/Aquarium Combined.v2-raw-1024.coco/valid/_annotations.coco.json" test: - test_dir: "test2017" + image_dir: "<...>/Downloads/edgeyolo/Aquarium Combined.v2-raw-1024.coco/test" + label: "<...>/Downloads/edgeyolo/Aquarium Combined.v2-raw-1024.coco/test/_annotations.coco.json" segmentaion_enabled: false names: ["creatures", "fish", "jellyfish", "penguin", "puffin", "shark", "starfish", "stingray"] ``` +Notice that you need to provide the list of classes in the `names` field. This should match the classes in the dataset. + +For example in the Aquarim dataset we will see in the `train/annotations.json` a field like so: + +```json + "categories": [ + { + "id": 0, + "name": "creatures", + "supercategory": "none" + }, + { + "id": 1, + "name": "fish", + "supercategory": "creatures" + }, + { + "id": 2, + "name": "jellyfish", + "supercategory": "creatures" + }, + ... + ] +``` + +Make sure the order from `categories` (and the `id` field) is maintained in the `names` field. + ## Step 4: Train the model You can train the model using the following command: @@ -109,11 +172,15 @@ Best to have a GPU for training. After training the model, you can convert it to ONNX format using the `export.py` script from EdgeYOLO. ```bash -python export.py --weights output/train/edgeyolo_tiny_coco_aquarium/last.pth --onnx-only +python export.py --weights output/train/edgeyolo_tiny_coco_aquarium/best.pth --onnx-only --batch 1 ``` -You will find the ONNX model in the `output/export/` folder. +You will find the ONNX model in the `output/export/` folder, e.g. `output/export/best/640x640_batch1.onnx`. Rename the file to something more descriptive. ## Step 6: Use the model with OBS Detect -TBD +You can now use the ONNX model with the OBS Detect plugin. Just load the model from the plugin settings. + +![alt text](image.png) + +You will also need a configuration file for the model but that is created automatically by the export script above. It will have the same name as the ONNX model but with a `.json` extension. diff --git a/src/FilterData.h b/src/FilterData.h index 91538c7..0b70a45 100644 --- a/src/FilterData.h +++ b/src/FilterData.h @@ -47,6 +47,7 @@ struct filter_data { std::mutex modelMutex; std::unique_ptr edgeyolo; + std::vector classNames; #if _WIN32 std::wstring modelFilepath; diff --git a/src/detect-filter.cpp b/src/detect-filter.cpp index 5988dcf..b5c318d 100644 --- a/src/detect-filter.cpp +++ b/src/detect-filter.cpp @@ -18,12 +18,16 @@ #include #include +#include + #include #include "FilterData.h" #include "consts.h" #include "obs-utils/obs-utils.h" #include "edgeyolo/utils.hpp" +#define EXTERNAL_MODEL_SIZE "!!!EXTERNAL_MODEL!!!" + struct detect_filter : public filter_data {}; const char *detect_filter_getname(void *unused) @@ -57,20 +61,12 @@ static bool enable_advanced_settings(obs_properties_t *ppts, obs_property_t *p, return true; } -obs_properties_t *detect_filter_properties(void *data) +void set_class_names_on_object_category(obs_property_t *object_category, + std::vector class_names) { - obs_properties_t *props = obs_properties_create(); - - obs_properties_add_bool(props, "preview", obs_module_text("Preview")); - - // add dropdown selection for object category selection: "All", or COCO classes - obs_property_t *object_category = - obs_properties_add_list(props, "object_category", obs_module_text("ObjectCategory"), - OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT); - obs_property_list_add_int(object_category, obs_module_text("All"), -1); std::vector> indexed_classes; - for (size_t i = 0; i < edgeyolo_cpp::COCO_CLASSES.size(); ++i) { - const std::string &class_name = edgeyolo_cpp::COCO_CLASSES[i]; + for (size_t i = 0; i < class_names.size(); ++i) { + const std::string &class_name = class_names[i]; // capitalize the first letter of the class name std::string class_name_cap = class_name; class_name_cap[0] = (char)std::toupper((int)class_name_cap[0]); @@ -82,11 +78,66 @@ obs_properties_t *detect_filter_properties(void *data) [](const std::pair &a, const std::pair &b) { return a.second < b.second; }); + // clear the object category list + obs_property_list_clear(object_category); + + // add the sorted classes to the property list + obs_property_list_add_int(object_category, obs_module_text("All"), -1); + // add the sorted classes to the property list for (const auto &indexed_class : indexed_classes) { obs_property_list_add_int(object_category, indexed_class.second.c_str(), (int)indexed_class.first); } +} + +void read_model_config_json_and_set_class_names(const char *model_file, obs_properties_t *props_, + obs_data_t *settings, struct detect_filter *tf_) +{ + if (model_file == nullptr || model_file[0] == '\0' || strlen(model_file) == 0) { + obs_log(LOG_ERROR, "Model file path is empty"); + return; + } + + // read the '.json' file near the model file to find the class names + std::string json_file = model_file; + json_file.replace(json_file.find(".onnx"), 5, ".json"); + std::ifstream file(json_file); + if (!file.is_open()) { + obs_data_set_string(settings, "error", "JSON file not found"); + obs_log(LOG_ERROR, "JSON file not found: %s", json_file.c_str()); + } else { + obs_data_set_string(settings, "error", ""); + // parse the JSON file + nlohmann::json j; + file >> j; + if (j.contains("names")) { + std::vector labels = j["names"]; + set_class_names_on_object_category( + obs_properties_get(props_, "object_category"), labels); + tf_->classNames = labels; + } else { + obs_data_set_string(settings, "error", + "JSON file does not contain 'names' field"); + obs_log(LOG_ERROR, "JSON file does not contain 'names' field"); + } + } +} + +obs_properties_t *detect_filter_properties(void *data) +{ + struct detect_filter *tf = reinterpret_cast(data); + + obs_properties_t *props = obs_properties_create(); + + obs_properties_add_bool(props, "preview", obs_module_text("Preview")); + + // add dropdown selection for object category selection: "All", or COCO classes + obs_property_t *object_category = + obs_properties_add_list(props, "object_category", obs_module_text("ObjectCategory"), + OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT); + set_class_names_on_object_category(object_category, edgeyolo_cpp::COCO_CLASSES); + tf->classNames = edgeyolo_cpp::COCO_CLASSES; // options group for masking obs_properties_t *masking_group = obs_properties_create(); @@ -231,20 +282,59 @@ obs_properties_t *detect_filter_properties(void *data) obs_property_list_add_string(model_size, obs_module_text("Medium"), "medium"); obs_property_list_add_string(model_size, obs_module_text("LargeSlow"), "large"); obs_property_list_add_string(model_size, obs_module_text("ExternalModel"), - "!!!external!!!"); + EXTERNAL_MODEL_SIZE); // add external model file path - obs_properties_add_path(props, "model_file", obs_module_text("ModelPath"), OBS_PATH_FILE, - "EdgeYOLO onnx files (*.onnx);;all files (*.*)", nullptr); + obs_properties_add_path(props, "external_model_file", obs_module_text("ModelPath"), + OBS_PATH_FILE, "EdgeYOLO onnx files (*.onnx);;all files (*.*)", + nullptr); // add callback to show/hide the external model file path - obs_property_set_modified_callback(model_size, [](obs_properties_t *props_, - obs_property_t *p, obs_data_t *settings) { - const char *model_size_value = obs_data_get_string(settings, "model_size"); - obs_property_t *prop = obs_properties_get(props_, "model_file"); - obs_property_set_visible(prop, strcmp(model_size_value, "!!!external!!!") == 0); - return true; - }); + obs_property_set_modified_callback2( + model_size, + [](void *data_, obs_properties_t *props_, obs_property_t *p, obs_data_t *settings) { + struct detect_filter *tf_ = reinterpret_cast(data_); + const char *model_size_value = obs_data_get_string(settings, "model_size"); + obs_log(LOG_INFO, "model_size modified: %s", model_size_value); + bool is_external = strcmp(model_size_value, EXTERNAL_MODEL_SIZE) == 0; + obs_property_t *prop = obs_properties_get(props_, "external_model_file"); + obs_property_set_visible(prop, is_external); + if (!is_external) { + // reset the class names to COCO classes for default models + set_class_names_on_object_category( + obs_properties_get(props_, "object_category"), + edgeyolo_cpp::COCO_CLASSES); + tf_->classNames = edgeyolo_cpp::COCO_CLASSES; + } else { + // if the model path is already set - update the class names + const char *model_file = + obs_data_get_string(settings, "external_model_file"); + read_model_config_json_and_set_class_names(model_file, props_, + settings, tf_); + } + return true; + }, + tf); + + // add callback on the model file path to check if the file exists + obs_property_set_modified_callback2( + obs_properties_get(props, "external_model_file"), + [](void *data_, obs_properties_t *props_, obs_property_t *p, obs_data_t *settings) { + obs_log(LOG_INFO, "external_model_file modified"); + const char *model_size_value = obs_data_get_string(settings, "model_size"); + bool is_external = strcmp(model_size_value, EXTERNAL_MODEL_SIZE) == 0; + if (!is_external) { + obs_log(LOG_INFO, "Not an external model"); + return true; + } + struct detect_filter *tf_ = reinterpret_cast(data_); + const char *model_file = + obs_data_get_string(settings, "external_model_file"); + read_model_config_json_and_set_class_names(model_file, props_, settings, + tf_); + return true; + }, + tf); // Add a informative text about the plugin std::string basic_info = @@ -283,6 +373,8 @@ void detect_filter_defaults(obs_data_t *settings) void detect_filter_update(void *data, obs_data_t *settings) { + obs_log(LOG_INFO, "Detect filter update"); + struct detect_filter *tf = reinterpret_cast(data); tf->isDisabled = true; @@ -341,7 +433,7 @@ void detect_filter_update(void *data, obs_data_t *settings) bool reinitialize = false; if (tf->useGPU != newUseGpu || tf->numThreads != newNumThreads || tf->modelSize != newModelSize) { - obs_log(LOG_DEBUG, "Reinitializing model"); + obs_log(LOG_INFO, "Reinitializing model"); reinitialize = true; // lock modelMutex @@ -357,8 +449,17 @@ void detect_filter_update(void *data, obs_data_t *settings) } else if (newModelSize == "large") { modelFilepath_rawPtr = obs_module_file("models/edgeyolo_tiny_lrelu_coco_736x1280.onnx"); - } else if (newModelSize == "!!!external!!!") { - modelFilepath_rawPtr = bstrdup(obs_data_get_string(settings, "model_file")); + } else if (newModelSize == EXTERNAL_MODEL_SIZE) { + obs_log(LOG_INFO, "External model selected"); + const char *external_model_file = + obs_data_get_string(settings, "external_model_file"); + if (external_model_file == nullptr || external_model_file[0] == '\0' || + strlen(external_model_file) == 0) { + obs_log(LOG_ERROR, "External model file path is empty"); + tf->isDisabled = true; + return; + } + modelFilepath_rawPtr = bstrdup(external_model_file); } else { obs_log(LOG_ERROR, "Invalid model size: %s", newModelSize.c_str()); tf->isDisabled = true; @@ -371,8 +472,6 @@ void detect_filter_update(void *data, obs_data_t *settings) return; } - std::string modelFilepath_s(modelFilepath_rawPtr); - #if _WIN32 int outLength = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, modelFilepath_rawPtr, -1, nullptr, 0); @@ -394,6 +493,41 @@ void detect_filter_update(void *data, obs_data_t *settings) bool onnxruntime_use_parallel_ = true; float nms_th_ = 0.45f; int num_classes_ = (int)edgeyolo_cpp::COCO_CLASSES.size(); + tf->classNames = edgeyolo_cpp::COCO_CLASSES; + + // If this is an external model - look for the config JSON file + if (tf->modelSize == EXTERNAL_MODEL_SIZE) { +#ifdef _WIN32 + std::wstring labelsFilepath = tf->modelFilepath; + labelsFilepath.replace(labelsFilepath.find(L".onnx"), 5, L".json"); +#else + std::string labelsFilepath = tf->modelFilepath; + labelsFilepath.replace(labelsFilepath.find(".onnx"), 5, ".json"); +#endif + std::ifstream labelsFile(labelsFilepath); + if (labelsFile.is_open()) { + // Parse the JSON file + nlohmann::json j; + labelsFile >> j; + if (j.contains("names")) { + std::vector labels = j["names"]; + num_classes_ = (int)labels.size(); + tf->classNames = labels; + } else { + obs_log(LOG_ERROR, + "JSON file does not contain 'labels' field"); + tf->isDisabled = true; + tf->edgeyolo.reset(); + return; + } + } else { + obs_log(LOG_ERROR, "Failed to open JSON file: %s", + labelsFilepath.c_str()); + tf->isDisabled = true; + tf->edgeyolo.reset(); + return; + } + } // Load model try { @@ -413,33 +547,6 @@ void detect_filter_update(void *data, obs_data_t *settings) tf->edgeyolo.reset(); return; } - - // If this is an external model - look for the labels file - if (tf->modelSize == "!!!external!!!") { -#ifdef _WIN32 - std::wstring labelsFilepath = tf->modelFilepath; - labelsFilepath.replace(labelsFilepath.find(L".onnx"), 5, L".txt"); -#else - std::string labelsFilepath = tf->modelFilepath; - labelsFilepath.replace(labelsFilepath.find(".onnx"), 5, ".txt"); -#endif - std::ifstream labelsFile(labelsFilepath); - if (labelsFile.is_open()) { - std::string line; - std::vector labels; - while (std::getline(labelsFile, line)) { - labels.push_back(line); - } - labelsFile.close(); - } else { - obs_log(LOG_ERROR, "Failed to load labels file: %s", - labelsFilepath.c_str()); - // disable filter - tf->isDisabled = true; - tf->edgeyolo.reset(); - return; - } - } } // update threshold on edgeyolo @@ -618,7 +725,7 @@ void detect_filter_video_tick(void *data, float seconds) // get source settings obs_data_t *source_settings = obs_source_get_settings(tf->source); obs_data_set_string(source_settings, "detected_object", - edgeyolo_cpp::COCO_CLASSES[objects[0].label].c_str()); + tf->classNames[objects[0].label].c_str()); // release the source settings obs_data_release(source_settings); } From a354823575b8b696ae87b4fa6991d801f13eb96e Mon Sep 17 00:00:00 2001 From: Roy Shilkrot Date: Thu, 9 May 2024 17:33:12 -0400 Subject: [PATCH 3/4] chore: Remove unused parameter in detect_filter_properties --- src/detect-filter.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/detect-filter.cpp b/src/detect-filter.cpp index b5c318d..798769d 100644 --- a/src/detect-filter.cpp +++ b/src/detect-filter.cpp @@ -293,6 +293,7 @@ obs_properties_t *detect_filter_properties(void *data) obs_property_set_modified_callback2( model_size, [](void *data_, obs_properties_t *props_, obs_property_t *p, obs_data_t *settings) { + UNUSED_PARAMETER(p); struct detect_filter *tf_ = reinterpret_cast(data_); const char *model_size_value = obs_data_get_string(settings, "model_size"); obs_log(LOG_INFO, "model_size modified: %s", model_size_value); @@ -320,6 +321,7 @@ obs_properties_t *detect_filter_properties(void *data) obs_property_set_modified_callback2( obs_properties_get(props, "external_model_file"), [](void *data_, obs_properties_t *props_, obs_property_t *p, obs_data_t *settings) { + UNUSED_PARAMETER(p); obs_log(LOG_INFO, "external_model_file modified"); const char *model_size_value = obs_data_get_string(settings, "model_size"); bool is_external = strcmp(model_size_value, EXTERNAL_MODEL_SIZE) == 0; From 0d6ac81ec26843bdab16604253f75b0700ffa7e0 Mon Sep 17 00:00:00 2001 From: Roy Shilkrot Date: Thu, 9 May 2024 18:14:08 -0400 Subject: [PATCH 4/4] Refactor detect_filter_properties to remove unused parameter and log statements --- src/detect-filter.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/detect-filter.cpp b/src/detect-filter.cpp index 798769d..065307e 100644 --- a/src/detect-filter.cpp +++ b/src/detect-filter.cpp @@ -296,7 +296,6 @@ obs_properties_t *detect_filter_properties(void *data) UNUSED_PARAMETER(p); struct detect_filter *tf_ = reinterpret_cast(data_); const char *model_size_value = obs_data_get_string(settings, "model_size"); - obs_log(LOG_INFO, "model_size modified: %s", model_size_value); bool is_external = strcmp(model_size_value, EXTERNAL_MODEL_SIZE) == 0; obs_property_t *prop = obs_properties_get(props_, "external_model_file"); obs_property_set_visible(prop, is_external); @@ -322,11 +321,9 @@ obs_properties_t *detect_filter_properties(void *data) obs_properties_get(props, "external_model_file"), [](void *data_, obs_properties_t *props_, obs_property_t *p, obs_data_t *settings) { UNUSED_PARAMETER(p); - obs_log(LOG_INFO, "external_model_file modified"); const char *model_size_value = obs_data_get_string(settings, "model_size"); bool is_external = strcmp(model_size_value, EXTERNAL_MODEL_SIZE) == 0; if (!is_external) { - obs_log(LOG_INFO, "Not an external model"); return true; } struct detect_filter *tf_ = reinterpret_cast(data_); @@ -452,7 +449,6 @@ void detect_filter_update(void *data, obs_data_t *settings) modelFilepath_rawPtr = obs_module_file("models/edgeyolo_tiny_lrelu_coco_736x1280.onnx"); } else if (newModelSize == EXTERNAL_MODEL_SIZE) { - obs_log(LOG_INFO, "External model selected"); const char *external_model_file = obs_data_get_string(settings, "external_model_file"); if (external_model_file == nullptr || external_model_file[0] == '\0' ||