import pandas as pd import numpy as np import streamlit as st import numpy as np import matplotlib.pyplot as plt from matplotlib.backends.backend_agg import FigureCanvasAgg from PIL import Image from streamlit_image_select import image_select from tqdm import tqdm import os import shutil from PIL import Image import torch import matplotlib.pyplot as plt from datasets import load_dataset from transformers import AutoProcessor, AutoModelForMaskGeneration def show_mask(image, mask, ax=None): fig, axes = plt.subplots() axes.imshow(np.array(image)) color = np.array([30/255, 144/255, 255/255, 0.6]) h, w = mask.shape[-2:] mask_image = mask.reshape(h, w, 1) * color.reshape(1, 1, -1) axes.imshow(mask_image) canvas = FigureCanvasAgg(fig) canvas.draw() pil_image = Image.frombytes('RGB', canvas.get_width_height(), canvas.tostring_rgb()) plt.close(fig) return pil_image def get_bounding_box(ground_truth_map): y_indices, x_indices = np.where(ground_truth_map > 0) x_min, x_max = np.min(x_indices), np.max(x_indices) y_min, y_max = np.min(y_indices), np.max(y_indices) H, W = ground_truth_map.shape x_min = max(0, x_min - np.random.randint(0, 20)) x_max = min(W, x_max + np.random.randint(0, 20)) y_min = max(0, y_min - np.random.randint(0, 20)) y_max = min(H, y_max + np.random.randint(0, 20)) bbox = [x_min, y_min, x_max, y_max] return bbox def get_output(image,prompt): inputs = processor(image,input_boxes=[[prompt]],return_tensors='pt').to(device) model.eval() with torch.no_grad(): outputs = model(**inputs,multimask_output=False) output_proba = torch.sigmoid(outputs.pred_masks.squeeze(1)) output_proba = output_proba.cpu().numpy().squeeze() output = (output_proba > 0.5).astype(np.uint8) return output def generate_image(np_array): return Image.fromarray((np_array*255).astype('uint8'),mode='L') def iou_calculation(result1, result2): intersection = np.logical_and(result1, result2) union = np.logical_or(result1, result2) iou_score = np.sum(intersection) / np.sum(union) iou_score = "{:.4f}".format(iou_score) return float(iou_score) def calculate_pixel_accuracy(image1, image2): if image1.size != image2.size or image1.mode != image2.mode: image1 = image1.resize(image2.size, Image.BILINEAR) if image1.mode != image2.mode: image1 = image1.convert(image2.mode) width, height = image1.size total_pixels = width * height image1 = image1.convert("RGB") image2 = image2.convert("RGB") pixels1 = image1.load() pixels2 = image2.load() num_correct_pixels = 0 for y in range(height): for x in range(width): if pixels1[x, y] == pixels2[x, y]: num_correct_pixels += 1 accuracy = num_correct_pixels / total_pixels return accuracy def calculate_f1_score(image1, image2): if image1.size != image2.size or image1.mode != image2.mode: image1 = image1.resize(image2.size, Image.BILINEAR) if image1.mode != image2.mode: image1 = image1.convert(image2.mode) width, height = image1.size image1 = image1.convert("L") image2 = image2.convert("L") np_image1 = np.array(image1) np_image2 = np.array(image2) np_image1_flat = np_image1.flatten() np_image2_flat = np_image2.flatten() true_positives = np.sum(np.logical_and(np_image1_flat == 255, np_image2_flat == 255)) false_positives = np.sum(np.logical_and(np_image1_flat != 255, np_image2_flat == 255)) false_negatives = np.sum(np.logical_and(np_image1_flat == 255, np_image2_flat != 255)) precision = true_positives / (true_positives + false_positives + 1e-7) recall = true_positives / (true_positives + false_negatives + 1e-7) f1_score = 2 * (precision * recall) / (precision + recall + 1e-7) return f1_score def calculate_dice_coefficient(image1, image2): if image1.size != image2.size or image1.mode != image2.mode: image1 = image1.resize(image2.size, Image.BILINEAR) if image1.mode != image2.mode: image1 = image1.convert(image2.mode) width, height = image1.size image1 = image1.convert("L") image2 = image2.convert("L") np_image1 = np.array(image1) np_image2 = np.array(image2) np_image1_flat = np_image1.flatten() np_image2_flat = np_image2.flatten() true_positives = np.sum(np.logical_and(np_image1_flat == 255, np_image2_flat == 255)) false_positives = np.sum(np.logical_and(np_image1_flat != 255, np_image2_flat == 255)) false_negatives = np.sum(np.logical_and(np_image1_flat == 255, np_image2_flat != 255)) dice_coefficient = (2 * true_positives) / (2 * true_positives + false_positives + false_negatives) return dice_coefficient device = "cuda" if torch.cuda.is_available() else "cpu" st.set_page_config(layout='wide') ds = load_dataset('ahishamm/combined_masks',split='train') s1 = ds[3]['image'] s2 = ds[4]['image'] s3 = ds[5]['image'] s4 = ds[6]['image'] s1_label = ds[3]['label'] s2_label = ds[4]['label'] s3_label = ds[5]['label'] s4_label = ds[6]['label'] image_arr = [s1,s2,s3,s4] label_arr = [s1_label,s2_label,s3_label,s4_label] img = image_select( label="Select a Skin Lesion Image", images=[ s1,s2,s3,s4 ], captions=["sample 1","sample 2","sample 3","sample 4"], return_value='index' ) processor = AutoProcessor.from_pretrained('ahishamm/skinsam') model = AutoModelForMaskGeneration.from_pretrained('ahishamm/skinsam_focalloss_base_combined') model.to(device) p = get_bounding_box(np.array(label_arr[img])) predicted_mask_array = get_output(image_arr[img],p) predicted_mask = generate_image(predicted_mask_array) result_image = show_mask(image_arr[img],predicted_mask_array) with st.container(): tab1, tab2 = st.tabs(['Visualizations','Metrics']) with tab1: col1, col2 = st.columns(2) with col1: st.image(image_arr[img],caption='Original Skin Lesion Image',use_column_width=True) with col2: st.image(result_image,caption='Mask Overlay',use_column_width=True) with tab2: st.write(f'The IOU Score: {iou_calculation(label_arr[img],predicted_mask)}') st.write(f'The Pixel Accuracy: {calculate_pixel_accuracy(label_arr[img],predicted_mask)}') st.write(f'The Dice Coefficient Score: {calculate_dice_coefficient(label_arr[img],predicted_mask)}')