1

Please consider the MWE below. I have a matrix (output) that corresponds to a graphics output buffer and some layers, that should be put into that buffer in a specific order. The layers contain alpha information (last byte). If all layers have the alpha bytes of all pixels set to 0xFF, only the layer on top can be seen. If all have the alpha value set to 0, none can be seen. There can be an alpha value between 0 and 0xFF, so the corresponding pixel should be semi-transparent.

I tried to use addWeighted(), but this didn't help (see below): All images are visible no matter what value the alpha byte is set to.

Do you have any idea how this can be realized?

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>

using namespace cv;

void test(){
    namedWindow("window", WINDOW_AUTOSIZE);

    Mat output(Size(300, 300), CV_8UC4, Scalar(0));

    Mat m1(Size(300, 300), CV_8UC4, Scalar(0));
    Mat m2(Size(300, 300), CV_8UC4, Scalar(0));
    Mat m3(Size(300, 300), CV_8UC4, Scalar(0));

    circle(m1, Point(130, 130), 75, Scalar(0, 0, 0xFF, 0xFF), -1);
    circle(m2, Point(150, 150), 75, Scalar(0, 0xFF, 0, 0xFF), -1);
    rectangle(m3, Rect(100, 100, 60, 60), Scalar(0xFF, 0, 0, 0xFF), -1);
    rectangle(m3, Rect(115, 115, 30, 30), Scalar(0), -1);

    /*
     Output should look like
    [   m3   ] <-- top
    [   m2   ]
    [   m1   ] <-- bottom
    */

    //What I've tried so far (the final solution should work for more than 3 'layers')
    m1.copyTo(output);
    addWeighted(output, .5, m2, .5, 0, output);
    addWeighted(output, .5, m3, .5, 0, output);

    imshow("window", output);
    cvWaitKey(0);

    destroyAllWindows();
}
muffel
  • 7,004
  • 8
  • 57
  • 98
  • There is no function as I know of in opencv that does this, but have you looked at this one: http://stackoverflow.com/questions/10677502/how-to-overlay-images-using-opencv – Øystein W. May 02 '14 at 12:27

1 Answers1

2

I'm not sure if this is the best way to do it, but this will maybe do the job.

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <stdio.h>

using namespace cv;

void addAlpha(Mat src, Mat input);

void test(){
    namedWindow("window", WINDOW_AUTOSIZE);

    Mat output(Size(300, 300), CV_8UC4, Scalar(0));

    Mat m1(Size(300, 300), CV_8UC4, Scalar(0));
    Mat m2(Size(300, 300), CV_8UC4, Scalar(0));
    Mat m3(Size(300, 300), CV_8UC4, Scalar(0));

    circle(m1, Point(130, 130), 75, Scalar(0, 0, 0xFF, 0xFF), -1);
    circle(m2, Point(150, 150), 75, Scalar(0, 0xFF, 0, 0xFF), -1);
    rectangle(m3, Rect(100, 100, 60, 60), Scalar(0xFF, 0, 0, 0xFF), -1);
    rectangle(m3, Rect(115, 115, 30, 30), Scalar(0), -1);


    m1.copyTo(output);

    addAlpha(output,m2);
    addAlpha(output,m3);

    imshow("window", output);
    cvWaitKey(0);

    destroyAllWindows();
}

void addAlpha(Mat src, Mat input){
    if(src.rows != input.rows || src.cols != input.cols){
        perror("Not same size");
    }
    for(int i = 0; i < src.rows; i++){
        for(int j = 0; j < src.cols; j++){
            src.at<cv::Vec4b>(i,j)[0] = src.at<cv::Vec4b>(i,j)[0] * (1 - input.at<cv::Vec4b>(i,j)[3]/255.0) + input.at<cv::Vec4b>(i,j)[0] * (input.at<cv::Vec4b>(i,j)[3]/255.0);
            src.at<cv::Vec4b>(i,j)[1] = src.at<cv::Vec4b>(i,j)[1] * (1 - input.at<cv::Vec4b>(i,j)[3]/255.0) + input.at<cv::Vec4b>(i,j)[1] * (input.at<cv::Vec4b>(i,j)[3]/255.0);
            src.at<cv::Vec4b>(i,j)[2] = src.at<cv::Vec4b>(i,j)[2] * (1 - input.at<cv::Vec4b>(i,j)[3]/255.0) + input.at<cv::Vec4b>(i,j)[2] * (input.at<cv::Vec4b>(i,j)[3]/255.0);
        }
    }
}
Øystein W.
  • 517
  • 3
  • 16
  • thank you, it works for me, but it is really slow. Do you have any idea how to speed it up? – muffel May 02 '14 at 13:12
  • 1
    You should change the way you iterate through the Mat with pointers. There is a lot of ways to do this. I suggest you read here: http://stackoverflow.com/questions/11977954/opencv-matrix-iteration, http://docs.opencv.org/doc/tutorials/core/how_to_scan_images/how_to_scan_images.html or on other answers in stackoverflow ;) – Øystein W. May 02 '14 at 13:48
  • For starters, the at()-function is the one that slows down mostly in most opencv-projects out there – Øystein W. May 02 '14 at 13:50