Ask Your Question
4

How to overlay an PNG image with alpha channel to another PNG?

asked 2015-10-13 03:45:42 -0600

realkill gravatar image

updated 2020-11-30 03:30:21 -0600

I have two PNG images (overlay.png and underlay.png) both with alpha channel. I tried the addWeight and copyTo API to mask overlay.png to underlay.png, but the result image is not what I want.

overlay.png image description

underlay.png image description

result png i wish image description

This is my test code:

void blend_two_images() {
cv::Mat underlay = cv::imread("/home/underlay.png", CV_LOAD_IMAGE_UNCHANGED);
cv::Mat overlay = cv::imread("/home/overlay.png", CV_LOAD_IMAGE_UNCHANGED);
cv::Mat roi = underlay(cv::Rect(0, 0, overlay.cols, overlay.rows));

cv::addWeighted(roi, 0, overlay, 1, 0, roi);
cv::imwrite("/home/result.png", underlay);  }

And this is the original image files: overlay.png underlay.png

How can I get the result I wish? Thanks a lot!

edit retag flag offensive close merge delete

Comments

2

Can you provide the original images?

LorenaGdL gravatar imageLorenaGdL ( 2015-10-13 04:23:14 -0600 )edit

Please check the attachment links at the end of this post.

realkill gravatar imagerealkill ( 2015-10-13 04:56:39 -0600 )edit

hmm... did you save your .png with alpha channel? I can't see it

LorenaGdL gravatar imageLorenaGdL ( 2015-10-13 05:01:48 -0600 )edit

I tried the code below from Steven with these images and it seems that the images as @LorenaGdL says are not saved with an alpha channel, though the output of .channels method return 4 if I use IMREAD_UNCHANGED. So, yes are you sure your images are saved with the alpha channel?

theodore gravatar imagetheodore ( 2015-10-13 06:51:26 -0600 )edit

1 answer

Sort by ยป oldest newest most voted
4

answered 2015-10-13 05:04:10 -0600

updated 2015-10-13 21:10:43 -0600

Looking at this post: http://jepsonsblog.blogspot.be/2012/1...

taking Max5684 comment

// http://jepsonsblog.blogspot.be/2012/10/overlay-transparent-image-in-opencv.html
// https://gist.github.com/maximus5684/082f8939edb6aed7ba0a

#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include <iostream>

using namespace cv;
using namespace std;

void overlayImage(Mat* src, Mat* overlay, const Point& location)
{
    for (int y = max(location.y, 0); y < src->rows; ++y)
    {
        int fY = y - location.y;

        if (fY >= overlay->rows)
            break;

        for (int x = max(location.x, 0); x < src->cols; ++x)
        {
            int fX = x - location.x;

            if (fX >= overlay->cols)
                break;

            double opacity = ((double)overlay->data[fY * overlay->step + fX * overlay->channels() + 3]) / 255;

            for (int c = 0; opacity > 0 && c < src->channels(); ++c)
            {
                unsigned char overlayPx = overlay->data[fY * overlay->step + fX * overlay->channels() + c];
                unsigned char srcPx = src->data[y * src->step + x * src->channels() + c];
                src->data[y * src->step + src->channels() * x + c] = srcPx * (1. - opacity) + overlayPx * opacity;
            }
        }
    }
}

int main( int argc, char** argv )
{
    Mat underlay = imread("14447300874345549.png",IMREAD_UNCHANGED);
    Mat overlay = imread("14447300692773615.png",IMREAD_UNCHANGED);
    Mat test = imread("1429209553641108.png",IMREAD_UNCHANGED);

    if( underlay.empty() || overlay.empty() || test.empty() )
    {
        cout << "Could not read input image files " << endl;
        return -1;
    }

    Mat rgba[4];
    split(underlay,rgba);
    imshow("alpha1.png",rgba[3]);
    imwrite("alpha1.png",rgba[3]);

    split(overlay,rgba);
    imshow("alpha2.png",rgba[3]);
    imwrite("alpha2.png",rgba[3]);

    overlayImage( &underlay, &overlay, Point() );
    overlayImage( &test, &underlay, Point(120,180) );

    split(underlay,rgba);
    imshow("alpha3.png",rgba[3]);
    imwrite("alpha3.png",rgba[3]);

    imshow("result1",underlay);
    imwrite("result1.png",underlay);
    imshow("result2",test);
    imwrite("result2.png",test);

    waitKey();

    return 0;
}

Test Images :

image description

image description image description

Result Images:

image description image description

Alpha channels before:

image description image description

Alpha channel of result:

image description

The output image will always be of the same size as the background image. The position parameter determines how the foreground is placed on top of the background. A position of (100, -50) will move the foreground 100 pixels to the right and 50 pixels up.

edit flag offensive delete link more

Comments

1

@sturkmen, thank you for the implementation!

StevenPuttemans gravatar imageStevenPuttemans ( 2015-10-14 01:17:17 -0600 )edit
1

@StevenPuttemans you are welcome. i also owe to thank you. you guided me to learn something new.

sturkmen gravatar imagesturkmen ( 2015-10-14 01:36:51 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2015-10-13 03:45:42 -0600

Seen: 35,098 times

Last updated: Oct 13 '15