diff --git a/modules/stitching/include/opencv2/stitching/detail/blenders.hpp b/modules/stitching/include/opencv2/stitching/detail/blenders.hpp index b291f93fd..42f1b3c2d 100644 --- a/modules/stitching/include/opencv2/stitching/detail/blenders.hpp +++ b/modules/stitching/include/opencv2/stitching/detail/blenders.hpp @@ -72,6 +72,7 @@ class CV_EXPORTS FeatherBlender : public Blender { public: FeatherBlender(float sharpness = 0.02f) { setSharpness(sharpness); } + float sharpness() const { return sharpness_; } void setSharpness(float val) { sharpness_ = val; } @@ -79,6 +80,11 @@ public: void feed(const Mat &img, const Mat &mask, Point tl); void blend(Mat &dst, Mat &dst_mask); + // Creates weight maps for fixed set of source images by their masks and top-left corners. + // Final image can be obtained by simple weighting of the source images. + Rect createWeightMaps(const std::vector &masks, const std::vector &corners, + std::vector &weight_maps); + private: float sharpness_; Mat weight_map_; diff --git a/modules/stitching/src/blenders.cpp b/modules/stitching/src/blenders.cpp index 957fe8d3d..47c3ce2b2 100644 --- a/modules/stitching/src/blenders.cpp +++ b/modules/stitching/src/blenders.cpp @@ -155,6 +155,37 @@ void FeatherBlender::blend(Mat &dst, Mat &dst_mask) } +Rect FeatherBlender::createWeightMaps(const vector &masks, const vector &corners, + vector &weight_maps) +{ + weight_maps.resize(masks.size()); + for (size_t i = 0; i < masks.size(); ++i) + createWeightMap(masks[i], sharpness_, weight_maps[i]); + + Rect dst_roi = resultRoi(corners, masks); + Mat weights_sum(dst_roi.size(), CV_32F); + weights_sum.setTo(0); + + for (size_t i = 0; i < weight_maps.size(); ++i) + { + Rect roi(corners[i].x - dst_roi.x, corners[i].y - dst_roi.y, + weight_maps[i].cols, weight_maps[i].rows); + weights_sum(roi) += weight_maps[i]; + } + + for (size_t i = 0; i < weight_maps.size(); ++i) + { + Rect roi(corners[i].x - dst_roi.x, corners[i].y - dst_roi.y, + weight_maps[i].cols, weight_maps[i].rows); + Mat tmp = weights_sum(roi); + tmp.setTo(1, tmp < numeric_limits::epsilon()); + divide(weight_maps[i], tmp, weight_maps[i]); + } + + return dst_roi; +} + + MultiBandBlender::MultiBandBlender(int try_gpu, int num_bands) { setNumBands(num_bands);