Compare commits
1 Commits
gpt-5.2
...
gemini-3-p
| Author | SHA1 | Date | |
|---|---|---|---|
| 0d23053e31 |
BIN
image-inpainting/results/testset/tikaiz-21.9691.npz
Normal file
BIN
image-inpainting/results/testset/tikaiz-21.9691.npz
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -15,8 +15,10 @@ def init_weights(m):
|
|||||||
nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
|
nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
|
||||||
if m.bias is not None:
|
if m.bias is not None:
|
||||||
nn.init.constant_(m.bias, 0)
|
nn.init.constant_(m.bias, 0)
|
||||||
elif isinstance(m, nn.BatchNorm2d):
|
elif isinstance(m, (nn.BatchNorm2d, nn.InstanceNorm2d)):
|
||||||
|
if m.weight is not None:
|
||||||
nn.init.constant_(m.weight, 1)
|
nn.init.constant_(m.weight, 1)
|
||||||
|
if m.bias is not None:
|
||||||
nn.init.constant_(m.bias, 0)
|
nn.init.constant_(m.bias, 0)
|
||||||
|
|
||||||
|
|
||||||
@@ -69,35 +71,36 @@ class CBAM(nn.Module):
|
|||||||
|
|
||||||
|
|
||||||
class ConvBlock(nn.Module):
|
class ConvBlock(nn.Module):
|
||||||
"""Convolutional block with Conv2d -> BatchNorm -> LeakyReLU"""
|
"""Convolutional block with Conv2d -> InstanceNorm2d -> GELU"""
|
||||||
def __init__(self, in_channels, out_channels, kernel_size=3, padding=1, dropout=0.0):
|
def __init__(self, in_channels, out_channels, kernel_size=3, padding=1, dropout=0.0, dilation=1):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.conv = nn.Conv2d(in_channels, out_channels, kernel_size, padding=padding)
|
self.conv = nn.Conv2d(in_channels, out_channels, kernel_size, padding=padding, dilation=dilation)
|
||||||
self.bn = nn.BatchNorm2d(out_channels)
|
# InstanceNorm is preferred for style/inpainting tasks
|
||||||
self.relu = nn.LeakyReLU(0.1, inplace=True)
|
self.bn = nn.InstanceNorm2d(out_channels, affine=True)
|
||||||
|
self.act = nn.GELU()
|
||||||
self.dropout = nn.Dropout2d(dropout) if dropout > 0 else nn.Identity()
|
self.dropout = nn.Dropout2d(dropout) if dropout > 0 else nn.Identity()
|
||||||
|
|
||||||
def forward(self, x):
|
def forward(self, x):
|
||||||
return self.dropout(self.relu(self.bn(self.conv(x))))
|
return self.dropout(self.act(self.bn(self.conv(x))))
|
||||||
|
|
||||||
class ResidualConvBlock(nn.Module):
|
class ResidualConvBlock(nn.Module):
|
||||||
"""Residual convolutional block for better gradient flow"""
|
"""Residual convolutional block for better gradient flow"""
|
||||||
def __init__(self, channels, dropout=0.0):
|
def __init__(self, channels, dropout=0.0, dilation=1):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.conv1 = nn.Conv2d(channels, channels, 3, padding=1)
|
self.conv1 = nn.Conv2d(channels, channels, 3, padding=dilation, dilation=dilation)
|
||||||
self.bn1 = nn.BatchNorm2d(channels)
|
self.bn1 = nn.InstanceNorm2d(channels, affine=True)
|
||||||
self.conv2 = nn.Conv2d(channels, channels, 3, padding=1)
|
self.conv2 = nn.Conv2d(channels, channels, 3, padding=dilation, dilation=dilation)
|
||||||
self.bn2 = nn.BatchNorm2d(channels)
|
self.bn2 = nn.InstanceNorm2d(channels, affine=True)
|
||||||
self.relu = nn.LeakyReLU(0.1, inplace=True)
|
self.act = nn.GELU()
|
||||||
self.dropout = nn.Dropout2d(dropout) if dropout > 0 else nn.Identity()
|
self.dropout = nn.Dropout2d(dropout) if dropout > 0 else nn.Identity()
|
||||||
|
|
||||||
def forward(self, x):
|
def forward(self, x):
|
||||||
residual = x
|
residual = x
|
||||||
out = self.relu(self.bn1(self.conv1(x)))
|
out = self.act(self.bn1(self.conv1(x)))
|
||||||
out = self.dropout(out)
|
out = self.dropout(out)
|
||||||
out = self.bn2(self.conv2(out))
|
out = self.bn2(self.conv2(out))
|
||||||
out = out + residual
|
out = out + residual
|
||||||
return self.relu(out)
|
return self.act(out)
|
||||||
|
|
||||||
|
|
||||||
class DownBlock(nn.Module):
|
class DownBlock(nn.Module):
|
||||||
@@ -161,9 +164,9 @@ class MyModel(nn.Module):
|
|||||||
# Bottleneck with multiple residual blocks
|
# Bottleneck with multiple residual blocks
|
||||||
self.bottleneck = nn.Sequential(
|
self.bottleneck = nn.Sequential(
|
||||||
ConvBlock(base_channels * 16, base_channels * 16, dropout=dropout),
|
ConvBlock(base_channels * 16, base_channels * 16, dropout=dropout),
|
||||||
ResidualConvBlock(base_channels * 16, dropout=dropout),
|
ResidualConvBlock(base_channels * 16, dropout=dropout, dilation=2),
|
||||||
ResidualConvBlock(base_channels * 16, dropout=dropout),
|
ResidualConvBlock(base_channels * 16, dropout=dropout, dilation=4),
|
||||||
ResidualConvBlock(base_channels * 16, dropout=dropout),
|
ResidualConvBlock(base_channels * 16, dropout=dropout, dilation=8),
|
||||||
CBAM(base_channels * 16)
|
CBAM(base_channels * 16)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -183,7 +186,7 @@ class MyModel(nn.Module):
|
|||||||
# Output layer with smooth transition
|
# Output layer with smooth transition
|
||||||
self.output = nn.Sequential(
|
self.output = nn.Sequential(
|
||||||
nn.Conv2d(base_channels, base_channels // 2, kernel_size=3, padding=1),
|
nn.Conv2d(base_channels, base_channels // 2, kernel_size=3, padding=1),
|
||||||
nn.LeakyReLU(0.1, inplace=True),
|
nn.GELU(),
|
||||||
nn.Conv2d(base_channels // 2, 3, kernel_size=1),
|
nn.Conv2d(base_channels // 2, 3, kernel_size=1),
|
||||||
nn.Sigmoid() # Ensure output is in [0, 1] range
|
nn.Sigmoid() # Ensure output is in [0, 1] range
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -26,11 +26,21 @@ def create_arrays_from_image(image_array: np.ndarray, offset: tuple, spacing: tu
|
|||||||
|
|
||||||
return image_array, known_array
|
return image_array, known_array
|
||||||
|
|
||||||
def resize(img: Image):
|
def resize(img: Image, augment: bool = False):
|
||||||
resize_transforms = transforms.Compose([
|
transforms_list = [
|
||||||
transforms.Resize((IMAGE_DIMENSION, IMAGE_DIMENSION)),
|
transforms.Resize((IMAGE_DIMENSION, IMAGE_DIMENSION)),
|
||||||
transforms.CenterCrop((IMAGE_DIMENSION, IMAGE_DIMENSION))
|
transforms.CenterCrop((IMAGE_DIMENSION, IMAGE_DIMENSION))
|
||||||
])
|
]
|
||||||
|
|
||||||
|
if augment:
|
||||||
|
transforms_list = [
|
||||||
|
transforms.RandomHorizontalFlip(),
|
||||||
|
transforms.RandomVerticalFlip(),
|
||||||
|
transforms.ColorJitter(brightness=0.1, contrast=0.1, saturation=0.1, hue=0.05),
|
||||||
|
transforms.RandomRotation(10),
|
||||||
|
] + transforms_list
|
||||||
|
|
||||||
|
resize_transforms = transforms.Compose(transforms_list)
|
||||||
return resize_transforms(img)
|
return resize_transforms(img)
|
||||||
def preprocess(input_array: np.ndarray):
|
def preprocess(input_array: np.ndarray):
|
||||||
input_array = np.asarray(input_array, dtype=np.float32) / 255.0
|
input_array = np.asarray(input_array, dtype=np.float32) / 255.0
|
||||||
@@ -41,8 +51,9 @@ class ImageDataset(torch.utils.data.Dataset):
|
|||||||
Dataset class for loading images from a folder
|
Dataset class for loading images from a folder
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, datafolder: str):
|
def __init__(self, datafolder: str, augment: bool = False):
|
||||||
self.imagefiles = sorted(glob.glob(os.path.join(datafolder,"**","*.jpg"),recursive=True))
|
self.imagefiles = sorted(glob.glob(os.path.join(datafolder,"**","*.jpg"),recursive=True))
|
||||||
|
self.augment = augment
|
||||||
|
|
||||||
def __len__(self):
|
def __len__(self):
|
||||||
return len(self.imagefiles)
|
return len(self.imagefiles)
|
||||||
@@ -51,7 +62,7 @@ class ImageDataset(torch.utils.data.Dataset):
|
|||||||
index = int(idx)
|
index = int(idx)
|
||||||
|
|
||||||
image = Image.open(self.imagefiles[index])
|
image = Image.open(self.imagefiles[index])
|
||||||
image = np.asarray(resize(image))
|
image = np.asarray(resize(image, self.augment))
|
||||||
image = preprocess(image)
|
image = preprocess(image)
|
||||||
spacing_x = random.randint(2,6)
|
spacing_x = random.randint(2,6)
|
||||||
spacing_y = random.randint(2,6)
|
spacing_y = random.randint(2,6)
|
||||||
|
|||||||
@@ -84,16 +84,21 @@ def train(seed, testset_ratio, validset_ratio, data_path, results_path, early_st
|
|||||||
plotpath = os.path.join(results_path, "plots")
|
plotpath = os.path.join(results_path, "plots")
|
||||||
os.makedirs(plotpath, exist_ok=True)
|
os.makedirs(plotpath, exist_ok=True)
|
||||||
|
|
||||||
image_dataset = datasets.ImageDataset(datafolder=data_path)
|
image_dataset = datasets.ImageDataset(datafolder=data_path, augment=False)
|
||||||
|
|
||||||
n_total = len(image_dataset)
|
n_total = len(image_dataset)
|
||||||
n_test = int(n_total * testset_ratio)
|
n_test = int(n_total * testset_ratio)
|
||||||
n_valid = int(n_total * validset_ratio)
|
n_valid = int(n_total * validset_ratio)
|
||||||
n_train = n_total - n_test - n_valid
|
n_train = n_total - n_test - n_valid
|
||||||
indices = np.random.permutation(n_total)
|
indices = np.random.permutation(n_total)
|
||||||
dataset_train = Subset(image_dataset, indices=indices[0:n_train])
|
|
||||||
dataset_valid = Subset(image_dataset, indices=indices[n_train:n_train + n_valid])
|
# Create datasets with and without augmentation
|
||||||
dataset_test = Subset(image_dataset, indices=indices[n_train + n_valid:n_total])
|
train_dataset_source = datasets.ImageDataset(datafolder=data_path, augment=True)
|
||||||
|
val_test_dataset_source = datasets.ImageDataset(datafolder=data_path, augment=False)
|
||||||
|
|
||||||
|
dataset_train = Subset(train_dataset_source, indices=indices[0:n_train])
|
||||||
|
dataset_valid = Subset(val_test_dataset_source, indices=indices[n_train:n_train + n_valid])
|
||||||
|
dataset_test = Subset(val_test_dataset_source, indices=indices[n_train + n_valid:n_total])
|
||||||
|
|
||||||
assert len(image_dataset) == len(dataset_train) + len(dataset_test) + len(dataset_valid)
|
assert len(image_dataset) == len(dataset_train) + len(dataset_test) + len(dataset_valid)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user