Spaces:
Sleeping
Sleeping
Upload 5 files
Browse files- Dockerfile +13 -0
- app.py +66 -0
- best_model.pth +3 -0
- requirements.txt +10 -0
- unet.py +102 -0
Dockerfile
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# lightweight python
|
2 |
+
FROM python:3.11
|
3 |
+
|
4 |
+
|
5 |
+
# Copy local code to the container image.
|
6 |
+
WORKDIR /app
|
7 |
+
COPY . /app
|
8 |
+
|
9 |
+
# Install dependencies
|
10 |
+
RUN pip install -r requirements.txt
|
11 |
+
EXPOSE 8051
|
12 |
+
# Run the streamlit on container startup
|
13 |
+
CMD ["streamlit", "run", "app.py"]
|
app.py
CHANGED
@@ -0,0 +1,66 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from unet import UNet
|
2 |
+
import streamlit as st
|
3 |
+
import torch
|
4 |
+
from torchvision import transforms
|
5 |
+
import albumentations as A
|
6 |
+
from albumentations.pytorch import ToTensorV2
|
7 |
+
from PIL import Image
|
8 |
+
import numpy as np
|
9 |
+
|
10 |
+
device = 'cuda' if torch.cuda.is_available() else 'cpu'
|
11 |
+
model = UNet(3, 1, [64, 128, 256, 512]).to(device)
|
12 |
+
model.load_state_dict(torch.load("best_model.pth", map_location=torch.device(device)))
|
13 |
+
# Set up transformations for the input image
|
14 |
+
|
15 |
+
|
16 |
+
transform = A.Compose([
|
17 |
+
A.Resize(224, 224, p=1.0),
|
18 |
+
ToTensorV2(),
|
19 |
+
])
|
20 |
+
# Streamlit app
|
21 |
+
def main():
|
22 |
+
st.title("MRI segmenation App")
|
23 |
+
|
24 |
+
# Upload image through Streamlit
|
25 |
+
uploaded_image = st.file_uploader("Choose an image...", type=["jpg", "jpeg", "png"])
|
26 |
+
|
27 |
+
if uploaded_image is not None:
|
28 |
+
# Display the uploaded and processed images side by side
|
29 |
+
col1, col2 = st.columns(2) # Using beta_columns for side-by-side layout
|
30 |
+
|
31 |
+
# Display the uploaded image in the first column
|
32 |
+
col1.header("Original Image")
|
33 |
+
col1.image(uploaded_image, caption="Uploaded Image", use_column_width=True)
|
34 |
+
|
35 |
+
# Process the image (replace this with your processing logic)
|
36 |
+
processed_image = generate_image(uploaded_image)
|
37 |
+
|
38 |
+
# Display the processed image in the second column
|
39 |
+
col2.header("Processed Image")
|
40 |
+
col2.image(processed_image, caption="Processed Image", use_column_width=True)
|
41 |
+
|
42 |
+
# Function to generate an image using the PyTorch model
|
43 |
+
def generate_image(uploaded_image):
|
44 |
+
# Load the uploaded image
|
45 |
+
input_image = Image.open(uploaded_image)
|
46 |
+
|
47 |
+
image = np.array(input_image).astype(np.float32) / 255.
|
48 |
+
# Apply transformations
|
49 |
+
input_tensor = transform(image=image)["image"].unsqueeze(0)
|
50 |
+
|
51 |
+
# Generate an image using the PyTorch model
|
52 |
+
with torch.no_grad():
|
53 |
+
input_tensor = input_tensor.type(torch.FloatTensor).to(device)
|
54 |
+
pred = model(input_tensor)
|
55 |
+
pred = torch.sigmoid(pred)
|
56 |
+
mask = (pred > 0.6).float()
|
57 |
+
mask = mask[0].permute(1, 2, 0)
|
58 |
+
image = input_tensor[0].permute(1, 2, 0)
|
59 |
+
|
60 |
+
mask = image + mask*0.3
|
61 |
+
mask = mask.permute(2, 0, 1)
|
62 |
+
mask = transforms.ToPILImage()(mask)
|
63 |
+
return mask
|
64 |
+
|
65 |
+
if __name__ == "__main__":
|
66 |
+
main()
|
best_model.pth
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:80bca9fca6dd62bb74e5072bcac8a4e2d232d43b6f45e0202bf6d5a353cd2b70
|
3 |
+
size 124203732
|
requirements.txt
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Core Libraries
|
2 |
+
numpy>=1.21.0
|
3 |
+
|
4 |
+
pillow>=9.3.0
|
5 |
+
|
6 |
+
# Web Application Framework
|
7 |
+
streamlit>=1.28.0
|
8 |
+
torch>=2.1.2
|
9 |
+
torchvision>=0.16.2
|
10 |
+
albumentations>=1.3.1
|
unet.py
ADDED
@@ -0,0 +1,102 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import torch
|
2 |
+
import torch.nn as nn
|
3 |
+
|
4 |
+
class DownSampling(nn.Module):
|
5 |
+
|
6 |
+
def __init__(self, in_channels, out_channels, max_pool):
|
7 |
+
"""
|
8 |
+
DownSampling block in the U-Net architecture.
|
9 |
+
|
10 |
+
Args:
|
11 |
+
in_channels (int): Number of input channels.
|
12 |
+
out_channels (int): Number of output channels.
|
13 |
+
max_pool (bool): Whether to use max pooling.
|
14 |
+
"""
|
15 |
+
super(DownSampling, self).__init__()
|
16 |
+
self.max_pool = max_pool
|
17 |
+
self.conv1 = nn.Conv2d(in_channels=in_channels, out_channels=out_channels, kernel_size=3, stride=1, padding=1)
|
18 |
+
self.conv2 = nn.Conv2d(in_channels=out_channels, out_channels=out_channels, kernel_size=3, stride=1, padding=1)
|
19 |
+
self.batchnorm2d = nn.BatchNorm2d(out_channels)
|
20 |
+
self.relu = nn.ReLU()
|
21 |
+
self.maxpool2d = nn.MaxPool2d(kernel_size=2, stride=2)
|
22 |
+
|
23 |
+
def forward(self, x):
|
24 |
+
x = self.conv1(x)
|
25 |
+
x = self.conv2(x)
|
26 |
+
|
27 |
+
x = self.relu(self.batchnorm2d(x))
|
28 |
+
skip_connection = x
|
29 |
+
|
30 |
+
if self.max_pool:
|
31 |
+
next_layer = self.maxpool2d(x)
|
32 |
+
else:
|
33 |
+
return x
|
34 |
+
return next_layer, skip_connection
|
35 |
+
|
36 |
+
class UpSampling(nn.Module):
|
37 |
+
def __init__(self, in_channels, out_channels):
|
38 |
+
"""
|
39 |
+
UpSampling block in the U-Net architecture.
|
40 |
+
|
41 |
+
Args:
|
42 |
+
in_channels (int): Number of input channels.
|
43 |
+
out_channels (int): Number of output channels.
|
44 |
+
"""
|
45 |
+
super(UpSampling, self).__init__()
|
46 |
+
self.up = nn.ConvTranspose2d(in_channels, out_channels=out_channels, kernel_size=2, stride=2)
|
47 |
+
self.conv1 = nn.Conv2d(in_channels=in_channels, out_channels=out_channels, kernel_size=3, stride=1, padding=1)
|
48 |
+
self.relu = nn.ReLU()
|
49 |
+
self.conv2 = nn.Conv2d(in_channels=out_channels, out_channels=out_channels, kernel_size=3, stride=1, padding=1)
|
50 |
+
self.batchnorm = nn.BatchNorm2d(out_channels)
|
51 |
+
|
52 |
+
def forward(self, x, prev_skip):
|
53 |
+
x = self.up(x)
|
54 |
+
x = torch.cat((x, prev_skip), dim=1)
|
55 |
+
x = self.conv1(x)
|
56 |
+
x = self.conv2(x)
|
57 |
+
next_layer = self.relu(self.batchnorm(x))
|
58 |
+
return next_layer
|
59 |
+
|
60 |
+
class UNet(nn.Module):
|
61 |
+
|
62 |
+
"""
|
63 |
+
U-Net architecture.
|
64 |
+
|
65 |
+
Args:
|
66 |
+
in_channels (int): Number of input channels.
|
67 |
+
out_channels (int): Number of output channels.
|
68 |
+
features (list): List of feature sizes for downsampling and upsampling.
|
69 |
+
"""
|
70 |
+
def __init__(self, in_channels, out_channels, features):
|
71 |
+
super(UNet, self).__init__()
|
72 |
+
self.ups = nn.ModuleList()
|
73 |
+
self.downs = nn.ModuleList()
|
74 |
+
|
75 |
+
for feature in features:
|
76 |
+
self.downs.append(DownSampling(in_channels, feature, True))
|
77 |
+
in_channels = feature
|
78 |
+
|
79 |
+
for feature in reversed(features):
|
80 |
+
self.ups.append(UpSampling(2 * feature, feature))
|
81 |
+
|
82 |
+
self.bottleneck = DownSampling(features[-1], 2 * features[-1], False)
|
83 |
+
self.final_conv = nn.Conv2d(features[0], out_channels, kernel_size=1)
|
84 |
+
|
85 |
+
def forward(self, x):
|
86 |
+
skip_connections = []
|
87 |
+
for down in self.downs:
|
88 |
+
x, skip_connection = down(x)
|
89 |
+
skip_connections.append(skip_connection)
|
90 |
+
skip_connections = skip_connections[::-1]
|
91 |
+
x = self.bottleneck(x)
|
92 |
+
for i, up in enumerate(self.ups):
|
93 |
+
x = up(x, skip_connections[i])
|
94 |
+
|
95 |
+
return self.final_conv(x)
|
96 |
+
|
97 |
+
if __name__ == "__main__":
|
98 |
+
#Example Usage
|
99 |
+
device = 'cuda' if torch.cuda.is_available() else 'cpu'
|
100 |
+
features = [64, 128, 256, 512]
|
101 |
+
model = UNet(1, 1, features=features).to(device)
|
102 |
+
print(model(torch.rand(1, 1, 512, 512)).shape)
|