Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When reading 4-channel tif file, value different from SKIMAGE, TIFFFILE and so on

I know the opencv got a BGR order, but in my experiment, not only the order but also the values are totally messed

import cv2 as cv
import tifffile as tiff
import skimage.io

img_path = r"C:\test\pics\t100r50s16_1_19.tif"
c = cv.imread(img_path,cv.IMREAD_UNCHANGED)
t = tiff.imread(img_path)
s = skimage.io.imread(img_path)

print("c:", c.shape, "t:", t.shape, "s:", s.shape)
print("c:", c.dtype, "t:", t.dtype, "s:", s.dtype)

print(c[0, 0], c[1023, 0], c[0, 1023], c[1023, 1023])
print(t[0, 0], t[1023, 0], t[0, 1023], t[1023, 1023])
print(s[0, 0], s[1023, 0], s[0, 1023], s[1023, 1023])

print(c.sum())
print(t.sum())
print(s.sum())

And the outputs like this:

c: (1024, 1024, 4) t: (1024, 1024, 4) s: (1024, 1024, 4)
c: uint8 t: uint8 s: uint8
[ 50  63  56 182] [131 137 140 193] [29 28 27 94] [123 130 134 190]
[ 79  88  70 182] [185 181 173 193] [74 77 80 94] [180 174 165 190]
[ 79  88  70 182] [185 181 173 193] [74 77 80 94] [180 174 165 190]
# Here seems that opencv only read the alpha channel right, 
# the values of first three channels are much different than other package

539623146
659997127
659997127

The image i use can be download here. So, here is my question, how open cv handle 4 channel tiff file? Because when i test on 3-channel image, everything looks alright.

like image 593
Ziyi He Avatar asked Sep 26 '18 02:09

Ziyi He


People also ask

How many channels does a tiff have?

Frames and Channels in TIFF files There is one channel per colour. A conventional colour image is made up of 3 colour channels: red, green and blue. A grayscale (black and white) image has just one channel.

Can OpenCV read TIFF?

So, OpenCV can always read JPEGs, PNGs, and TIFFs.


1 Answers

I don't buy it for a minute that there is a rounding error or some error related to JPEG decoding like the linked article suggests.

Firstly because your image is integer, specifically uint8 so there is no rounding of floats, and secondly because the compression of your TIF image is not JPEG - in fact there is no compression. You can see that for yourself if you use ImageMagick and do:

identify -verbose a.tif

or if you use tiffinfo that ships with libtiff, like this:

tiffinfo -v a.tif

So, I did some experiments by generating sample images with ImageMagick like this:

# Make 8x8 pixel TIF full of RGBA(64,128,192) with full opacity
convert -depth 8 -size 8x8 xc:"rgba(64,128,192,1)" a.tif

# Make 8x8 pixel TIFF with 4 rows per strip
convert -depth 8 -define tiff:rows-per-strip=4 -size 8x8 xc:"rgba(64,128,192,1)" a.tif

And OpenCV was able to read all those correctly, however, when I did the following it went wrong.

# Make 8x8 pixel TIFF with RGB(64,128,192) with 50% opacity
convert -depth 8 -define tiff:rows-per-strip=1 -size 8x8 xc:"rgba(64,128,192,0.5)" a.tif

And the values came out in OpenCV as 32, 64, 96 - yes, exactly HALF the correct values - like OpenCV is pre-multiplying the alpha. So I tried with an opacity of 25% and the values came out at 1/4 of the correct ones. So, I suspect there is a bug in OpenCV that premultiplies the alpha.

If you look at your values, you will see that tifffile and skimage read the first pixel as:

[ 79  88  70 182 ]

if you look at the alpha of that pixel, it is 0.713725 (182/255), and if you multiply each of those values by that, you will get:

[ 50  63  56 182 ]

which is exactly what OpenCV did.

As a workaround, I guess you could divide by the alpha to scale correctly.


In case the argument is that OpenCV intentionally pre-multiplies the alpha, then that begs the question why it does that for TIFF files but NOT for PNG files:

# Create 8x8 PNG image full of rgb(64,128,192) with alpha=0.5
convert -depth 8 size 8x8 xc:"rgba(64,128,192,0.5)" a.png

Check with OpenCV:

import cv2
c = cv2.imread('a.png',cv2.IMREAD_UNCHANGED)

In [4]: c.shape
Out[4]: (8, 8, 4)

In [5]: c
Out[5]: 
array([[[192, 128,  64, 128],
        [192, 128,  64, 128],
...
...

In case anyone thinks that the values in the TIF file are as OpenCV reports them, I can only say that I wrote rgb(64,128,192) at 50% opacity and I tested each of the following and found that they all agree, with the sole exception of OpenCV that that is exactly what the file contains:

  • ImageMagick v7
  • libvips v8
  • Adobe Photoshop CC 2017
  • PIL/Pillow v5.2.0
  • GIMP v2.8
  • scikit-image v0.14
like image 123
Mark Setchell Avatar answered Nov 15 '22 09:11

Mark Setchell