harmesh95 commited on
Commit
453aad4
·
1 Parent(s): 0824b05

Add application file

Browse files
Files changed (3) hide show
  1. Dockerfile +66 -0
  2. app.py +100 -0
  3. requirements.txt +8 -0
Dockerfile ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ------------------------------------------------------------
2
+ # Base image
3
+ # ------------------------------------------------------------
4
+ FROM python:3.12-slim-bookworm
5
+
6
+ # ------------------------------------------------------------
7
+ # Environment
8
+ # ------------------------------------------------------------
9
+ # PYTHONUNBUFFERED : ensures stdout/stderr aren’t buffered (logs show up instantly)
10
+ # PYTHONDONTWRITEBYTECODE : avoids .pyc files
11
+ # PIP_NO_CACHE_DIR : prevents pip from caching wheels
12
+ ENV PYTHONUNBUFFERED=1 \
13
+ PYTHONDONTWRITEBYTECODE=1 \
14
+ PIP_NO_CACHE_DIR=1
15
+
16
+ # Create a dedicated folder for Ultralytics settings
17
+ RUN mkdir -p /app/config
18
+
19
+ # Set the environment variable to point to that folder
20
+ ENV YOLO_CONFIG_DIR=/app/config
21
+ # ------------------------------------------------------------
22
+ # Working directory inside container
23
+ # ------------------------------------------------------------
24
+ WORKDIR /app
25
+
26
+ # ------------------------------------------------------------
27
+ # Copy application files
28
+ # ------------------------------------------------------------
29
+ # Copy only what’s required first (so Docker can cache layers)
30
+
31
+ COPY . .
32
+
33
+ # ------------------------------------------------------------
34
+ # System + Python dependencies
35
+ # ------------------------------------------------------------
36
+ # --no-install-recommends : install only what we ask for
37
+ # Remove apt cache & docs to reduce size
38
+ RUN apt-get update && \
39
+ apt-get install -y --no-install-recommends \
40
+ ffmpeg \
41
+ libgl1 \
42
+ libglib2.0-0 \
43
+ libsm6 \
44
+ libxrender1 \
45
+ libxext6 && \
46
+ rm -rf /var/lib/apt/lists/* /usr/share/doc /usr/share/man /usr/share/locale && \
47
+ \
48
+ # Upgrade pip & install Python dependencies (CPU-only Torch)
49
+ pip install --no-cache-dir --upgrade pip && \
50
+ pip install --no-cache-dir \
51
+ torch==2.4.1+cpu \
52
+ torchvision==0.19.1+cpu \
53
+ --index-url https://download.pytorch.org/whl/cpu && \
54
+ pip install --no-cache-dir -r requirements.txt && \
55
+ # Editable install so the package can be imported elsewhere
56
+ pip install --no-cache-dir -e .
57
+
58
+ # ------------------------------------------------------------
59
+ # Networking
60
+ # ------------------------------------------------------------
61
+ EXPOSE 8000
62
+
63
+ # ------------------------------------------------------------
64
+ # Start FastAPI with auto-reload (remove --reload for production)
65
+ # ------------------------------------------------------------
66
+ CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860", "--reload"]
app.py ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import uuid
3
+ import tempfile
4
+ import pandas as pd
5
+ from fastapi import FastAPI, UploadFile, File, HTTPException
6
+ from fastapi.responses import FileResponse
7
+ import uvicorn
8
+
9
+ from backend.services.video_data_extraction.video_preprocessor import VideoDataExtractor
10
+ from backend.services.prediction.predictor import ViolencePredictor
11
+
12
+ app = FastAPI(title="Video Analysis Backend")
13
+
14
+ processor = VideoDataExtractor()
15
+ predictor = ViolencePredictor()
16
+ jobs: dict[str, dict] = {}
17
+
18
+
19
+ @app.get("/")
20
+ def greet_json():
21
+ return {"Hello": "World!"}
22
+
23
+
24
+ @app.get("/health")
25
+ async def health_check():
26
+ return {"status": "ok", "message": "Service is running"}
27
+
28
+
29
+ @app.post("/process-video/")
30
+ async def process_video(file: UploadFile = File(...)):
31
+ try:
32
+ with tempfile.NamedTemporaryFile(delete=False, suffix=".mp4") as input_video:
33
+ input_video.write(await file.read())
34
+ input_path = input_video.name
35
+
36
+ output_csv = tempfile.NamedTemporaryFile(delete=False, suffix=".csv").name
37
+ output_video_path = tempfile.NamedTemporaryFile(
38
+ delete=False, suffix=".mp4"
39
+ ).name
40
+
41
+ frame_w, frame_h, num_interactions = processor.extract_video_data(
42
+ input_path,
43
+ output_csv,
44
+ output_folder=os.path.dirname(output_video_path),
45
+ save_video=True,
46
+ )
47
+
48
+ job_id = str(uuid.uuid4())
49
+ jobs[job_id] = {"csv": output_csv, "video": output_video_path}
50
+
51
+ return {
52
+ "job_id": job_id,
53
+ "message": f"Processed video with {num_interactions} interactions",
54
+ "frame_width": frame_w,
55
+ "frame_height": frame_h,
56
+ }
57
+ except Exception as e:
58
+ raise HTTPException(status_code=500, detail=str(e))
59
+ finally:
60
+ if os.path.exists(input_path):
61
+ os.unlink(input_path)
62
+
63
+
64
+ @app.get("/get-results/{job_id}")
65
+ async def get_results(job_id: str):
66
+ if job_id not in jobs:
67
+ raise HTTPException(status_code=404, detail="Job ID not found")
68
+ csv_path = jobs[job_id]["csv"]
69
+ if not os.path.exists(csv_path):
70
+ raise HTTPException(status_code=404, detail="CSV file not found")
71
+ return FileResponse(
72
+ csv_path, media_type="text/csv", filename="violence_analysis_results.csv"
73
+ )
74
+
75
+
76
+ @app.get("/sample-results/{job_id}")
77
+ async def get_sample_results(job_id: str):
78
+ if job_id not in jobs:
79
+ raise HTTPException(status_code=404, detail="Job ID not found")
80
+ csv_path = jobs[job_id]["csv"]
81
+ if not os.path.exists(csv_path):
82
+ raise HTTPException(status_code=404, detail="CSV file not found")
83
+ df = pd.read_csv(csv_path)
84
+ return df.head(5).to_dict(orient="records")
85
+
86
+
87
+ @app.post("/predict/{job_id}")
88
+ async def predict_violence(job_id: str):
89
+ if job_id not in jobs:
90
+ raise HTTPException(status_code=404, detail="Job ID not found")
91
+ csv_path = jobs[job_id]["csv"]
92
+ if not os.path.exists(csv_path):
93
+ raise HTTPException(status_code=404, detail="CSV file not found")
94
+ df = pd.read_csv(csv_path)
95
+ preds = predictor.predict(df)
96
+ return {"predictions": preds.tolist()}
97
+
98
+
99
+ if __name__ == "__main__":
100
+ uvicorn.run(app, host="0.0.0.0", port=7860)
requirements.txt ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ fastapi
2
+ uvicorn[standard]
3
+ numpy
4
+ opencv-python
5
+ pandas
6
+ scikit-learn
7
+ python-multipart
8
+ # any other dependencies your backend uses