【问题标题】:How to obtain the right alpha value to perfectly blend two images?如何获得正确的 alpha 值以完美融合两个图像?
【发布时间】:2016-06-19 19:34:00
【问题描述】:

我一直在尝试混合两个图像。我目前采用的方法是,我获取两个图像的重叠区域的坐标,并且仅对于重叠区域,我在添加之前与 0.5 的硬编码 alpha 混合。所以基本上我只是从两个图像的重叠区域中取出每个像素值的一半,然后添加它们。这并没有给我一个完美的融合,因为 alpha 值被硬编码为 0.5。这是 3 张图像混合的结果:

如您所见,从一张图像到另一张图像的过渡仍然可见。如何获得可以消除这种可见过渡的完美 alpha 值?还是没有这样的事情,我采取了错误的方法?

这是我目前进行混合的方式:

for i in range(3):
            base_img_warp[overlap_coords[0], overlap_coords[1], i] = base_img_warp[overlap_coords[0], overlap_coords[1],i]*0.5
            next_img_warp[overlap_coords[0], overlap_coords[1], i] = next_img_warp[overlap_coords[0], overlap_coords[1],i]*0.5
final_img = cv2.add(base_img_warp, next_img_warp)

如果有人想试一试,这里有两张扭曲的图像,以及它们重叠区域的蒙版:http://imgur.com/a/9pOsQ

【问题讨论】:

  • 源图像似乎与背景预乘。你能展示一下你目前使用的公式吗?
  • @K3N,我已经编辑并添加了一些代码。让我知道这是否有帮助。
  • 您能否提供 3 个单独的扭曲图像以及重叠坐标?这将允许人们验证不同的方法。
  • @Miki 当然,这里有 2 张扭曲的图像,以及它们重叠区域的掩码:imgur.com/a/9pOsQ
  • 也许你会从我的回答中得到一些启发:stackoverflow.com/questions/22315904/…

标签: python opencv image-processing computer-vision alphablending


【解决方案1】:

这是我通常会这样做的方式:

int main(int argc, char* argv[])
{
    cv::Mat input1 = cv::imread("C:/StackOverflow/Input/pano1.jpg");
    cv::Mat input2 = cv::imread("C:/StackOverflow/Input/pano2.jpg");

    // compute the vignetting masks. This is much easier before warping, but I will try...
    // it can be precomputed, if the size and position of your ROI in the image doesnt change and can be precomputed and aligned, if you can determine the ROI for every image
    // the compression artifacts make it a little bit worse here, I try to extract all the non-black regions in the images.
    cv::Mat mask1;
    cv::inRange(input1, cv::Vec3b(10, 10, 10), cv::Vec3b(255, 255, 255), mask1);
    cv::Mat mask2;
    cv::inRange(input2, cv::Vec3b(10, 10, 10), cv::Vec3b(255, 255, 255), mask2);


    // now compute the distance from the ROI border:
    cv::Mat dt1;
    cv::distanceTransform(mask1, dt1, CV_DIST_L1, 3);
    cv::Mat dt2;
    cv::distanceTransform(mask2, dt2, CV_DIST_L1, 3);

    // now you can use the distance values for blending directly. If the distance value is smaller this means that the value is worse (your vignetting becomes worse at the image border)
    cv::Mat mosaic = cv::Mat(input1.size(), input1.type(), cv::Scalar(0, 0, 0));
    for (int j = 0; j < mosaic.rows; ++j)
    for (int i = 0; i < mosaic.cols; ++i)
    {
        float a = dt1.at<float>(j, i);
        float b = dt2.at<float>(j, i);

        float alpha = a / (a + b); // distances are not between 0 and 1 but this value is. The "better" a is, compared to b, the higher is alpha.
        // actual blending: alpha*A + beta*B
        mosaic.at<cv::Vec3b>(j, i) = alpha*input1.at<cv::Vec3b>(j, i) + (1 - alpha)* input2.at<cv::Vec3b>(j, i);
    }

    cv::imshow("mosaic", mosaic);

    cv::waitKey(0);
    return 0;
}

基本上,您计算 ROI 边界到对象中心的距离,并根据两个混合蒙版值计算 alpha。因此,如果一幅图像与边界的距离较远,而另一幅图像与边界的距离较近,则您更喜欢靠近图像中心的像素。对于扭曲图像大小不相似的情况,最好对这些值进行标准化。 但更好、更有效的是预先计算混合蒙版并扭曲它们。最好是了解您的光学系统的渐晕并选择相同的混合蒙版(通常是较低的边框值)。

从前面的代码中,您将获得以下结果: ROI 掩码:

混合蒙版(只是作为一种印象,必须是浮点矩阵):

图像马赛克:

【讨论】:

  • 你好,你是怎么拿到口罩的。 cv2.distanceTransform(img_1_mask, cv2.DIST_L1, 3) 只是在 python 中返回原始掩码。
  • 在显示之前你必须缩放它们,因为浮点值 >= 1 显示为白色。试试imshow(windowname, dt1/255) 或某事。像那样(不知道 numpy/python 语法,抱歉)
  • 我是cv2.imshow(windowname, img/255),谢谢!另外,想知道是否有一种更快的方法来操纵所有像素,而不是遍历所有像素。有什么想法吗?
  • 是的,您可以使用子矩阵仅迭代重叠的图像部分。使用您在问题中发布的掩码,计算边界框并使用该 ROI 对所有其他矩阵(image1/image2/dt1/dt2)进行子矩阵化。此外,您可以加快文本中所述的混合蒙版的计算,您可以计算马赛克的组合混合蒙版,以便为您将添加的下一张图像记住它。
  • 很好的答案。干得好,伙计。
【解决方案2】:

您的图片有 2 个明显的问题:

  1. 边界区域的照明条件失真

    这很可能是由用于获取图像的光学器件引起的。所以为了补救你应该只使用图像的内部部分(从边框上剪掉几个像素。

    因此,当从边框切掉 20 个像素并混合到普通照明时,我得到了这个:

    您可以看到丑陋的边框接缝消失了,现在只有照明问题仍然存在(参见项目符号 #2)。

  2. 图像是在不同的光照条件下拍摄的

    这里的次表面散射效果使图像“不兼容”。您应该将它们归一化为一些均匀的照明或逐行对混合结果进行后期处理,当检测到相干凹凸时,将其余部分相乘,这样凹凸就会减少。

    所以该行的其余部分应该乘以常数i0/i1。如果凹凸只能出现在重叠值之间的边缘,那么您可以扫描它们或直接使用这些位置......要识别有效的凹凸,它应该在整个图像高度的上一行和下一行附近有邻居。

    您也可以在 y 轴方向上以相同的方式执行此操作...

【讨论】:

    猜你喜欢
    • 2022-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-06
    • 1970-01-01
    • 1970-01-01
    • 2018-01-28
    相关资源
    最近更新 更多