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'
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:
The contrast is enhanced, but the input image is mainly noise...