5

does OpenCV support alpha-channel? Or is there any way to work with transparent png? I need to merge two images, where the first one is background and the second one is image which was rotated by cvWarpAffine. I can do this by merging pixels one by one and omit pixels with some value, which I set in cvScalar in cvWarpAffine. However, I don't think that this is intended solution. Thanks for suggestions

  • This is one of the oldest questions on this subject and still attracts many visitors. Here's a [more recent answer](https://stackoverflow.com/a/49180468/176769) if you are looking for some code. – karlphillip Mar 08 '18 at 19:17

2 Answers2

8

Updated answer: Use CV_LOAD_IMAGE_UNCHANGED flag to load all four channels (including Alpha) from the image. Then, use mixChannels() and/or split() to separate the alpha channel from others, and threshold on it, as explained below.

Very old answer:

OpenCV does not support alpha channel, only masking. If you want to read in PNG with alpha, use imagemagick first to extract alpha channel:

convert input.png -channel Alpha -negate -separate input-mask.png

Then in OpenCV you can do sth like this:

Mat_<float> mask = imread("input-mask.png", 0);
threshold(mask, mask, 254., 1., THRESH_BINARY);

... to get a real mask (usable as mask matrix in OpenCV operations). Or you can use it in your own operations without the thresholding. To apply the mask it may also be a good idea to extend it to three channels:

std::vector<Mat> marr(3, mask);
Mat_<Vec<float, 3> > maskRGB;
merge(marr, maskRGB);

After that you can test it like this:

imshow("Target", target);
imshow("Mask", mask*255);
imshow("Applied", target.mul(maskRGB));
waitKey();

Note: This is OpenCV 2.0 code.

ypnos
  • 50,202
  • 14
  • 95
  • 141
2

Here is a bash script that I threw together that will perform the ImageMagick conversion given by ypnos on all of the png files in a directory. You can make it recursive by replacing the * in the third line with a find command.

#!/bin/bash

for file in *
do
    if [[ $file =~ (.+)-mask\.png ]]; then
        echo "Ignoring mask $file"
    elif [[ $file =~ (.+)\.png ]]; then
        echo "Generating mask for $file"
        basefn=${BASH_REMATCH[1]}
        convert "$basefn.png" -channel Alpha -negate -separate "$basefn-mask.png"
    fi
done
Jonathan
  • 4,847
  • 3
  • 32
  • 37