Update app.py
Browse files
app.py
CHANGED
|
@@ -3,33 +3,88 @@ import numpy as np
|
|
| 3 |
import tensorflow as tf
|
| 4 |
from PIL import Image
|
| 5 |
import cv2
|
|
|
|
| 6 |
|
| 7 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8 |
MODEL_PATH = "segmentation_model.h5"
|
| 9 |
model = tf.keras.models.load_model(MODEL_PATH)
|
| 10 |
|
| 11 |
def predict_image(input_image):
|
| 12 |
-
# Converte a imagem de PIL para NumPy
|
| 13 |
-
|
|
|
|
| 14 |
|
| 15 |
-
# Redimensiona
|
| 16 |
-
img_resized = tf.image.resize(
|
| 17 |
img_input = np.expand_dims(img_resized, axis=0)
|
| 18 |
|
| 19 |
-
# Faz a previsão
|
| 20 |
-
prediction = model.predict(img_input)
|
|
|
|
|
|
|
| 21 |
mask_predicted = np.argmax(prediction[0], axis=-1)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 22 |
|
| 23 |
-
|
| 24 |
-
|
| 25 |
|
| 26 |
-
return mask_image
|
| 27 |
|
| 28 |
-
# Define a interface Gradio
|
| 29 |
gr.Interface(
|
| 30 |
fn=predict_image,
|
| 31 |
inputs=gr.Image(type="pil"),
|
| 32 |
outputs="image",
|
| 33 |
-
title="Ferramenta de Segmentação de Objetos",
|
| 34 |
-
description="Carregue uma imagem e o modelo irá
|
| 35 |
).launch()
|
|
|
|
| 3 |
import tensorflow as tf
|
| 4 |
from PIL import Image
|
| 5 |
import cv2
|
| 6 |
+
from scipy.ndimage import binary_fill_holes
|
| 7 |
|
| 8 |
+
CLASS_COLORS = {
|
| 9 |
+
1: (0, 255, 0), # diecast (verde)
|
| 10 |
+
2: (0, 0, 255), # large_packaging (azul)
|
| 11 |
+
3: (255, 0, 0), # packaging (vermelho)
|
| 12 |
+
}
|
| 13 |
+
CLASS_NAMES = {
|
| 14 |
+
1: "diecast",
|
| 15 |
+
2: "large_packaging",
|
| 16 |
+
3: "packaging",
|
| 17 |
+
}
|
| 18 |
+
|
| 19 |
+
# Caminho para o modelo
|
| 20 |
MODEL_PATH = "segmentation_model.h5"
|
| 21 |
model = tf.keras.models.load_model(MODEL_PATH)
|
| 22 |
|
| 23 |
def predict_image(input_image):
|
| 24 |
+
# Converte a imagem de PIL para NumPy (formato BGR para OpenCV)
|
| 25 |
+
original_img_np = np.array(input_image.convert('RGB'))
|
| 26 |
+
original_img_cv2 = cv2.cvtColor(original_img_np, cv2.COLOR_RGB2BGR)
|
| 27 |
|
| 28 |
+
# Redimensiona para o tamanho do modelo (256, 256)
|
| 29 |
+
img_resized = tf.image.resize(original_img_np, (256, 256))
|
| 30 |
img_input = np.expand_dims(img_resized, axis=0)
|
| 31 |
|
| 32 |
+
# Faz a previsão do modelo
|
| 33 |
+
prediction = model.predict(img_input, verbose=0)
|
| 34 |
+
|
| 35 |
+
# Obtém a máscara e a confiança para cada pixel
|
| 36 |
mask_predicted = np.argmax(prediction[0], axis=-1)
|
| 37 |
+
confidences = np.max(prediction[0], axis=-1)
|
| 38 |
+
|
| 39 |
+
# Redimensiona a máscara e a confiança para o tamanho da imagem original
|
| 40 |
+
original_size = original_img_np.shape[:2]
|
| 41 |
+
mask_final = cv2.resize(mask_predicted.astype(np.uint8), (original_size[1], original_size[0]), interpolation=cv2.INTER_NEAREST)
|
| 42 |
+
confidences_final = cv2.resize(confidences, (original_size[1], original_size[0]), interpolation=cv2.INTER_LINEAR)
|
| 43 |
+
|
| 44 |
+
final_img = original_img_cv2.copy()
|
| 45 |
+
confidence_threshold = 0.7 # Limiar de 80%
|
| 46 |
+
|
| 47 |
+
for class_id in np.unique(mask_final):
|
| 48 |
+
if class_id == 0:
|
| 49 |
+
continue
|
| 50 |
+
|
| 51 |
+
class_name = CLASS_NAMES.get(class_id, f"Classe {class_id}")
|
| 52 |
+
binary_mask = (mask_final == class_id).astype(np.uint8)
|
| 53 |
+
binary_mask = binary_fill_holes(binary_mask)
|
| 54 |
+
|
| 55 |
+
contours, _ = cv2.findContours(binary_mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
|
| 56 |
+
|
| 57 |
+
for contour in contours:
|
| 58 |
+
x_min, y_min, w, h = cv2.boundingRect(contour)
|
| 59 |
+
x_max, y_max = x_min + w, y_min + h
|
| 60 |
+
|
| 61 |
+
region_mask = (mask_final[y_min:y_max, x_min:x_max] == class_id)
|
| 62 |
+
region_confidences = confidences_final[y_min:y_max, x_min:x_max][region_mask]
|
| 63 |
+
|
| 64 |
+
if region_confidences.size > 0:
|
| 65 |
+
avg_confidence = np.mean(region_confidences)
|
| 66 |
+
else:
|
| 67 |
+
avg_confidence = 0
|
| 68 |
+
|
| 69 |
+
if avg_confidence > confidence_threshold:
|
| 70 |
+
label_text = f"{class_name}: {avg_confidence:.2f}%"
|
| 71 |
+
color_tuple = CLASS_COLORS.get(class_id, (255, 255, 255))
|
| 72 |
+
|
| 73 |
+
cv2.rectangle(final_img, (x_min, y_min), (x_max, y_max), color_tuple, 2)
|
| 74 |
+
|
| 75 |
+
(text_width, text_height), baseline = cv2.getTextSize(label_text, cv2.FONT_HERSHEY_SIMPLEX, 0.6, 2)
|
| 76 |
+
cv2.rectangle(final_img, (x_min, y_min - text_height - 10), (x_min + text_width, y_min), color_tuple, -1)
|
| 77 |
+
cv2.putText(final_img, label_text, (x_min, y_min - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 0), 2)
|
| 78 |
+
|
| 79 |
|
| 80 |
+
final_img_rgb = cv2.cvtColor(final_img, cv2.COLOR_BGR2RGB)
|
| 81 |
+
return Image.fromarray(final_img_rgb)
|
| 82 |
|
|
|
|
| 83 |
|
|
|
|
| 84 |
gr.Interface(
|
| 85 |
fn=predict_image,
|
| 86 |
inputs=gr.Image(type="pil"),
|
| 87 |
outputs="image",
|
| 88 |
+
title="Ferramenta de Segmentação e Detecção de Objetos",
|
| 89 |
+
description="Carregue uma imagem e o modelo irá detetar objetos com caixas e confiança."
|
| 90 |
).launch()
|