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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With