garbart
garbart

Reputation: 485

Translucent objects on IplImage

I draw objects on IplImage like this:

cvLine(image, point_1, point_2, color, thickness, CV_AA); // Line
cvCircle(mage, point, radius, color, thickness, CV_AA); // Circle
// and some others...

How can I draw them translucent? cv::Scalar does not support alpha channel, if I understand correctly. I found something similar, but not quite appropriate: link. Here we are talking about translucenty IplImage, not about the objects on it.

Upvotes: 1

Views: 394

Answers (1)

HansHirse
HansHirse

Reputation: 18925

So, I tested it now with IplImage and cv::Mat, and both cvCircle and cv::circle don't support drawing semi-transparent objects. I used OpenCV 3.4.0, since this version still supports the old C API.

Let's have a look at the following code:

// IplImage - doesn't work
IplImage* ipl = cvCreateImage(cvSize(201, 201), IPL_DEPTH_8U, 4);
cvSet(ipl, CvScalar(255, 0, 0, 255));
cvCircle(ipl, CvPoint(100, 100), 50, CvScalar(0, 0, 255, 128), CV_FILLED);

// cv::Mat - doesn't work
cv::Mat img = cv::Mat(201, 201, CV_8UC4, cv::Scalar(255, 0, 0, 255));
cv::circle(img, cv::Point(100, 100), 50, cv::Scalar(0, 0, 255, 128), cv::FILLED);

We create a blue 4-channel image with zero transparency, and draw a red circle with 0.5 transparency. In both cases, we get the following output:

False output

We see, that the part of red circle actually "replaces" the pixel values in the original blue image.

So, for IplImage as well as for cv::Mat we need to use blending, e.g. using addWeighted. Let's have a look at this code:

// IplImage - works
IplImage* iplBG = cvCreateImage(cvSize(201, 201), IPL_DEPTH_8U, 3);
cvSet(iplBG, CvScalar(255, 0, 0));
IplImage* iplFG = cvCreateImage(cvSize(201, 201), IPL_DEPTH_8U, 3);
cvSet(iplFG, CvScalar(0, 0, 0));
cvCircle(iplFG, CvPoint(100, 100), 50, CvScalar(0, 0, 255), CV_FILLED);
IplImage* iplOut = cvCreateImage(cvSize(201, 201), IPL_DEPTH_8U, 3);
cvAddWeighted(iplBG, 1, iplFG, 0.5, 0, iplOut);

// cv::Mat - works
cv::Mat imgBG = cv::Mat(201, 201, CV_8UC3, cv::Scalar(255, 0, 0));
cv::Mat imgFG = cv::Mat(201, 201, CV_8UC3, cv::Scalar(0, 0, 0));
cv::circle(imgFG, cv::Point(100, 100), 50, cv::Scalar(0, 0, 255), cv::FILLED);
cv::Mat imgOut;
cv::addWeighted(imgBG, 1, imgFG, 0.5, 0, imgOut);

In fact, we create a blue 3-channel background image like this:

Background

And, we create a black foreground 3-channel image of the same size with the red circle:

Foreground

Using addWeighted with alpha = 1 and beta = 0.5, we get the expected output for both versions:

Correct output

Upvotes: 2

Related Questions