|
import cv2 |
|
import numpy as np |
|
import matplotlib.pyplot as plt |
|
from ultralytics import YOLO |
|
import gradio as gr |
|
from matplotlib.patches import Rectangle |
|
from matplotlib.legend import Legend |
|
|
|
|
|
model = YOLO("model.pt") |
|
|
|
def process_image(image): |
|
|
|
img_rgb = np.array(image) |
|
img_bgr = cv2.cvtColor(img_rgb, cv2.COLOR_RGB2BGR) |
|
|
|
|
|
results = model.predict(source=img_bgr, save=False) |
|
|
|
|
|
mask_info_list = [] |
|
|
|
|
|
mask_image = np.zeros_like(img_bgr, dtype=np.uint8) |
|
|
|
|
|
for result in results: |
|
|
|
if result.masks is not None and len(result.masks.data) > 0: |
|
|
|
masks = result.masks.data.cpu().numpy() |
|
confidences = result.boxes.conf.cpu().numpy() |
|
classes = result.boxes.cls.cpu().numpy().astype(int) |
|
names = model.names |
|
|
|
|
|
confidences_norm = (confidences - confidences.min()) / (confidences.max() - confidences.min() + 1e-6) |
|
|
|
|
|
resized_masks = [] |
|
for mask in masks: |
|
mask_resized = cv2.resize(mask, (img_bgr.shape[1], img_bgr.shape[0]), interpolation=cv2.INTER_LINEAR) |
|
resized_masks.append(mask_resized) |
|
resized_masks = np.array(resized_masks) |
|
|
|
|
|
smoothed_masks = [] |
|
for mask in resized_masks: |
|
|
|
mask_uint8 = (mask * 255).astype(np.uint8) |
|
|
|
blurred_mask = cv2.GaussianBlur(mask_uint8, (7, 7), 0) |
|
|
|
mask_smoothed = blurred_mask.astype(np.float32) / 255.0 |
|
smoothed_masks.append(mask_smoothed) |
|
smoothed_masks = np.array(smoothed_masks) |
|
|
|
|
|
sorted_indices = np.argsort(-confidences) |
|
sorted_masks = smoothed_masks[sorted_indices] |
|
sorted_confidences = confidences[sorted_indices] |
|
sorted_confidences_norm = confidences_norm[sorted_indices] |
|
sorted_classes = classes[sorted_indices] |
|
|
|
|
|
colormap = plt.cm.get_cmap('viridis') |
|
|
|
|
|
mask_indices = np.full((img_bgr.shape[0], img_bgr.shape[1]), -1, dtype=int) |
|
|
|
|
|
for idx_in_order, (idx, mask, conf_norm, conf, cls) in enumerate( |
|
zip(sorted_indices, sorted_masks, sorted_confidences_norm, sorted_confidences, sorted_classes)): |
|
mask_bool = mask > 0.5 |
|
|
|
update_mask = np.logical_and(mask_bool, mask_indices == -1) |
|
if not np.any(update_mask): |
|
continue |
|
mask_indices[update_mask] = idx |
|
|
|
|
|
color_rgb = colormap(conf_norm)[:3] |
|
color_rgb_255 = [int(c * 255) for c in color_rgb] |
|
color_bgr_255 = color_rgb_255[::-1] |
|
|
|
|
|
mask_info = { |
|
'mask_index': idx, |
|
'class': names[cls], |
|
'confidence': conf, |
|
'color_rgb': color_rgb_255, |
|
'color_bgr': color_bgr_255 |
|
} |
|
mask_info_list.append(mask_info) |
|
|
|
|
|
for i in range(3): |
|
mask_image[:, :, i][update_mask] = color_bgr_255[i] |
|
|
|
|
|
alpha = 0.2 |
|
img_with_masks = cv2.addWeighted(img_bgr.astype(np.float32), 1, mask_image.astype(np.float32), alpha, 0).astype(np.uint8) |
|
|
|
else: |
|
|
|
img_with_masks = img_bgr.copy() |
|
print("No se detectaron máscaras en esta imagen.") |
|
|
|
|
|
img_with_masks_rgb = cv2.cvtColor(img_with_masks, cv2.COLOR_BGR2RGB) |
|
|
|
|
|
fig, ax = plt.subplots(figsize=(8, 8)) |
|
ax.imshow(img_with_masks_rgb) |
|
ax.axis('off') |
|
|
|
|
|
if mask_info_list: |
|
handles = [] |
|
labels = [] |
|
for mask_info in mask_info_list: |
|
color_rgb_normalized = np.array(mask_info['color_rgb']) / 255 |
|
patch = Rectangle((0, 0), 1, 1, facecolor=color_rgb_normalized) |
|
label = f"Stenosis probability: {mask_info['confidence']:.2f}" |
|
handles.append(patch) |
|
labels.append(label) |
|
|
|
|
|
legend = Legend(ax, handles, labels, loc='upper right') |
|
ax.add_artist(legend) |
|
|
|
plt.tight_layout() |
|
|
|
|
|
fig.canvas.draw() |
|
img_figure = np.frombuffer(fig.canvas.tostring_rgb(), dtype=np.uint8) |
|
img_figure = img_figure.reshape(fig.canvas.get_width_height()[::-1] + (3,)) |
|
|
|
plt.close(fig) |
|
|
|
return img_figure |
|
|
|
|
|
iface = gr.Interface( |
|
fn=process_image, |
|
inputs=gr.Image(type="pil"), |
|
outputs=gr.Image(type="numpy"), |
|
title="Detección de Estenosis", |
|
description="Sube una imagen para detectar estenosis." |
|
) |
|
|
|
if __name__ == "__main__": |
|
iface.launch() |
|
|