Spaces:
Sleeping
Sleeping
File size: 6,106 Bytes
62f828b |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 |
import pydicom
import numpy as np
from pydicom.pixels import apply_voi_lut
from skimage import exposure
from PIL import Image,ImageEnhance
import cv2
def read_xray(path, voi_lut=True, fix_monochrome=True):
"""
Read and preprocess a DICOM X-ray image.
Parameters:
- path: Path to the DICOM file.
- voi_lut: Apply VOI LUT if available.
- fix_monochrome: Fix inverted monochrome images.
Returns:
- NumPy array: Preprocessed X-ray image.
"""
dicom = pydicom.dcmread(path)
# Apply VOI LUT if available
if voi_lut:
data = apply_voi_lut(dicom.pixel_array, dicom)
else:
data = dicom.pixel_array
# Fix inverted monochrome images
if fix_monochrome and dicom.PhotometricInterpretation == "MONOCHROME1":
data = np.amax(data) - data
# Normalize data to start from 0
data = data - np.min(data)
return data
def resize_pil_image(image: Image.Image, target_shape: tuple) -> Image.Image:
"""
Resizes a PIL image based on a target shape.
Args:
image: Input PIL image.
target_shape: Desired shape for resizing. It can be a 2D tuple (height, width)
or a 3D tuple (height, width, channels), where channels will be ignored.
Returns:
Resized PIL image.
"""
# Convert image to a numpy array
np_image = np.array(image)
# Extract the original height and width from the numpy array
height, width = np_image.shape[:2]
# If the target shape is 2D (height, width)
if len(target_shape) == 2:
new_width, new_height = target_shape
elif len(target_shape) == 3:
# If the target shape is 3D (height, width, channels), only change the first two dimensions
new_width, new_height = target_shape[:2]
else:
raise ValueError("Target shape must be either 2D or 3D.")
# Resize the image using cv2 or PIL's in-built resizing (no channels affected)
pil_resized_image = Image.fromarray(np_image).resize((new_width, new_height), Image.LANCZOS)
return pil_resized_image
def enhance_exposure(img):
"""
Enhance image exposure using histogram equalization.
Parameters:
- img: Input image as a NumPy array.
Returns:
- PIL.Image: Exposure-enhanced image.
"""
img = exposure.equalize_hist(img)
img = exposure.equalize_adapthist(img / np.max(img))
img = (img * 255).astype(np.uint8)
return Image.fromarray(img)
def unsharp_masking(image, kernel_size=5, strength=0.25):
"""
Apply unsharp masking to enhance image sharpness.
Parameters:
- image: Input image as a NumPy array or PIL.Image.
- kernel_size: Size of the Gaussian blur kernel.
- strength: Strength of the high-pass filter.
Returns:
- PIL.Image: Sharpened image.
"""
image = np.array(image)
# Convert to grayscale if needed
if len(image.shape) == 3:
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
else:
gray = image
# Apply Gaussian blur and calculate high-pass filter
blurred = cv2.GaussianBlur(gray, (kernel_size, kernel_size), 0)
high_pass = cv2.subtract(gray, blurred)
# Combine high-pass with original image
sharpened = cv2.addWeighted(gray, 1, high_pass, strength, 0)
return Image.fromarray(sharpened)
def increase_contrast(image: Image.Image, factor: float) -> Image.Image:
"""
Increases the contrast of the input PIL image by a given factor.
Args:
image: Input PIL image.
factor: Factor by which to increase the contrast.
A factor of 1.0 means no change, values greater than 1.0 increase contrast,
values between 0.0 and 1.0 decrease contrast.
Returns:
Image with increased contrast.
"""
if image.mode not in ['RGB', 'L']:
image = image.convert('RGB')
enhancer = ImageEnhance.Contrast(image)
image_enhanced = enhancer.enhance(factor)
return image_enhanced
def increase_brightness(image: Image.Image, factor: float) -> Image.Image:
"""
Increases the brightness of the input PIL image by a given factor.
Args:
image: Input PIL image.
factor: Factor by which to increase the brightness.
A factor of 1.0 means no change, values greater than 1.0 increase brightness,
values between 0.0 and 1.0 decrease brightness.
Returns:
Image with increased brightness.
"""
if image.mode not in ['RGB', 'L']:
image = image.convert('RGB')
enhancer = ImageEnhance.Brightness(image)
image_enhanced = enhancer.enhance(factor)
return image_enhanced
def apply_clahe(image, clipLimit=2.0, tileGridSize=(8, 8)):
"""
Apply CLAHE (Contrast Limited Adaptive Histogram Equalization) to an image.
Parameters:
- image: Input image as a PIL.Image.
- clipLimit: Threshold for contrast limiting.
- tileGridSize: Size of the grid for histogram equalization.
Returns:
- Processed image in the same format as the input (PIL.Image).
"""
image_np = np.array(image)
image_np = cv2.cvtColor(image_np, cv2.COLOR_RGB2BGR)
# Apply CLAHE based on image type
if len(image_np.shape) == 2:
# Grayscale image
clahe = cv2.createCLAHE(clipLimit=clipLimit, tileGridSize=tileGridSize)
processed = clahe.apply(image_np)
else:
# Color image: Apply CLAHE on the L channel in LAB space
lab = cv2.cvtColor(image_np, cv2.COLOR_BGR2LAB)
L, A, B = cv2.split(lab)
clahe = cv2.createCLAHE(clipLimit=clipLimit, tileGridSize=tileGridSize)
L_clahe = clahe.apply(L)
lab_clahe = cv2.merge((L_clahe, A, B))
processed = cv2.cvtColor(lab_clahe, cv2.COLOR_LAB2BGR)
processed_rgb = cv2.cvtColor(processed, cv2.COLOR_BGR2RGB)
return Image.fromarray(processed_rgb)
|