0

I have jpg image and polygon which I want to use as mask in this way: image inside this polygon should be displayed, and all outside this polygon should be 100% transparent. Now I achieved only first goal - I can display image inside polygon, but all outside of it is black:

cv::Mat image;

//load image

image.convertTo(image, CV_8UC3, 255.0);

std::vector<cv::Point> contour;

//load polygon

const cv::Point* elementPoints[1] = { &contour[0] };
int numberOfPoints = (int)contour.size();

cv::Mat mask = cv::Mat::zeros(image.size(), image.type());

cv::fillPoly(mask, elementPoints, &numberOfPoints, 1, cv::Scalar( 255, 255, 255), 8);

cv::Mat dstImage = cv::Mat::zeros(image.size(), image.type());

cv::bitwise_and(image, mask, dstImage);

imwrite("test.jpg", dstImage);

I know that I need to use alpha channel, but it's unclear what I need to do next and how to implement this.

How can I get transparent background outside the mask?

konstantin_doncov
  • 2,725
  • 4
  • 40
  • 100
  • Possible duplicate of [OpenCV: transforming 3 channel image into 4 channel](https://stackoverflow.com/questions/13451936/opencv-transforming-3-channel-image-into-4-channel) – Aconcagua Jul 19 '18 at 11:58
  • @Aconcagua this isn't a solution. – konstantin_doncov Jul 19 '18 at 12:03
  • You asked for adding an alpha channel, didn't you? What do you think the 4th channel is??? – Aconcagua Jul 19 '18 at 12:03
  • @Aconcagua please reread my post again, last update can make it more clear – konstantin_doncov Jul 19 '18 at 12:07
  • Can [this](https://stackoverflow.com/a/32290192/3051961) help you? – ZdaR Jul 19 '18 at 12:08
  • OK, assuming you have successfully added the alpha channel already, then you set opacity to 0 outside the polygon and to 255 inside. You don't *have* to clear out RGB values, but you might do so for better compression of the resulting image... – Aconcagua Jul 19 '18 at 12:13
  • @Aconcagua thanks for your advice, but I'm not so good in OpenCV. I would be very grateful if you could post an answer with the code which you mean – konstantin_doncov Jul 19 '18 at 12:41
  • 1
    add a 4th channel by splitting the BGR image to 3 single images, then merge again an use the mask as the 4th image. Then save as .png or any other alpha channel image format. – Micka Jul 19 '18 at 12:54

1 Answers1

1

First, create your image with four channels as described in this answer. Use negative source for fourth channel to get it zeroed out already. You now have a totally transparent image.

Create your mask just as you did before, just using different RGBA values (be aware that Scalar has a fourth constructor parameter for alpha values):

cv::fillPoly(mask, elementPoints, &numberOfPoints, 1, cv::Scalar(0, 0, 0, 255), 8);

Finally, apply the mask to set the region in question to totally opaque:

cv::bitwise_or(image, mask, dstImage);

You might want to retain the RGB values of the original image (so you can operate on later) or you might clear them out (which will result in higher compression and thus smaller file size). If the latter, use an inverted mask with RGBA set to 0, 0, 0, 0 and apply that with bitwise_and...

Aconcagua
  • 24,880
  • 4
  • 34
  • 59