4
votes

I have a tif image that has transparent pixels (I can see them in paint.net as transparent pixels).

I am trying to read them into a Mat in openCV and I am using this code:

Mat image=imread(imagePathname,CV_LOAD_IMAGE_UNCHANGED);
auto x=image.channels();

based on I my understanding, since the input image has transparency, channels() should return 4, but it return 3.

How can I read a tif image with transparent pixels and checking if a pixel is transparent in opencv?

edit1

Result of running imagemagick:

Image: layer0003.tif
  Format: TIFF (Tagged Image File Format)
  Mime type: image/tiff
  Class: DirectClass
  Geometry: 10000x5000+0+0
  Resolution: 150x150
  Print size: 66.6667x33.3333
  Units: PixelsPerInch
  Type: TrueColorAlpha
  Base type: TrueColor
  Endianess: MSB
  Colorspace: sRGB
  Depth: 8-bit
  Channel depth:
    red: 8-bit
    green: 8-bit
    blue: 8-bit
    alpha: 1-bit
  Channel statistics:
    Red:
      min: 0 (0)
      max: 255 (1)
      mean: 23.6472 (0.0927342)
      standard deviation: 37.6851 (0.147785)
      kurtosis: 8.93054
      skewness: 2.28009
    Green:
      min: 0 (0)
      max: 255 (1)
      mean: 22.8353 (0.0895504)
      standard deviation: 37.6516 (0.147653)
      kurtosis: 10.4255
      skewness: 2.52881
    Blue:
      min: 0 (0)
      max: 255 (1)
      mean: 22.798 (0.0894041)
      standard deviation: 37.6575 (0.147677)
      kurtosis: 10.9059
      skewness: 2.58999
    Alpha:
      min: 0 (0)
      max: 255 (1)
      mean: 89.055 (0.349235)
      standard deviation: 121.566 (0.476728)
      kurtosis: -1.59995
      skewness: -0.632496
  Image statistics:
    Overall:
      min: 0 (0)
      max: 255 (1)
      mean: 58.8064 (0.230613)
      standard deviation: 68.9821 (0.270518)
      kurtosis: 8.35337
      skewness: 3.53852
  Alpha: none   #00000000
  Rendering intent: Perceptual
  Gamma: 0.454545
  Chromaticity:
    red primary: (0.64,0.33)
    green primary: (0.3,0.6)
    blue primary: (0.15,0.06)
    white point: (0.3127,0.329)
  Background color: white
  Border color: srgba(223,223,223,1)
  Matte color: grey74
  Transparent color: none
  Interlace: None
  Intensity: Undefined
  Compose: Over
  Page geometry: 10000x5000+0+0
  Dispose: Undefined
  Iterations: 0
  Compression: LZW
  Orientation: TopLeft
  Properties:
    date:create: 2014-03-01T13:11:12+00:00
    date:modify: 2014-02-28T17:48:41+00:00
    signature: dfa3e35c35345ef3440ff15d15ad37222f9cf0376bed7b7710dd95f4e537e210
    tiff:alpha: unassociated
    tiff:endian: lsb
    tiff:photometric: RGB
    tiff:rows-per-strip: 1
    tiff:timestamp: 2014:02:28 17:48:38
    xmp:CreatorTool: Microsoft Windows Live Photo Gallery 15.4.3555.308
  Profiles:
    Profile-xmp: 12702 bytes
  Artifacts:
    filename: layer0003.tif
    verbose: true
  Tainted: False
  Filesize: 20.42MB
  Number pixels: 50M
  Pixels per second: 60.24MB
  User time: 0.827u
  Elapsed time: 0:01.829
  Version: ImageMagick 6.8.8-7 Q16 x64 2014-02-13 http://www.imagemagick.org
1
Try using ImageMagick and running "identify -verbose yourimage.tif" to see if it has an alpha channel or not. imagemagick.org/script/identify.phpMark Setchell
@MarkSetchell: result shows that it has alpha channel (See me edited questions), but it is only one bit depth. Is it important?mans
Can you post your image ?Haris
@Haris: Yes I can do, but when I try to do it, it converted to bmp which loses its alpha. Is there any way that I post it as an attachment instead of an image? here is a sample image that I post the other day to this forum: stackoverflow.com/questions/22119246/… loo for tif images and the end of question.mans
I suspect OpenCV expects an 8-bit alpha channel, not 1-bit. Maybe you can extract the alpha channel with ImageMagick and scale it by multiplying by 255. You could try this command to see the histogram of the alpha channel... convert image.tif -alpha extract -format "%c" histogram:info:Mark Setchell

1 Answers

0
votes

I just had some time to revisit this :-)

Basically, I think the issue is that ImageMagick will adopt the most economical, in terms of file size, when writing its output files. So, if your image is basically greyscale but the alpha (opacity) channel is only 0 or 1, ImageMagick will encode that with 16-bit greyscale for the data and single-bit alpha channel. I guess that is beyond OpenCV as it seems to expect the alpha to be encoded with the same depth as the data.

So, the question becomes... "How can you force the combination you need of data/alpha (both 8-bit, not 8-bit plus 1-bit) greyscale/colour (8-bit greyscale or 8-bit colour)?"

There may be other ways, but for now, I can envisage adding a row across the bottom of the image that forces ImageMagick's hand and which you can hopefully readily remove once it has done the trick for you in OpenCV.

So, let's create a 16-bit greyscale image with a single-bit alpha where it makes the square transparent hole in the middle:

convert -size 300x300 gradient:black-white -alpha set -region 100x100+100+100 -alpha transparent image.tif

enter image description here

Let's check what we have:

identify -verbose image.tif | head -14

Image: image.tif
  Format: TIFF (Tagged Image File Format)
  Mime type: image/tiff
  Class: DirectClass
  Geometry: 300x300+0+0
  Units: PixelsPerInch
  Type: GrayscaleAlpha
  Base type: Grayscale
  Endianess: LSB
  Colorspace: Gray
  Depth: 16-bit
  Channel depth:
    gray: 16-bit          <--- 16-bit greyscale data
    alpha: 1-bit          <--- 1-bit alpha

Now let's force it to 8-bit alpha and 8-bit data:

# Force to at least 8-bit greyscale (but maybe RGB depending on rest of image) plus 8-bit alpha...
# ... by adding a line across the bottom with alpha varying from 0 to 1 (i=x coordinate,w=width)
convert image.tif                                \
   \( +clone -resize x1! -channel A -fx "i/w" \) \
   -append -depth 8 result.tif

enter image description here

Let's check it worked:

identify -verbose result.tif | head -16

Image: result.tif
  Format: TIFF (Tagged Image File Format)
  Mime type: image/tiff
  Class: DirectClass
  Geometry: 300x301+0+0      <--- one extra row
  Units: PixelsPerInch
  Type: GrayscaleAlpha
  Base type: Grayscale
  Endianess: LSB
  Colorspace: Gray
  Depth: 8-bit
  Channel depth:
    gray: 8-bit              <--- 8-bit data
    alpha: 8-bit             <--- 8-bit alpha

Now let's force 8-bit RGB plus 8-bit alpha:

# Force to 8-bit RGB plus 8-bit alpha...
# ...  by adding a coloured line across the bottom with alpha varying from 0 to 1 (i=x coordinate,w=width)
convert image.tif                                      \
   \( +clone -resize x1! -channel RGBA -fx "rand()" \) \
   -append -depth 8 result.tif

enter image description here

And let's check again:

Image: result.tif
  Format: TIFF (Tagged Image File Format)
  Mime type: image/tiff
  Class: DirectClass
  Geometry: 300x301+0+0       <--- 1 extra row
  Units: PixelsPerInch
  Type: TrueColorAlpha
  Base type: TrueColor        <--- Truecolour
  Endianess: LSB
  Colorspace: sRGB            <--- RGB
  Depth: 8-bit
  Channel depth:
    red: 8-bit                <--- 8-bit red
    green: 8-bit              <--- 8-bit green
    blue: 8-bit               <--- 8-bit blue
    alpha: 8-bit              <--- 8-bit alpha