OpenCV Cuda alphaComp, blending a 0 image repeatedly makes it darker

asked 2018-08-13 11:47:33 -0500

I am experiencing strange behavior with alpha compositing using OpenCV 3.4.1 and Cuda.

When I blend an all-black image with an all-zero alpha channel to another image, and repeat this process recursively, the image becomes darker, settling at around 50% brightness.

Is this some kind of bug, or am I misunderstanding something fundamental about alpha compositing? The documentation on the different blend modes is sparse.

I have written a short example code illustrating what happens. When run once, the rectangle seems to stay green. However, putting this in a loop makes the rectangle slowly fade out until it becomes dark-green.

image description image description

#include <stdio.h>
#include <iostream>

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

#include <opencv2/core/cuda.hpp>
#include <opencv2/cudaimgproc.hpp>
#include <opencv2/cudaarithm.hpp>

using namespace std;
using namespace cv;

int main(int argc, char *argv[])
{
    Mat frame(1080, 1920, CV_8UC4, Scalar(0, 0, 0, 255));

    namedWindow("test", CV_WINDOW_OPENGL);

    // Drawing a green rectangle with 100% opacity
    rectangle(frame, Rect(10, 10, 200, 200), Scalar(0, 255, 0, 255), CV_FILLED);

    cuda::GpuMat gpuFrame(frame);

    while(true){

        // Creating an all-black image with 0% opacity
        cuda::GpuMat gpuBlank(1080, 1920, CV_8UC4, Scalar(0, 0, 0, 0));

        // Alpha-compositing them together should keep the image untouched..?
        cuda::alphaComp(gpuFrame, gpuBlank, gpuFrame, cuda::ALPHA_OVER);

        // Splitting the image into 4 mats, to remove any resulting opacity from the image
        // Hopefully coming out with another 100% opacity image to blend again
        vector<cuda::GpuMat> frameChannels;
        cuda::split(gpuFrame, frameChannels);
        cuda::GpuMat fullAlpha(1080, 1920, CV_8UC1, Scalar(255));

        if (gpuFrame.channels() > 3) {
            frameChannels.pop_back();
        }
        frameChannels.push_back(fullAlpha);

        cuda::merge(frameChannels, gpuFrame);

        imshow("test", gpuFrame);
        waitKey(1);
    }
    while(1) {
        waitKey(1);
    }
}
edit retag flag offensive close merge delete