0

我正在使用带有 C++11 的 OpenCV 3.4.8,我正在尝试将图像混合在一起。在这个例子中,我有 2 个图像(它们的掩码显示在下面的屏幕中)。我有地理参考,所以我可以在最终图像中轻松计算这些图像的角。掩码外的数据为黑色。

混合前的图像蒙版

我的代码看起来像这样:

std::vector<cv::UMat> inputImages;
std::vector<cv::UMat> masks;
std::vector<cv::Point> corners;
std::vector<cv::Size> imgSizes;

/*
here is code where I load images, create thier masks 
(like in the screen above) and calculate corners.
*/

cv::Ptr<cv::detail::SeamFinder> seamFinder = new cv::detail::DpSeamFinder();
seamFinder->find(inputImages, corners, masks);

cv::Ptr<cv::detail::Blender> blender = new cv::detail:: MultiBandBlender(false);
blender->prepare(corners, imgSizes);
for(size_t i = 0; i < inputImages.size(); i++)
{
    blender->feed(inputImages[i], masks[i], corners[i]);
}

cv::UMat blendedImg, outMask;
blender->blend(blendedImg, outMask);

图像的接缝线

SeamFinder 给了我上面屏幕中的结果。找到的接缝线看起来不错,我对它们非常满意。但另一个问题发生在下一步。当接缝线位于数据末端时,MultiBandBlender 会产生奇怪的白色条纹。这是一个例子:

混合后的图像

当我不使用搅拌机,而只是使用蒙版来剪切原始图像并添加(cv::add())图像以及额外的 alpha 通道(由蒙版制成)时,我得到了非常好的结果,没有任何孔和奇怪的颜色,但我需要有更平滑的过渡:/

谁能帮我?当我创建具有较小 num_bands 的 MultiBand Blender 时,白色条纹较小,并且 num_bands = 0 的结果看起来就像只添加图像。我查看了 MultiBandBlender 中feed()blend()方法,我认为它与高斯或拉普拉斯金字塔以及该blend()方法中从拉普拉斯金字塔的最终恢复图像有关。

EDIT1:当创建高斯和拉普拉斯金字塔copyMakeBorder()时,当图像完全填充数据时,它可以防止 MultiBandBlender 产生这种白色条纹。因此,就我而言,我认为我需要创建与 MultiBandBlender 几乎相同的搅拌机,但copyMakeBorder()方法中的feed()方法更改为将“扩展”我的图像在面具内的东西,就像@AlexanderKondratskiy 建议的那样。现在我不知道如何实现类似于 BORDER_REFLECT 或 BORDER_REFLECT_101 的正确“扩展”。

4

1 回答 1

1

我怀疑您的输入图像在这些蒙版之外包含白色像素。白色条纹出现在接缝完全跟随蒙版的区域周围。例如,对于拉普拉斯算子,蒙版之外的像素确实会影响最终结果,因为金字塔的每一层本质上都是图像上的一些模糊核。

如果您在掩码之外有某种好的数据,请保留它。如果您不这样做,我建议将您的图像“扩展”到遮罩之外以保持平滑过渡。

编辑:

除非有更多 OpenCV 经验的人出现,否则您可以尝试以下两件事。

  1. 为了证明/反驳我的假设,只需用掩码内的平均颜色或中间颜色填充黑色区域。这应该会使到外部区域的过渡不那么尖锐,并有望减少伪影。如果这没有发生,我的回答是错误的。

  2. 当边缘是任意的时,就“BORDER_REFLECT”的一个很好的概括而言,你可以尝试这样的事情:

    • 找到c遮罩多边形的质心
    • p对于掩码外的每个像素,想想它和c
    • 计算p'沿这条线的点,该点与蒙版区域内的距离相同,p与蒙版边缘的距离相同。(即你沿着蒙版边缘反射)
    • 从 的 邻居线性插值 的颜色p'(因为它的位置可能不会正好落在像素的中间)。这是像素的颜色p
于 2020-01-09T19:31:02.610 回答