|
import numpy as np |
|
from PIL import Image |
|
from skimage.transform import resize |
|
import tensorflow as tf |
|
from tensorflow.keras.models import load_model |
|
|
|
from huggingface_hub import snapshot_download |
|
|
|
import matplotlib.pyplot as plt |
|
from matplotlib.colors import ListedColormap |
|
|
|
import gradio as gr |
|
import os |
|
import io |
|
|
|
REPO_ID = "amosfang/segmentation_u_net" |
|
TRAIN_FOLDER = 'train_images' |
|
TEST_FOLDER = 'example_images' |
|
NUM_CLASSES = 7 |
|
|
|
def pil_image_as_numpy_array(pilimg): |
|
|
|
|
|
img_array = tf.keras.utils.img_to_array(pilimg) |
|
return img_array |
|
|
|
def resize_image(image, input_shape=(224, 224, 3)): |
|
|
|
|
|
image_array = pil_image_as_numpy_array(image) |
|
image = image_array.astype(np.float32) / 255. |
|
|
|
|
|
image_resized = resize(image, input_shape, anti_aliasing=True) |
|
|
|
return image_resized |
|
|
|
def load_model_file(filename): |
|
|
|
model_dir = snapshot_download(REPO_ID) |
|
saved_model_filepath = os.path.join(model_dir, filename) |
|
unet_model = load_model(saved_model_filepath) |
|
|
|
return unet_model |
|
|
|
def get_sample_images(image_folder, format=[('.jpg', '.jpeg'), ('.png')]): |
|
|
|
|
|
image_files = [] |
|
mask_files = [] |
|
|
|
|
|
img_file_list = os.listdir(image_folder) |
|
img_file_list.sort() |
|
|
|
|
|
image_files = [image_folder +'/' + file for file in img_file_list if file.lower().endswith(format[0])] |
|
mask_files = [image_folder +'/' + file for file in img_file_list if file.lower().endswith(format[1])] |
|
|
|
if mask_files == []: |
|
print(image_files) |
|
image_files = [[file] for file in image_files] |
|
return image_files |
|
|
|
return [list(pair) for pair in zip(image_files, mask_files)] |
|
|
|
def ensemble_predict(X_array): |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
X_array = np.expand_dims(X_array, axis=0) |
|
|
|
unet_model = load_model_file('base_u_net.0098-acc-0.75-val_acc-0.74-loss-0.79.h5') |
|
vgg16_model = load_model_file('vgg16_u_net.0092-acc-0.74-val_acc-0.74-loss-0.82.h5') |
|
resnet50_model = load_model_file('resnet50_u_net.0095-acc-0.79-val_acc-0.76-loss-0.72.h5') |
|
|
|
pred_y_unet = unet_model.predict(X_array) |
|
pred_y_vgg16 = vgg16_model.predict(X_array) |
|
pred_y_resnet50 = resnet50_model.predict(X_array) |
|
|
|
return (pred_y_unet + pred_y_vgg16 + pred_y_resnet50) / 3 |
|
|
|
def get_predictions(y_prediction_encoded): |
|
|
|
|
|
predicted_label_indices = np.argmax(y_prediction_encoded, axis=-1) + 1 |
|
|
|
return predicted_label_indices |
|
|
|
def predict_on_train(image, mask): |
|
|
|
|
|
sample_image_resized = resize_image(image) |
|
mask_resized = resize_image(mask) |
|
|
|
|
|
fig, ax = plt.subplots() |
|
|
|
|
|
ax.imshow(sample_image_resized) |
|
|
|
|
|
cax = ax.imshow(mask_resized, alpha=0.5) |
|
|
|
|
|
image_buffer = io.BytesIO() |
|
plt.savefig(image_buffer, format='png') |
|
image_buffer.seek(0) |
|
mask_pil = Image.open(image_buffer) |
|
|
|
|
|
plt.close(fig) |
|
|
|
|
|
|
|
|
|
y_pred = ensemble_predict(sample_image_resized) |
|
y_pred = get_predictions(y_pred).squeeze() |
|
|
|
|
|
colors = ['cyan', 'yellow', 'magenta', 'green', 'blue', 'black', 'white'] |
|
|
|
cmap = ListedColormap(colors) |
|
|
|
|
|
fig, ax = plt.subplots() |
|
|
|
|
|
ax.imshow(sample_image_resized) |
|
|
|
|
|
cax = ax.imshow(y_pred, cmap=cmap, vmin=1, vmax=NUM_CLASSES, alpha=0.5) |
|
|
|
|
|
cbar = plt.colorbar(cax, ticks=np.arange(1, NUM_CLASSES + 1)) |
|
cbar.set_ticklabels(['Urban', 'Agriculture', 'Range Land', 'Forest', 'Water', 'Barren', 'Unknown']) |
|
|
|
|
|
image_buffer = io.BytesIO() |
|
plt.savefig(image_buffer, format='png') |
|
image_buffer.seek(0) |
|
image_pil = Image.open(image_buffer) |
|
|
|
|
|
plt.close(fig) |
|
|
|
return mask_pil, image_pil |
|
|
|
def predict_on_test(image): |
|
|
|
|
|
sample_image_resized = resize_image(image) |
|
y_pred = ensemble_predict(sample_image_resized) |
|
y_pred = get_predictions(y_pred).squeeze() |
|
|
|
|
|
colors = ['cyan', 'yellow', 'magenta', 'green', 'blue', 'black', 'white'] |
|
|
|
cmap = ListedColormap(colors) |
|
|
|
|
|
fig, ax = plt.subplots() |
|
|
|
|
|
ax.imshow(sample_image_resized) |
|
|
|
|
|
cax = ax.imshow(y_pred, cmap=cmap, vmin=1, vmax=7, alpha=0.5) |
|
|
|
|
|
cbar = plt.colorbar(cax, ticks=np.arange(1, 8)) |
|
cbar.set_ticklabels(['Urban', 'Agriculture', 'Range Land', 'Forest', 'Water', 'Barren', 'Unknown']) |
|
|
|
|
|
image_buffer = io.BytesIO() |
|
plt.savefig(image_buffer, format='png') |
|
image_buffer.seek(0) |
|
image_pil = Image.open(image_buffer) |
|
|
|
|
|
plt.close(fig) |
|
|
|
return image_pil |
|
|
|
train_images = get_sample_images(TRAIN_FOLDER) |
|
test_images = get_sample_images(TEST_FOLDER) |
|
|
|
description= ''' |
|
Computer vision deep learning, powered by GPU advancements, plays a potentially |
|
key role in urban planning and climate change research. The U-Net model architecture, that is |
|
commonly used in semantic segmentation, can be applied to automated land cover classification and |
|
seagrass habitat monitoring. |
|
|
|
Our project, using the DeepGlobe Land Cover Classification Challenge 2018 dataset, trained four models |
|
(basic U-Net, VGG16 U-Net, Resnet50 U-Net, and Efficient Net U-Net) and achieved a validation accuracy of |
|
approximately 75\% and a dice score of about 0.6 through an ensemble approach on 803 images with |
|
segmentation masks (80/20 split). |
|
''' |
|
|
|
|
|
tab1 = gr.Interface( |
|
fn=predict_on_train, |
|
inputs=[gr.Image(), gr.Image()], |
|
outputs=[gr.Image(label='Ground Truth'), gr.Image(label='Predicted')], |
|
title='Images with Ground Truth', |
|
description=description, |
|
examples=train_images |
|
) |
|
|
|
|
|
tab2 = gr.Interface( |
|
fn=predict_on_test, |
|
inputs=gr.Image(), |
|
outputs=gr.Image(label='Predicted'), |
|
title='Images without Ground Truth', |
|
description=description, |
|
examples=test_images |
|
) |
|
|
|
|
|
iface = gr.TabbedInterface([tab1, tab2], |
|
title='Land Cover Segmentation', |
|
tab_names = ['Train','Test']) |
|
|
|
|
|
iface.launch(share=True) |