HMCLIP / data_process.py
SteveZeyuZhang's picture
Start resumable backup upload: root source files
1cc4fea
Raw History Blame Contribute Delete
4.66 kB
import nibabel as nib
import torch
import numpy as np
import torch.nn.functional as F
from PIL import Image
import random
def resize_array(array, current_spacing, target_spacing):
"""
Resize the array to match the target spacing.
Args:
array (torch.Tensor): Input array to be resized.
current_spacing (tuple): Current voxel spacing (z_spacing, xy_spacing, xy_spacing).
target_spacing (tuple): Target voxel spacing (target_z_spacing, target_x_spacing, target_y_spacing).
Returns:
np.ndarray: Resized array.
"""
# Calculate new dimensions
original_shape = array.shape[2:]
scaling_factors = [
current_spacing[i] / target_spacing[i] for i in range(len(original_shape))
]
new_shape = [
int(original_shape[i] * scaling_factors[i]) for i in range(len(original_shape))
]
# Resize the array
resized_array = F.interpolate(array, size=new_shape, mode='trilinear', align_corners=False).cpu().numpy()
return resized_array
def load_3d_image_to_tensor(path):
nii_img = nib.load(str(path))
img_data = nii_img.get_fdata()
img_data = np.flip(img_data, axis=0)
img_data = np.flip(img_data, axis=1)
# WARNING Respacing
img_data = img_data.transpose(2, 0, 1)
img_data = np.copy(img_data)
tensor = torch.tensor(img_data)
tensor = tensor.unsqueeze(0).unsqueeze(0)
target_x_spacing = 0.75
target_y_spacing = 0.75
target_z_spacing = 1.5
current = (3, 1, 1) # this is all set to 3 1 1
target = (target_z_spacing, target_x_spacing, target_y_spacing)
img_data = resize_array(tensor, current, target)
img_data = img_data[0][0]
img_data= np.transpose(img_data, (1, 2, 0))
# WARNING Normalization 2
hu_min, hu_max = -1000, 1000
img_data = np.clip(img_data, hu_min, hu_max)
img_data = (((img_data ) / 1000)).astype(np.float32)
tensor = torch.tensor(img_data)
# WARNING Padding or Crop
# Get the dimensions of the input tensor
target_shape = (480,480,240) # h w d
# Extract dimensions
h, w, d = tensor.shape
# Calculate cropping/padding values for height, width, and depth
dh, dw, dd = target_shape
h_start = max((h - dh) // 2, 0)
h_end = min(h_start + dh, h)
w_start = max((w - dw) // 2, 0)
w_end = min(w_start + dw, w)
d_start = max((d - dd) // 2, 0)
d_end = min(d_start + dd, d)
# Crop or pad the tensor
tensor = tensor[h_start:h_end, w_start:w_end, d_start:d_end]
pad_h_before = (dh - tensor.size(0)) // 2
pad_h_after = dh - tensor.size(0) - pad_h_before
pad_w_before = (dw - tensor.size(1)) // 2
pad_w_after = dw - tensor.size(1) - pad_w_before
pad_d_before = (dd - tensor.size(2)) // 2
pad_d_after = dd - tensor.size(2) - pad_d_before
tensor = torch.nn.functional.pad(tensor, (pad_d_before, pad_d_after, pad_w_before, pad_w_after, pad_h_before, pad_h_after), value=-1)
tensor = tensor.permute(2, 0, 1) # d h w
tensor = tensor.unsqueeze(0) # 1 d h w
return tensor
def load_2d_image_to_tensor(image_path,resize=False):
"""
Load a 2D grayscale image and convert it to a tensor with dimensions [1, 1, 480, 480].
Args:
image_path (str): Path to the image file.
Returns:
tensor (torch.Tensor): Tensor with shape [1, 1, 480, 480].
"""
# Load the image as grayscale
image = Image.open(image_path).convert('L')
# Resize to 480x480 if needed
if resize:
if image.size != (480, 480):
image = image.resize((480, 480), Image.BILINEAR)
else:
if image.size != (480, 480):
# 计算可以开始裁剪的最大左上角坐标
width, height = image.size
crop_size = 480
if width < crop_size or height < crop_size:
raise ValueError(f"Image size {image.size} is smaller than the crop size {crop_size}.")
max_left = width - crop_size
max_top = height - crop_size
# 随机选择裁剪的左上角坐标
left = random.randint(0, max(0, max_left))
top = random.randint(0, max(0, max_top))
# 裁剪图像
image = image.crop((left, top, left + crop_size, top + crop_size))
# Convert to numpy array and normalize to [0, 1]
img_array = (np.array(image, dtype=np.float32) / 255.0) * 2 -1
# Convert to tensor
tensor = torch.from_numpy(img_array)
# Add batch and channel dimensions
tensor = tensor.unsqueeze(0).unsqueeze(0) # [1, 1, 480, 480]
return tensor