1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
| #ifndef MEDIAPIPE_CALCULATORS_IMAGE_BACKGROUND_BLUR_CALCULATOR_H_ #define MEDIAPIPE_CALCULATORS_IMAGE_BACKGROUND_BLUR_CALCULATOR_H_
#include "mediapipe/framework/calculator_framework.h" #include "mediapipe/framework/formats/image_frame.h"
namespace mediapipe {
class BackgroundBlurCalculator : public CalculatorBase { public: static absl::Status GetContract(CalculatorContract* cc) { cc->Inputs().Tag("IMAGE").Set<ImageFrame>(); cc->Inputs().Tag("MASK").Set<ImageFrame>(); cc->Outputs().Tag("OUTPUT").Set<ImageFrame>(); cc->Options<BackgroundBlurOptions>(); return absl::OkStatus(); }
absl::Status Open(CalculatorContext* cc) override { const auto& options = cc->Options<BackgroundBlurOptions>(); blur_strength_ = options.blur_strength(); return absl::OkStatus(); }
absl::Status Process(CalculatorContext* cc) override { if (cc->Inputs().Tag("IMAGE").IsEmpty() || cc->Inputs().Tag("MASK").IsEmpty()) { return absl::OkStatus(); }
const auto& image = cc->Inputs().Tag("IMAGE").Get<ImageFrame>(); const auto& mask = cc->Inputs().Tag("MASK").Get<ImageFrame>(); cv::Mat img = formats::MatView(&image); cv::Mat msk = formats::MatView(&mask); cv::resize(msk, msk, img.size()); cv::Mat blurred; int kernel_size = blur_strength_ * 2 + 1; cv::GaussianBlur(img, blurred, cv::Size(kernel_size, kernel_size), 0); cv::Mat result = img.clone(); blurred.copyTo(result, msk < 128); ApplyEdgeFeathering(result, img, blurred, msk); auto output_frame = absl::make_unique<ImageFrame>( ImageFormat::SRGB, result.cols, result.rows); cv::Mat output_mat = formats::MatView(output_frame.get()); result.copyTo(output_mat); cc->Outputs().Tag("OUTPUT").Add(output_frame.release(), cc->InputTimestamp()); return absl::OkStatus(); }
private: int blur_strength_ = 21; void ApplyEdgeFeathering(cv::Mat& result, const cv::Mat& foreground, const cv::Mat& background, const cv::Mat& mask) { cv::Mat mask_float; mask.convertTo(mask_float, CV_32F, 1.0 / 255.0); cv::GaussianBlur(mask_float, mask_float, cv::Size(7, 7), 0); cv::Mat fg_float, bg_float; foreground.convertTo(fg_float, CV_32F); background.convertTo(bg_float, CV_32F); cv::Mat blended = fg_float.mul(mask_float) + bg_float.mul(1.0 - mask_float); blended.convertTo(result, CV_8U); } };
REGISTER_CALCULATOR(BackgroundBlurCalculator);
}
#endif
|