Spaces:
Sleeping
Sleeping
File size: 4,052 Bytes
2758540 | 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 | """
database/models.py - SQLAlchemy ORM models for Surveillance System
"""
import uuid
from datetime import datetime
from sqlalchemy import Column, String, DateTime, Float, Text, Integer, ForeignKey, JSON, Enum
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.orm import relationship
from database.session import Base
import enum
class ActivityType(str, enum.Enum):
DETECTED = "detected"
TRACKED = "tracked"
REID_MATCH = "reid_match"
ANOMALY = "anomaly"
LOITERING = "loitering"
RUNNING = "running"
FIGHTING = "fighting"
TRESPASSING = "trespassing"
class AnalysisSession(Base):
__tablename__ = "analysis_sessions"
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, index=True)
timestamp = Column(DateTime, default=datetime.utcnow, nullable=False, index=True)
video_filename = Column(String(255), nullable=False)
thumbnail_path = Column(String(500), nullable=True)
# Analysis Summary Stats
duration_sec = Column(Float, nullable=False, default=0.0)
frames_processed = Column(Integer, nullable=False, default=0)
unique_persons = Column(Integer, nullable=False, default=0)
peak_count = Column(Integer, nullable=False, default=0)
def __repr__(self):
return f"<AnalysisSession id={self.id} video={self.video_filename}>"
class Person(Base):
__tablename__ = "persons"
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, index=True)
first_seen = Column(DateTime, default=datetime.utcnow, nullable=False)
last_seen = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False)
# ReID embedding reference
faiss_id = Column(Integer, nullable=True, unique=True)
embedding_version = Column(String(50), default="vit-base-patch16-224")
# Attributes from CLIP
attributes = Column(JSON, nullable=True) # {"clothing": [...], "colors": [...]}
thumbnail_path = Column(String(500), nullable=True)
track_ids = Column(JSON, default=list) # list of all track IDs assigned cross-camera
events = relationship("Event", back_populates="person", cascade="all, delete-orphan")
def __repr__(self):
return f"<Person id={self.id} first_seen={self.first_seen}>"
class Event(Base):
__tablename__ = "events"
event_id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, index=True)
person_id = Column(UUID(as_uuid=True), ForeignKey("persons.id", ondelete="CASCADE"), nullable=False, index=True)
camera_id = Column(String(64), nullable=False, index=True)
timestamp = Column(DateTime, default=datetime.utcnow, nullable=False, index=True)
activity_type = Column(Enum(ActivityType), default=ActivityType.DETECTED, nullable=False)
# Spatial & tracking info
bounding_box = Column(JSON, nullable=True) # {"x1": f, "y1": f, "x2": f, "y2": f}
confidence = Column(Float, nullable=True)
track_id = Column(Integer, nullable=True)
location_zone = Column(String(128), nullable=True)
# Additional metadata
anomaly_score = Column(Float, default=0.0)
raw_metadata = Column(JSON, nullable=True)
description = Column(Text, nullable=True) # NLP-generated description
person = relationship("Person", back_populates="events")
def __repr__(self):
return f"<Event {self.event_id} person={self.person_id} cam={self.camera_id} type={self.activity_type}>"
class IncidentReport(Base):
__tablename__ = "incident_reports"
report_id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, index=True)
person_id = Column(UUID(as_uuid=True), ForeignKey("persons.id", ondelete="SET NULL"), nullable=True)
generated_at = Column(DateTime, default=datetime.utcnow)
report_text = Column(Text, nullable=False)
summary = Column(Text, nullable=True)
severity = Column(String(20), default="medium") # low / medium / high / critical
camera_ids = Column(JSON, default=list)
model_version = Column(String(50), default="flan-t5-base")
|