1

As I tried to code the opencv2 to read the tiff image file, It show up

OpenCV TIFF: TIFFRGBAImageOK: Sorry, can not handle images with 32-bit samples

I should expect that the opencv will read the file and process it with enhance contrast a bit.

here is the code:

import os
import cv2

input_folder = 'path'
output_folder = 'path'

# Loop through all TIFF files in the input folder
for filename in os.listdir(input_folder):
    if filename.endswith('.tiff'):
        image = cv2.imread(os.path.join(input_folder, filename), cv2.IMREAD_GRAYSCALE)

        alpha = 1.0035
        beta = 0
        enhanced_image = cv2.convertScaleAbs(image, alpha=alpha, beta=beta)

        output_filename = os.path.splitext(filename)[0] + '_enhanced.tif'
        cv2.imwrite(os.path.join(output_folder, output_filename), enhanced_image)

For the image tiff file, i have upload Here and please use ImageJ to view it.

Update (1), I have tried How do you read a 32-bit TIFF image in python? But it seem have another error which is this

can't open/read file: check file path/integrity

Followed by

cv2.error: OpenCV(4.7.0) D:\a\opencv-python\opencv-python\opencv\modules\imgcodecs\src\loadsave.cpp:783: error: (-215:Assertion failed) !_img.empty() in function 'cv::imwrite'

Neko Lim
  • 53
  • 5
  • Your linked file is inaccessible - maybe try sharing via Google Drive. Try placing another, simpler TIFF in the directory instead of the existing one and see if your paths/filenames are parsing correctly. – Mark Setchell Mar 03 '23 at 08:38

3 Answers3

2

OpenCV doesn't support reading Tiff image in float format (at least not the standard Python version).
We may use tifffile for reading the image:

import tifffile
...
image = tifffile.imread(filename)

There are multiple ways to enhance the contrast of the image.
Two examples: "Linear stretching" and CLAHE.

  • Linear stretching (from my following answer):
    Find minimal and maximal percentile, and apply linear "stretch" such that low percentile goes to 0, and high_prc percentile goes to 255:

     def lin_stretch_img(img, low_prc, high_prc):
         lo, hi = np.percentile(img, (low_prc, high_prc))  # Example: 1% - Low percentile, 99% - High percentile
    
         if lo == hi:
             return np.full(img.shape, 128, np.uint8)  # Protection: return gray image if lo = hi.
    
         stretch_img = (img.astype(np.float32) - lo) * (255/(hi-lo))  # Linear stretch: lo goes to 0, hi to 255.
         stretch_img = stretch_img.clip(0, 255).astype(np.uint8)  # Clip range to [0, 255] and convert to uint8
         return stretch_img
    
  • OpenCV CLAHE:
    Enhancing the contrast in each block, allows much higher contrast compared to the linear stretching.
    Since CLAHE in OpenCV does not support float32, we have to convert the image to uint16 type before applying CLAHE.

     image_as_uint16 = cv2.normalize(image, None, 0, 65535, cv2.NORM_MINMAX, cv2.CV_16U) # Convert to uint16 before applying CLAHE
     clahe = cv2.createCLAHE(clipLimit=20, tileGridSize=(8, 8))
     cl1 = clahe.apply(image_as_uint16)  # CLAHE in OpenCV does not support float32 apply CLAHE to the uint16 image.
     cl1 = cv2.convertScaleAbs(cl1, alpha=255/65535)  # Convert from uint16 to uint8
    

Code sample:

import os
import cv2
import tifffile
import numpy as np

def lin_stretch_img(img, low_prc, high_prc):
    """ 
    Apply linear "stretch" - low_prc percentile goes to 0, 
    and high_prc percentile goes to 255.
    The result is clipped to [0, 255] and converted to np.uint8
    """
    lo, hi = np.percentile(img, (low_prc, high_prc))  # Example: 1% - Low percentile, 99% - High percentile

    if lo == hi:
        return np.full(img.shape, 128, np.uint8)  # Protection: return gray image if lo = hi.

    stretch_img = (img.astype(np.float32) - lo) * (255/(hi-lo))  # Linear stretch: lo goes to 0, hi to 255.
    stretch_img = stretch_img.clip(0, 255).astype(np.uint8)  # Clip range to [0, 255] and convert to uint8
    return stretch_img


filename = 'top_high_1493_2065_132_132_0.tiff'

#image = cv2.imread(filename, cv2.IMREAD_GRAYSCALE)
image = tifffile.imread(filename)

alpha = 1.0035
beta = 0
enhanced_image = cv2.convertScaleAbs(image, alpha=alpha, beta=beta)

# Apply "linear stretching" (lower percentile 0.1 goes to 0, and percentile 99.9 to 255).
lin_enhanced_image = lin_stretch_img(image, 0.1, 99.9)

# Normalizing frame to range [0, 65535], and get the result as type uint16. (65535 = 2**16-1)
image_as_uint16 = cv2.normalize(image, None, 0, 65535, cv2.NORM_MINMAX, cv2.CV_16U) # Convert to uint16 before applying CLAHE
clahe = cv2.createCLAHE(clipLimit=20, tileGridSize=(8, 8))
cl1 = clahe.apply(image_as_uint16)  # CLAHE in OpenCV does not support float32 apply CLAHE to the uint16 image.
cl1 = cv2.convertScaleAbs(cl1, alpha=255/65535)  # Convert from uint16 to uint8

output_filename = os.path.splitext(filename)[0] + '_enhanced.tif'
cv2.imwrite(output_filename, enhanced_image)

cv2.imwrite(os.path.splitext(filename)[0] + '_lin_enhanced.tif', lin_enhanced_image)

cv2.imwrite(os.path.splitext(filename)[0] + '_cl1_enhanced.tif', cl1)

CLAHE output for example:
enter image description here
The contrast is enhanced, but the input image is mainly noise...

Rotem
  • 30,366
  • 4
  • 32
  • 65
1

You can use Skimage to read, stretch the dynamic range and write your result in Python. Here I stretch the dynamic range to full dynamic range and save to both 8-bit and 32-bit results.

from skimage import io
from skimage import exposure
import numpy as np

# read 32-bit tiff using skimage
img = io.imread('top_high_1493_2065_132_132_0.tiff', as_gray=True)
print(img.shape)

# get input min and max values   
imin=np.amin(img)
imax=np.amax(img)
print(imin, imax)

# stretch dynamic range using skimage
result8 = exposure.rescale_intensity(img, in_range=(imin,imax), out_range=(0,255)).astype(np.uint8)
result32 = exposure.rescale_intensity(img, in_range=(imin,imax), out_range='dtype').astype(np.float32)

# save results
io.imsave('top_high_1493_2065_132_132_0_stretch8.tiff', result8)
io.imsave('top_high_1493_2065_132_132_0_stretch32.tiff', result32)

# show result
io.imshow(result8) 
io.imshow(result32) 
io.show()

Result:

enter image description here

fmw42
  • 46,825
  • 10
  • 62
  • 80
0

Try cv2.imread(fullImagePath, flags=(cv2.IMREAD_GRAYSCALE | cv2.IMREAD_ANYDEPTH))

ref

How do you read a 32-bit TIFF image in python?

balu
  • 1,023
  • 12
  • 18
  • Hi, it shows that "can't open/read file: check file path/integrity" and in the last line, [cv2.error: OpenCV(4.7.0) D:\a\opencv-python\opencv-python\opencv\modules\imgcodecs\src\loadsave.cpp:783: error: (-215:Assertion failed) !_img.empty() in function 'cv::imwrite'] – Neko Lim Mar 03 '23 at 07:41