97 lines
2.8 KiB
Python
97 lines
2.8 KiB
Python
"""
|
|
ContentTypeProfile protocol and config dataclasses.
|
|
|
|
Each profile defines the pipeline topology (as a JSONB blob), stage configs,
|
|
brand dictionary, VLM prompt templates, and aggregation strategy.
|
|
|
|
When profiles are persisted, the pipeline field is a JSONB column.
|
|
For now, profiles are code-only and pipeline_config() returns a hardcoded value.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass, field
|
|
from typing import Any, Dict, Protocol
|
|
|
|
from detect.models import BrandDetection, DetectionReport
|
|
from core.schema.models.pipeline_config import PipelineConfig, StageRef, Edge
|
|
|
|
|
|
@dataclass
|
|
class FrameExtractionConfig:
|
|
fps: float = 2.0
|
|
max_frames: int = 500
|
|
|
|
|
|
@dataclass
|
|
class SceneFilterConfig:
|
|
hamming_threshold: int = 8
|
|
enabled: bool = True
|
|
|
|
|
|
@dataclass
|
|
class DetectionConfig:
|
|
model_name: str = "yolov8n.pt"
|
|
confidence_threshold: float = 0.3
|
|
target_classes: list[str] = field(default_factory=lambda: ["logo", "text"])
|
|
|
|
|
|
@dataclass
|
|
class OCRConfig:
|
|
languages: list[str] = field(default_factory=lambda: ["en"])
|
|
min_confidence: float = 0.5
|
|
|
|
|
|
@dataclass
|
|
class ResolverConfig:
|
|
fuzzy_threshold: int = 75
|
|
|
|
|
|
@dataclass
|
|
class RegionAnalysisConfig:
|
|
enabled: bool = True
|
|
# Edge detection (Canny + HoughLinesP)
|
|
edge_canny_low: int = 50
|
|
edge_canny_high: int = 150
|
|
edge_hough_threshold: int = 80
|
|
edge_hough_min_length: int = 100
|
|
edge_hough_max_gap: int = 10
|
|
edge_pair_max_distance: int = 200
|
|
edge_pair_min_distance: int = 15
|
|
|
|
|
|
@dataclass
|
|
class CropContext:
|
|
image: bytes
|
|
surrounding_text: str = ""
|
|
position_hint: str = ""
|
|
|
|
|
|
def pipeline_config_from_dict(data: Dict[str, Any]) -> PipelineConfig:
|
|
"""Deserialize a PipelineConfig from a JSONB dict."""
|
|
stages = [StageRef(**s) for s in data.get("stages", [])]
|
|
edges = [Edge(**e) for e in data.get("edges", [])]
|
|
return PipelineConfig(
|
|
name=data.get("name", ""),
|
|
profile_name=data.get("profile_name", ""),
|
|
stages=stages,
|
|
edges=edges,
|
|
routing_rules=data.get("routing_rules", {}),
|
|
)
|
|
|
|
|
|
class ContentTypeProfile(Protocol):
|
|
name: str
|
|
pipeline: Dict[str, Any] # JSONB blob — PipelineConfig shape
|
|
|
|
def pipeline_config(self) -> PipelineConfig: ...
|
|
def frame_extraction_config(self) -> FrameExtractionConfig: ...
|
|
def scene_filter_config(self) -> SceneFilterConfig: ...
|
|
def region_analysis_config(self) -> RegionAnalysisConfig: ...
|
|
def detection_config(self) -> DetectionConfig: ...
|
|
def ocr_config(self) -> OCRConfig: ...
|
|
def resolver_config(self) -> ResolverConfig: ...
|
|
def vlm_prompt(self, crop_context: CropContext) -> str: ...
|
|
def aggregate(self, detections: list[BrandDetection]) -> DetectionReport: ...
|
|
def auxiliary_detections(self, source: str) -> list[BrandDetection]: ...
|