File size: 5,535 Bytes
a2b5362 06c0743 a2b5362 06c0743 494daa2 06c0743 494daa2 06c0743 a2b5362 e78d7b4 a2b5362 e78d7b4 a2b5362 06c0743 e78d7b4 a2b5362 06c0743 494daa2 06c0743 a2b5362 e78d7b4 a2b5362 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 | import streamlit as st
import cv2
import numpy as np
from PIL import Image
from yolo_inference import build_detector_from_env
from streamlit_webrtc import webrtc_streamer, VideoProcessorBase, RTCConfiguration
import av
# Configuração inicial da página do Streamlit (Título e Layout)
st.set_page_config(page_title="YOLO Detection - Streamlit", layout="wide", page_icon="🚀")
# Configuração RTC para STUN servers (mais robusta para evitar timeouts)
RTC_CONFIGURATION = RTCConfiguration(
{
"iceServers": [
{"urls": ["stun:stun.l.google.com:19302"]},
{"urls": ["stun:stun1.l.google.com:19302"]},
{"urls": ["stun:stun2.l.google.com:19302"]},
{"urls": ["stun:stun3.l.google.com:19302"]},
{"urls": ["stun:stun4.l.google.com:19302"]},
{"urls": ["stun:stun.services.mozilla.com"]},
]
}
)
# Lista de classes do dataset personalizado para monitoramento especial
CUSTOM_CLASSES = {"car", "truck", "bus", "motorbike", "bicycle", "van", "threewheel"}
class YoloVideoProcessor(VideoProcessorBase):
def __init__(self, detector):
self.detector = detector
def recv(self, frame):
img = frame.to_ndarray(format="bgr24")
# Realiza a detecção de objetos
detections = self.detector.detect(img)
# Desenha os resultados no frame
img_out = self.detector.draw(img, detections)
# Adiciona overlay de instrução
cv2.putText(img_out, "YOLO Real-time Detection", (20, 40),
cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)
return av.VideoFrame.from_ndarray(img_out, format="bgr24")
def main():
"""
Função principal que gerencia a interface Streamlit.
Permite alternar entre detecção em imagens estáticas e vídeo em tempo real via webcam.
"""
st.title("🚀 YOLO Object Detection")
st.markdown("---")
st.markdown("### Interface interativa para detecção de objetos usando YOLOv3-tiny.")
# Sidebar: Painel lateral para controle de parâmetros e seleção de modo
st.sidebar.header("🛠️ Configurações do Modelo")
# Sliders para ajuste dinâmico dos limiares de detecção
conf_threshold = st.sidebar.slider("Confiança Mínima (Threshold)", 0.0, 1.0, 0.5, 0.05,
help="Nível mínimo de certeza para exibir uma detecção.")
nms_threshold = st.sidebar.slider("NMS Threshold", 0.0, 1.0, 0.4, 0.05,
help="Limiar para supressão de não-máximos (remove bboxes sobrepostas).")
st.sidebar.markdown("---")
# Seleção do modo de operação
mode = st.sidebar.radio(
"📡 Escolha o Modo de Entrada",
["Imagem", "Câmera (Snapshot)", "Câmera (WebRTC)"],
help="Snapshot: Mais estável em nuvem. WebRTC: Vídeo em tempo real (pode falhar em algumas redes)."
)
# Inicializa o detector YOLO
try:
detector = build_detector_from_env(conf_threshold=conf_threshold, nms_threshold=nms_threshold)
except Exception as e:
st.error(f"❌ Erro ao inicializar detector: {e}")
return
if mode == "Imagem":
st.subheader("📁 Upload e Detecção em Imagem")
uploaded_file = st.file_uploader("Arraste ou selecione uma imagem...", type=["jpg", "jpeg", "png"])
if uploaded_file is not None:
image = Image.open(uploaded_file)
process_and_display_image(image, detector)
elif mode == "Câmera (Snapshot)":
st.subheader("📸 Detecção via Foto (Snapshot)")
st.info("Este modo é o mais estável para uso em nuvem. Ele tira uma foto e processa a detecção.")
img_file = st.camera_input("Tirar Foto")
if img_file:
image = Image.open(img_file)
process_and_display_image(image, detector)
elif mode == "Câmera (WebRTC)":
st.subheader("🎥 Detecção via Webcam (WebRTC)")
st.info("Vídeo em tempo real. Se a conexão demorar (timeout), use o modo 'Câmera (Snapshot)'.")
webrtc_streamer(
key="yolo-detection",
video_processor_factory=lambda: YoloVideoProcessor(detector),
rtc_configuration=RTC_CONFIGURATION,
media_stream_constraints={"video": True, "audio": False},
async_processing=True,
video_html_attrs={
"style": {"width": "100%"},
"controls": False,
"autoPlay": True,
},
)
def process_and_display_image(image, detector):
"""Função auxiliar para processar e exibir os resultados de uma imagem PIL"""
image_np = np.array(image)
frame_bgr = cv2.cvtColor(image_np, cv2.COLOR_RGB2BGR)
with st.spinner('Processando...'):
detections = detector.detect(frame_bgr)
hits = sorted({d['class_name'] for d in detections if d['class_name'] in CUSTOM_CLASSES})
col1, col2 = st.columns(2)
with col1:
st.image(image, caption="Entrada", use_column_width=True)
with col2:
result_bgr = detector.draw(frame_bgr, detections)
result_rgb = cv2.cvtColor(result_bgr, cv2.COLOR_BGR2RGB)
st.image(result_rgb, caption="Resultado da Detecção", use_column_width=True)
if hits:
st.success(f"✅ Objetos detectados: **{', '.join(hits)}**")
else:
st.info("ℹ️ Nenhuma classe de interesse detectada.")
if __name__ == "__main__":
main()
|