5

How can I overlay two images? Essentially I have a background with no alpha channel and than one or more images that have alpha channel that need to be overlaid on top of each other.

I have tried the following code but the overlay result is horrible:

// 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);

I also tried using merge but I read somewhere that it doesn't support alpha channel?

Jona
  • 13,325
  • 15
  • 86
  • 129

2 Answers2

6

I don't know about a OpenCV function that does this. But you could just implement it yourself. It is similar to the addWeighted function. But instead of a fixed weight of 0.5 the weights are computed from the alpha channel of the overlay image.

    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);

Note that I was not able to read in a file with the alpha channel because apparently OpenCV does not support this. That's why I computed an alpha value from the coordinates to get some kind of gradient.

sietschie
  • 7,425
  • 3
  • 33
  • 54
  • Ah! Perfect! I was actually able to use your code and modified it to support 4 channels Vect4b and uncomented your first alpha line. Perfect works real good! :) – Jona May 21 '12 at 14:59
  • 1
    This seems not to be very efficient though. – Barney Szabolcs Oct 29 '12 at 22:33
  • This code is working good, but taking too much time for large size images, like for 6.4MP image with 500KB watermark it is taking 45 seconds. – Farrakh Javed Oct 13 '14 at 09:52
0

Most probably channel number of merged is different from inputs. You can replace

Mat merged (info.width, info.height, CV_8UC4);

with this:

Mat merged; 

This way you will let the addWeighted method create the destination matrix with the correct parameters.

Hakan Serce
  • 11,198
  • 3
  • 29
  • 48
  • Thanks for the quick answer. The crash issue I just figure it out was due to the layer2 not matching the size of layer1. :( I have tried merging the images but they look kinda bad. I tried playing with alpha and beta but I can't get the untouched image to just lay over it. – Jona May 20 '12 at 22:23