|
|
from __future__ import annotations
|
|
|
from typing import Tuple, Optional
|
|
|
import cv2
|
|
|
import numpy as np
|
|
|
|
|
|
# --- пакетные импорты с fallback при запуске скриптом ---
|
|
|
try:
|
|
|
from . import config as _cfg
|
|
|
from . import state as _state
|
|
|
from .preview import (
|
|
|
encode_jpeg_bgr as _encode_jpeg_bgr,
|
|
|
maybe_downscale as _maybe_downscale,
|
|
|
publish_preview as _publish_preview,
|
|
|
)
|
|
|
except Exception: # запуск вне пакета (нежелательно, но поддержим)
|
|
|
import config as _cfg # type: ignore
|
|
|
import state as _state # type: ignore
|
|
|
from preview import ( # type: ignore
|
|
|
encode_jpeg_bgr as _encode_jpeg_bgr,
|
|
|
maybe_downscale as _maybe_downscale,
|
|
|
publish_preview as _publish_preview,
|
|
|
)
|
|
|
|
|
|
# Оставляем старые имена функций для обратной совместимости,
|
|
|
# под капотом вызываем реализацию из preview.py.
|
|
|
|
|
|
def encode_jpeg_bgr(img_bgr: np.ndarray) -> Optional[bytes]:
|
|
|
"""Совместимость: прокси к preview.encode_jpeg_bgr."""
|
|
|
return _encode_jpeg_bgr(img_bgr)
|
|
|
|
|
|
|
|
|
def maybe_downscale(img: np.ndarray, target_w: int = None) -> Tuple[np.ndarray, float, float]:
|
|
|
"""Совместимость: прокси к preview.maybe_downscale."""
|
|
|
if target_w is None:
|
|
|
target_w = int(getattr(_cfg, "PREVIEW_TARGET_W", 896))
|
|
|
return _maybe_downscale(img, target_w)
|
|
|
|
|
|
|
|
|
def publish_preview(cam_id: int, img: np.ndarray) -> None:
|
|
|
"""
|
|
|
Совместимость: прокси к preview.publish_preview.
|
|
|
Учитывает флаг PUBLISH_ONLY_IF_CLIENTS внутри preview.
|
|
|
"""
|
|
|
_publish_preview(cam_id, img)
|
|
|
|
|
|
|
|
|
def publish_annotated_scaled(
|
|
|
cam_id: int,
|
|
|
frame_bgr: np.ndarray,
|
|
|
x1: int, y1: int, x2: int, y2: int,
|
|
|
label: str
|
|
|
) -> None:
|
|
|
"""
|
|
|
Быстрый аннотатор: даунскейлит кадр под превью, рисует коробку+лейбл и публикует JPEG.
|
|
|
"""
|
|
|
# ранний выход, если никому слать
|
|
|
if getattr(_cfg, "PUBLISH_ONLY_IF_CLIENTS", True) and not _state.video_clients:
|
|
|
return
|
|
|
|
|
|
down, sx, sy = maybe_downscale(frame_bgr)
|
|
|
if sx != 1.0 or sy != 1.0:
|
|
|
x1 = int(x1 * sx); y1 = int(y1 * sy)
|
|
|
x2 = int(x2 * sx); y2 = int(y2 * sy)
|
|
|
|
|
|
cv2.rectangle(down, (x1, y1), (x2, y2), (0, 255, 0), 2, lineType=cv2.LINE_4)
|
|
|
cv2.putText(
|
|
|
down, label, (x1, max(0, y1 - 6)),
|
|
|
cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 1, cv2.LINE_4
|
|
|
)
|
|
|
publish_preview(cam_id, down)
|