import io from PIL import Image import streamlit as st import config from utils import draw_boxes, run_detection # App config st.set_page_config( page_title=config.PAGE_TITLE, page_icon=config.PAGE_ICON, layout=config.LAYOUT, ) # Sidebar controls st.sidebar.header("⚙️ Настройки") model_label = st.sidebar.selectbox( "Hugging Face модель", options=list(config.MODEL_CATALOG.keys()), index=0, help="Например, YOLO модель для детекции", ) model_id = config.MODEL_CATALOG[model_label] threshold = st.sidebar.slider( "Порог уверенности", min_value=0.0, max_value=1.0, value=float(config.DEFAULT_THRESHOLD), step=0.01, ) st.title(config.PAGE_ICON + " " + config.PAGE_TITLE) st.write( "Загрузите изображение. Модель найдёт объекты " "и отрисует bounding boxes." ) uploaded = st.file_uploader( "Выберите изображение", type=config.UPLOADER_TYPES, accept_multiple_files=False, ) if uploaded is not None: try: image = Image.open(uploaded).convert("RGB") except Exception as exc: st.error(f"Не удалось открыть изображение: {exc}") st.stop() with st.spinner("Детекция логотипов…"): try: predictions = run_detection( model_id, image, ) except Exception as exc: st.error(f"Ошибка инференса: {exc}") st.stop() cols = st.columns(2) with cols[0]: st.image( image, caption="Оригинал", use_container_width=True, ) if isinstance(predictions, dict) and predictions.get("error"): err_msg = predictions.get("error") st.error(f"Ошибка модели: {err_msg}") st.stop() annotated_image = draw_boxes(image, predictions, threshold) with cols[1]: st.image( annotated_image, caption="С найденными боксами", use_container_width=True, ) # Stats and download shown = sum( 1 for p in predictions # type: ignore[assignment] if float(p.get("score", 0.0)) >= threshold ) total = len(predictions) # type: ignore[arg-type] st.caption( f"Показано боксов: {shown} из {total} " f"(порог {threshold:.2f})" ) predictions_str = "\n".join( [f"{p['label']}: {round(p['score'], 2)}" for p in predictions] ) st.markdown(f"**{predictions_str}**") buf = io.BytesIO() annotated_image.save(buf, format="PNG") st.download_button( label="Скачать размеченное изображение", data=buf.getvalue(), file_name="detections.png", mime="image/png", type="primary", )