如何利用OpenCv叠加图像?

5
我应该如何叠加两张图片?我有一张没有 alpha 通道的背景图和一张或多张具有 alpha 通道的需要叠加在其上的图片。
我尝试了以下代码,但叠加的效果非常糟糕:
// create our out image
Mat merged (info.width, info.height, CV_8UC4);

// get layers
Mat layer1Image = imread(layer1Path);
Mat layer2Image = imread(layer2Path);

addWeighted(layer1Image, 0.5, layer2Image, 0.5, 0.0, merged);

我也尝试使用合并,但我在某个地方读到它不支持alpha通道?

2个回答

6

我不知道是否有一个OpenCV函数可以做到这一点。但你可以自己实现它。它类似于addWeighted函数。但是,权重不是固定的0.5,而是从覆盖图像的alpha通道计算出来的。

    Mat img = imread("bg.bmp");
    Mat dst(img);
    Mat ov = imread("ov.tiff", -1);


    for(int y=0;y<img.rows;y++)
    for(int x=0;x<img.cols;x++)
    {
            //int alpha = ov.at<Vec4b>(y,x)[3];
            int alpha = 256 * (x+y)/(img.rows+img.cols);
            dst.at<Vec3b>(y,x)[0] = (1-alpha/256.0) * img.at<Vec3b>(y,x)[0] + (alpha * ov.at<Vec3b>(y,x)[0] / 256);
            dst.at<Vec3b>(y,x)[1] = (1-alpha/256.0) * img.at<Vec3b>(y,x)[1] + (alpha * ov.at<Vec3b>(y,x)[1] / 256);
            dst.at<Vec3b>(y,x)[2] = (1-alpha/256.0) * img.at<Vec3b>(y,x)[2] + (alpha * ov.at<Vec3b>(y,x)[2] / 256);
    }

    imwrite("bg_ov.bmp",dst);

请注意,我无法读取具有 alpha 通道的文件,因为显然 OpenCV 不支持此功能。这就是为什么我从坐标中计算 alpha 值以获取某种渐变效果的原因。

啊!太棒了!我实际上能够使用你的代码,并对其进行修改以支持4通道Vect4b,并取消注释你的第一条alpha线。完美工作得非常好! :) - Jona
1
这似乎并不是非常高效的。 - Barney Szabolcs
这段代码运行良好,但对于大尺寸图像来说需要太长时间,例如对于一个带有500KB水印的6.4MP图像,它需要45秒的时间。 - Farrakh Javed

0
最可能合并的通道号与输入不同。您可以进行替换。
Mat merged (info.width, info.height, CV_8UC4);

用这个:

Mat merged; 

这样做可以让addWeighted方法使用正确的参数创建目标矩阵。


感谢您的快速回答。 我刚才发现崩溃问题是由于第二层的大小与第一层不匹配 :( 我尝试将图像合并在一起,但它们看起来有些糟糕。 我尝试了调整 alpha 和 beta,但我无法使未经触摸的图像仅覆盖它。 - Jona

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接