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")