diff --git a/data/locale/en-US.ini b/data/locale/en-US.ini index c2ae325d..89db8729 100644 --- a/data/locale/en-US.ini +++ b/data/locale/en-US.ini @@ -36,3 +36,5 @@ FocalBlurGroup="Focal blur settings" ThresholdGroup="Threshold settings" EnableImageSimilarity="Skip image based on similarity?" ImageSimilarityThreshold="Sim. thresh. (high -> sensitive)" +TemporalSmoothFactor="Temporal smooth factor" +MaskExpansion="Mask expansion" diff --git a/src/background-filter.cpp b/src/background-filter.cpp index ccb938a3..e9d36d12 100644 --- a/src/background-filter.cpp +++ b/src/background-filter.cpp @@ -38,6 +38,7 @@ struct background_removal_filter : public filter_data { float contourFilter = 0.05f; float smoothContour = 0.5f; float feather = 0.0f; + int maskExpansion = 0; cv::Mat backgroundMask; cv::Mat lastBackgroundMask; @@ -103,7 +104,7 @@ static bool enable_advanced_settings(obs_properties_t *ppts, obs_property_t *p, for (const char *prop_name : {"model_select", "useGPU", "mask_every_x_frames", "numThreads", "enable_focal_blur", "enable_threshold", "threshold_group", "focal_blur_group", "temporal_smooth_factor", "image_similarity_threshold", - "enable_image_similarity"}) { + "enable_image_similarity", "mask_expansion"}) { p = obs_properties_get(ppts, prop_name); obs_property_set_visible(p, enabled); } @@ -148,6 +149,9 @@ obs_properties_t *background_filter_properties(void *data) obs_properties_add_group(props, "threshold_group", obs_module_text("ThresholdGroup"), OBS_GROUP_NORMAL, threshold_props); + /* Mask expansion slider - in advanced settings */ + obs_properties_add_int_slider(props, "mask_expansion", obs_module_text("MaskExpansion"), -30, 30, 1); + /* GPU, CPU and performance Props */ obs_property_t *p_use_gpu = obs_properties_add_list(props, "useGPU", obs_module_text("InferenceDevice"), OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING); @@ -227,6 +231,7 @@ void background_filter_defaults(obs_data_t *settings) obs_data_set_default_double(settings, "threshold", 0.5); obs_data_set_default_double(settings, "contour_filter", 0.05); obs_data_set_default_double(settings, "smooth_contour", 0.5); + obs_data_set_default_double(settings, "mask_expansion", 0); obs_data_set_default_double(settings, "feather", 0.0); #if defined(__APPLE__) obs_data_set_default_string(settings, "useGPU", USEGPU_CPU); @@ -258,6 +263,7 @@ void background_filter_update(void *data, obs_data_t *settings) tf->contourFilter = (float)obs_data_get_double(settings, "contour_filter"); tf->smoothContour = (float)obs_data_get_double(settings, "smooth_contour"); + tf->maskExpansion = (float)obs_data_get_double(settings, "mask_expansion"); tf->feather = (float)obs_data_get_double(settings, "feather"); tf->maskEveryXFrames = (int)obs_data_get_int(settings, "mask_every_x_frames"); tf->maskEveryXFramesCount = (int)(0); @@ -340,6 +346,7 @@ void background_filter_update(void *data, obs_data_t *settings) obs_log(LOG_INFO, " Threshold: %f", tf->threshold); obs_log(LOG_INFO, " Contour Filter: %f", tf->contourFilter); obs_log(LOG_INFO, " Smooth Contour: %f", tf->smoothContour); + obs_log(LOG_INFO, " Mask Expansion: %f", tf->maskExpansion); obs_log(LOG_INFO, " Feather: %f", tf->feather); obs_log(LOG_INFO, " Mask Every X Frames: %d", tf->maskEveryXFrames); obs_log(LOG_INFO, " Enable Image Similarity: %s", tf->enableImageSimilarity ? "true" : "false"); @@ -559,6 +566,15 @@ void background_filter_video_tick(void *data, float seconds) backgroundMask = backgroundMask > 128; } + // Expand or shrink the mask + if (tf->maskExpansion > 0.0) { + cv::erode(backgroundMask, backgroundMask, cv::Mat(), cv::Point(-1, -1), + tf->maskExpansion); + } else if (tf->maskExpansion < 0.0) { + cv::dilate(backgroundMask, backgroundMask, cv::Mat(), cv::Point(-1, -1), + -tf->maskExpansion); + } + if (tf->feather > 0.0) { // Feather (blur) the mask int k_size = (int)(40 * tf->feather);