What is the most efficient way to make an alpha mask in opencv?

I know that OpenCV only supports binary masks.
But I need to make an overlay where I have a shade of gray that determines the transparency of the overlay.

Eg. if the pixel in the mask is 50% white, this means the operation cv::addWeighted for this pixel with alpha = beta = 0.5, gamma = 0.0.

Now, if there is no opencv library function, what algorithm would you suggest as the most efficient?

+7
source share
3 answers

I did something similar to fix it.

 typedef double Mask_value_t; typedef Mat_<Mask_value_t> Mask; void cv::addMasked(const Mat& src1, const Mat& src2, const Mask& mask, Mat& dst) { MatConstIterator_<Vec3b> it1 = src1.begin<Vec3b>(), it1_end = src1.end<Vec3b>(); MatConstIterator_<Vec3b> it2 = src2.begin<Vec3b>(); MatConstIterator_<Mask_value_t> mask_it = mask.begin(); MatIterator_<Vec3b> dst_it = dst.begin<Vec3b>(); for(; it1 != it1_end; ++it1, ++it2, ++mask_it, ++dst_it) *dst_it = (*it1) * (1.0-*mask_it) + (*it2) * (*mask_it); } 

I have not yet optimized and made this assertion code safe.
Working assumptions: all mats and masks are the same size, and Mat are normal three-channel color images.

+5
source

I have a similar problem when I wanted to apply png with transparency. My solution was to use Mat expressions:

 void AlphaBlend(const Mat& imgFore, Mat& imgDst, const Mat& alpha) { vector<Mat> vAlpha; Mat imgAlpha3; for(int i = 0; i < 3; i++) vAlpha.push_back(alpha); merge(vAlpha,imgAlpha3) Mat blend = imgFore.mul(imgAlpha3,1.0/255) + imgDst.mul(Scalar::all(255)-imgAlpha3,1.0/255); blend.copyTo(imgDst); } 
+3
source

OpenCV supports RGBA images, which you can create with mixchannels or split and merge to combine images with your grayscale mask. Hope this is what you are looking for!

Using this method, you can combine a grayscale mask with your image as follows:

  cv::Mat gray_image, mask, rgba_image; std::vector<cv::Mat> result; cv::Mat image = cv::imread(image_path); cv::split(image, result); cv::cvtColor(image, gray_image, CV_BGR2GRAY); cv::threshold(gray_image, mask, 128, 255, CV_THRESH_BINARY); result.push_back(mask); cv::merge(result, rgba_image); imwrite("rgba.png", rgba_image); 

Keep in mind that you cannot view RGBA images using cv::imshow as described in read-rgba-image-opencv , and you cannot save the image as jpeg, because this format does not support transparency. It seems that you can combine channels using cv::cvtcolor , as shown in opencv-2-3-convert-mat-to-rgba-pixel-array

-one
source

All Articles