feat: initial BantayCam scaffold

- FastAPI backend with async SQLAlchemy
- Camera RTSP management (add, start, stop)
- Vehicle detection (YOLO + fast-alpr)
  - Type: car, motorcycle, truck, jeepney
  - Color detection (HSV)
  - License plate OCR
  - Motorcycle person count
- Face detection + InsightFace ArcFace embedding
- pgvector identity grouping (auto-cluster same face)
- Vehicle + person movement trail APIs
- Docker Compose with pgvector/pg16
- Models: Camera, VehicleIdentity, VehicleEvent, PersonIdentity, FaceEvent
This commit is contained in:
Nemo
2026-03-12 12:11:02 +08:00
commit 7c43e4580d
24 changed files with 1650 additions and 0 deletions

View File

@@ -0,0 +1,30 @@
from sqlalchemy import Column, String, Boolean, DateTime, Text, Enum
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.sql import func
import uuid
import enum
from app.core.database import Base
class CameraStatus(str, enum.Enum):
active = "active"
inactive = "inactive"
error = "error"
class Camera(Base):
__tablename__ = "cameras"
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
name = Column(String(255), nullable=False, unique=True) # e.g. "Gate 1 - Main Entrance"
rtsp_url = Column(Text, nullable=False) # rtsp://admin:pass@192.168.1.64:554/...
location = Column(String(255), nullable=True) # e.g. "North Gate, Building A"
description = Column(Text, nullable=True)
status = Column(Enum(CameraStatus), default=CameraStatus.inactive)
is_enabled = Column(Boolean, default=True)
created_at = Column(DateTime(timezone=True), server_default=func.now())
updated_at = Column(DateTime(timezone=True), onupdate=func.now())
def __repr__(self):
return f"<Camera {self.name} ({self.status})>"