BerhaneW's picture
Added ml project
c4a8c0e verified
Raw History Blame Contribute Delete
3.75 kB
import tensorflow as tf
class PixelShuffle(tf.keras.layers.Layer):
"""
Sub-pixel convolution layer (equivalent to PyTorch's nn.PixelShuffle).
Rearranges elements in a tensor of shape (N, H, W, C * r^2)
into (N, H*r, W*r, C) using tf.nn.depth_to_space.
"""
def __init__(self, scale_factor, **kwargs):
super().__init__(**kwargs)
self.scale_factor = scale_factor
def call(self, x):
return tf.nn.depth_to_space(x, self.scale_factor)
def get_config(self):
config = super().get_config()
config["scale_factor"] = self.scale_factor
return config
def build_srcnn(num_channels=3):
"""
Super-Resolution Convolutional Neural Network (SRCNN).
Input:
Bicubic-upsampled LR image with same spatial size as HR target.
Output:
Refined SR image of the same size.
"""
model = tf.keras.Sequential(
[
tf.keras.layers.Input(shape=(None, None, num_channels), name="input"),
tf.keras.layers.Conv2D(
64,
kernel_size=9,
padding="same",
activation="relu",
name="feature_extraction",
),
tf.keras.layers.Conv2D(
32,
kernel_size=1,
padding="same",
activation="relu",
name="non_linear_mapping",
),
tf.keras.layers.Conv2D(
num_channels,
kernel_size=5,
padding="same",
activation="sigmoid",
name="reconstruction",
),
],
name="SRCNN",
)
return model
def build_espcn(scale_factor=2, num_channels=3):
"""
Efficient Sub-Pixel Convolutional Neural Network (ESPCN).
Input:
Native low-resolution image.
Output:
High-resolution image after learned sub-pixel upscaling.
Args:
scale_factor: upscaling factor, e.g. 2, 3, 4, 8
num_channels: usually 3 for RGB
"""
inputs = tf.keras.Input(shape=(None, None, num_channels), name="lr_input")
x = tf.keras.layers.Conv2D(
64,
kernel_size=5,
padding="same",
activation="relu",
name="conv1",
)(inputs)
x = tf.keras.layers.Conv2D(
32,
kernel_size=3,
padding="same",
activation="relu",
name="conv2",
)(x)
x = tf.keras.layers.Conv2D(
num_channels * (scale_factor ** 2),
kernel_size=3,
padding="same",
name="conv3",
)(x)
x = PixelShuffle(scale_factor, name="pixel_shuffle")(x)
outputs = tf.keras.layers.Activation("sigmoid", name="output")(x)
model = tf.keras.Model(inputs, outputs, name=f"ESPCN_x{scale_factor}")
return model
def build_model(architecture="espcn", scale_factor=2, num_channels=3):
"""
Factory function that builds the requested model.
Args:
architecture: 'srcnn' or 'espcn'
scale_factor: upscale factor for ESPCN
num_channels: number of image channels
"""
architecture = architecture.lower()
if architecture == "srcnn":
return build_srcnn(num_channels=num_channels)
elif architecture == "espcn":
return build_espcn(scale_factor=scale_factor, num_channels=num_channels)
else:
raise ValueError(
f"Unknown architecture '{architecture}'. Choose 'srcnn' or 'espcn'."
)
if __name__ == "__main__":
print("=== SRCNN ===")
srcnn = build_model("srcnn")
srcnn.summary()
for scale in [2, 3, 4, 8]:
print(f"\n=== ESPCN (x{scale}) ===")
espcn = build_model("espcn", scale_factor=scale)
espcn.summary()