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.
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:
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:
And, we create a black foreground 3-channel image of the same size with the red circle:
Using addWeighted
with alpha = 1
and beta = 0.5
, we get the expected output for both versions: