Reading .tif images: vector of 8-bit unsigned in vs. 8-bit unsigned int

I have come across this issue, where some .tif files that I read into SimpleITK load as “8-but unsigned int”, but others load as “vector of 8-bit unsigned int”.

I have been reading in the .tif images using sitk.ReadImage(img) function, and then casting to sitkFloat32 type. But when the images load initially as vector of 8-bit unsigned int, this casting function errors out.

I have attached two images - one that loads as a vector and other that loads normally as 8-bit unsigned int.

searchArea.tif (vector of 8-bit unsigned int):
searchArea0.tif (210.0 KB)

SUB0.tif (8-bit unsigned int):
SUB0.tif (10.6 KB)

I really am just unsure as to why there is a difference loading certain .tif images. I think it has to do with the RGB factor, but how can I change this to load only one channel?

Thank you

The command line too “tiffinfo” is useful to looking at the TIFF tags. Here are the results:

# tiffinfo searchArea0.tif 
TIFFReadDirectory: Warning, Unknown field with tag 50838 (0xc696) encountered.
TIFFReadDirectory: Warning, Unknown field with tag 50839 (0xc697) encountered.
TIFF Directory at offset 0x8 (8)
  Subfile Type: (0 = 0x0)
  Image Width: 267 Image Length: 268
  Resolution: 1.319, 1.319 (unitless)
  Bits/Sample: 8
  Compression Scheme: None
  Photometric Interpretation: RGB color
  Samples/Pixel: 3
  Rows/Strip: 268
  Planar Configuration: single image plane
  ImageDescription: ImageJ=1.53k
unit=micron

  Tag 50838: 12,156
  Tag 50839: 73,74,73,74,105,110,102,111,0,0,0,1,0,83,0,111,0,102,0,116,0,119,0,97,0,114,0,101,0,58,0,32,0,87,0,105,0,110,0,100,0,111,0,119,0,115,0,32,0,80,0,104,0,111,0,116,0,111,0,32,0,69,0,100,0,105,0,116,0,111,0,114,0,32,0,49,0,48,0,46,0,48,0,46,0,49,0,48,0,48,0,49,0,49,0,46,0,49,0,54,0,51,0,56,0,52,0,10,0,68,0,97,0,116,0,101,0,84,0,105,0,109,0,101,0,58,0,32,0,50,0,48,0,50,0,51,0,58,0,48,0,51,0,58,0,49,0,55,0,32,0,48,0,56,0,58,0,51,0,52,0,58,0,51,0,52,0,10
1 Like

The following is the C++ signature for the ReadImage method:

 Image itk::simple::ReadImage( const std::string & filename, PixelIDValueEnum outputPixelType = sitkUnknown, const std::string & imageIO = "" )	

If outputPixelType is specified as sitkFloat32 the file will be automatically cast when reading.

2 Likes

Hello @elapins,

As @blowekamp highlighted, you can force the images you read to be single channel when you specify the pixel type in the read function.

The more worrying thing is that you appear to have different representations for the same data. How does this arise in your workflow? You need to exercise caution and be familiar with your input characteristics. Forcing everything to scalar without understanding why this is a valid action is dangerous.

Code below interrogates the images and exposes that the “searchArea0.tif” is actually a redundant representation of a scalar image, so you can safely force it to be scalar in the ReadImage, no loss of information. Though it raises the question, why was it saved as a three channel image when it is actually a one channel image?

import SimpleITK as sitk
import numpy as np

image_file_names = ["searchArea0.tif", "SUB0.tif"]

for file_name in image_file_names:
    image = sitk.ReadImage(file_name)
    if image.GetNumberOfComponentsPerPixel() == 1:
        print(f"{file_name}: {image.GetPixelIDTypeAsString()}")
    elif image.GetNumberOfComponentsPerPixel() == 3:
        # is it "really" a three channel image or a single channel repeated three times
        channels = [
            sitk.GetArrayFromImage(sitk.VectorIndexSelectionCast(image, i))
            for i in range(image.GetNumberOfComponentsPerPixel())
        ]
        if np.array_equal(channels[0], channels[1]) and np.array_equal(
            channels[0], channels[2]
        ):
          print(f"{file_name}: {image.GetPixelIDTypeAsString()} - grayscale")
        else:
          print(f"{file_name}: {image.GetPixelIDTypeAsString()} - color")
    else:
          print(f"{file_name}: {image.GetNumberOfComponentsPerPixel()} channels")
2 Likes

Thank you for all your help!!
I created the image causing issues via cropping then saving as .tif via ImageJ. I did not realized that the default is to save as RGB tif image, so I just switched the type in ImageJ, and re-saved, and it worked!!

Thank you for clearing up my confusion. I really appreciate it