Hussein El-Hadidy commited on
Commit
1a5dbca
·
1 Parent(s): 5601c7f
Files changed (7) hide show
  1. .gitignore +3 -1
  2. CPR/CPRAnalyzer.py +1 -1
  3. CPR/pose_estimation.py +1 -1
  4. app.py +6 -0
  5. backupbackend.zip +3 -0
  6. main.py +76 -17
  7. yolo11n-pose.pt +3 -0
.gitignore CHANGED
@@ -1,4 +1,6 @@
1
  __pycache__/*
2
  venv/*
3
  uploads/*
4
- runs/*
 
 
 
1
  __pycache__/*
2
  venv/*
3
  uploads/*
4
+ runs/*
5
+ screenshots/*
6
+ *.pyc
CPR/CPRAnalyzer.py CHANGED
@@ -232,7 +232,7 @@ class CPRAnalyzer:
232
  for path in paths:
233
  # You might want to convert local paths to URLs if you're serving them via FastAPI
234
  result.append({
235
- "image_url": f"/static/{os.path.basename(path)}", # Adjust if hosted elsewhere
236
  "description": description
237
  })
238
  return result
 
232
  for path in paths:
233
  # You might want to convert local paths to URLs if you're serving them via FastAPI
234
  result.append({
235
+ "image_url": f"{os.path.basename(path)}", # Adjust if hosted elsewhere
236
  "description": description
237
  })
238
  return result
CPR/pose_estimation.py CHANGED
@@ -8,7 +8,7 @@ class PoseEstimator:
8
  """Human pose estimation using YOLO"""
9
 
10
  def __init__(self, model_path="yolo11n-pose.pt", min_confidence=0.2):
11
- self.model = YOLO(model_path)
12
  self.min_confidence = min_confidence
13
 
14
  def detect_poses(self, frame):
 
8
  """Human pose estimation using YOLO"""
9
 
10
  def __init__(self, model_path="yolo11n-pose.pt", min_confidence=0.2):
11
+ self.model = YOLO(model_path).to('cuda')
12
  self.min_confidence = min_confidence
13
 
14
  def detect_poses(self, frame):
app.py CHANGED
@@ -249,6 +249,12 @@ async def process_video(file: UploadFile = File(...)):
249
  metrics = analyzer.get_compression_metrics()
250
  warnings = analyzer.get_posture_warning_results()
251
 
 
 
 
 
 
 
252
  # Estimate score (adjust this logic as needed)
253
  penalty = len(warnings) * 0.1
254
  rate_score = min(metrics["average_compression_rate"] / 120, 1.0)
 
249
  metrics = analyzer.get_compression_metrics()
250
  warnings = analyzer.get_posture_warning_results()
251
 
252
+ # Upload each warning to cloudinary
253
+ for w in warnings:
254
+ local_path = w['image_url']
255
+ upload_result = cloudinary.uploader.upload(local_path, folder="posture_warnings")
256
+ w['image_url'] = upload_result['secure_url']
257
+
258
  # Estimate score (adjust this logic as needed)
259
  penalty = len(warnings) * 0.1
260
  rate_score = min(metrics["average_compression_rate"] / 120, 1.0)
backupbackend.zip ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:31c7f003c89e9daecb3cf71a0806f668967632fd7a9eaa0c588ca666e7c87d83
3
+ size 39047568
main.py CHANGED
@@ -21,6 +21,10 @@ from fastapi import HTTPException
21
  from fastapi import WebSocket, WebSocketDisconnect
22
  import base64
23
  import cv2
 
 
 
 
24
 
25
 
26
 
@@ -194,28 +198,83 @@ async def process_video(file: UploadFile = File(...)):
194
 
195
  print("File content type:", file.content_type)
196
  print("File filename:", file.filename)
 
197
  # Save uploaded file
198
  video_path = os.path.join(UPLOAD_DIR, file.filename)
199
  with open(video_path, "wb") as buffer:
200
  shutil.copyfileobj(file.file, buffer)
201
 
202
- model = YOLO("yolo11n-pose_float16.tflite") # fixed variable name
203
-
204
- print("Model loaded successfully")
205
-
206
- # Run YOLO detection
207
- try:
208
- results = model(
209
- source=video_path,
210
- show=True, # Set True if running locally and want to view
211
- save=True,
212
- project="runs/detect",
213
- name="testResult"
214
- )
215
- except Exception as e:
216
- raise HTTPException(status_code=500, detail=f"YOLO processing error: {str(e)}")
217
-
218
- return JSONResponse(content={"message": "Video processed successfully", "result_dir": "runs/detect/testResult"})
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
219
 
220
 
221
  @app.post("/process_image")
 
21
  from fastapi import WebSocket, WebSocketDisconnect
22
  import base64
23
  import cv2
24
+ import time
25
+ from CPR.CPRAnalyzer import CPRAnalyzer
26
+ import tempfile
27
+
28
 
29
 
30
 
 
198
 
199
  print("File content type:", file.content_type)
200
  print("File filename:", file.filename)
201
+
202
  # Save uploaded file
203
  video_path = os.path.join(UPLOAD_DIR, file.filename)
204
  with open(video_path, "wb") as buffer:
205
  shutil.copyfileobj(file.file, buffer)
206
 
207
+ print("[START] CPR Analysis started")
208
+ start_time = time.time()
209
+
210
+ cap = cv2.VideoCapture(video_path)
211
+ fps = cap.get(cv2.CAP_PROP_FPS)
212
+ total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
213
+ duration_seconds = total_frames / fps
214
+ chunk_duration = 10 # seconds
215
+ frames_per_chunk = int(fps * chunk_duration)
216
+
217
+ chunks = []
218
+ chunk_index = 0
219
+ current_frame = 0
220
+
221
+ while current_frame < total_frames:
222
+ # Read the chunk into memory
223
+ frames = []
224
+ for _ in range(frames_per_chunk):
225
+ ret, frame = cap.read()
226
+ if not ret:
227
+ break
228
+ frames.append(frame)
229
+ current_frame += 1
230
+
231
+ if not frames:
232
+ break
233
+
234
+ # Save chunk to temp video
235
+ temp_chunk_path = os.path.join(tempfile.gettempdir(), f"chunk_{chunk_index}.mp4")
236
+ height, width = frames[0].shape[:2]
237
+ fourcc = cv2.VideoWriter_fourcc(*'mp4v')
238
+ out = cv2.VideoWriter(temp_chunk_path, fourcc, fps, (width, height))
239
+ for f in frames:
240
+ out.write(f)
241
+ out.release()
242
+
243
+ # Analyze chunk
244
+ print(f"[CHUNK {chunk_index}] Processing chunk at {temp_chunk_path}")
245
+ analyzer = CPRAnalyzer(temp_chunk_path)
246
+ analyzer.run_analysis()
247
+
248
+ # Gather results
249
+ metrics = analyzer.get_compression_metrics()
250
+ warnings = analyzer.get_posture_warning_results()
251
+
252
+ # Upload each warning to cloudinary
253
+ for w in warnings:
254
+ filename = w['image_url'] # just the filename
255
+ local_path = os.path.join("screenshots", filename)
256
+ upload_result = cloudinary.uploader.upload(local_path, folder="posture_warnings")
257
+ w['image_url'] = upload_result['secure_url']
258
+
259
+ # Estimate score (adjust this logic as needed)
260
+ penalty = len(warnings) * 0.1
261
+ rate_score = min(metrics["average_compression_rate"] / 120, 1.0)
262
+ depth_score = min(metrics["average_compression_depth"] / 5.0, 1.0)
263
+ average_score = max(0.0, (rate_score + depth_score)/2 - penalty)
264
+
265
+ chunks.append({
266
+ "average_score": round(average_score, 2),
267
+ "average_rate": round(metrics["average_compression_rate"], 1),
268
+ "average_depth": round(metrics["average_compression_depth"], 1),
269
+ "posture_warnings": warnings
270
+ })
271
+
272
+ chunk_index += 1
273
+
274
+ cap.release()
275
+ print(f"[END] Total processing time: {time.time() - start_time:.2f}s")
276
+
277
+ return JSONResponse(content={"chunks": chunks})
278
 
279
 
280
  @app.post("/process_image")
yolo11n-pose.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:869e83fcdffdc7371fa4e34cd8e51c838cc729571d1635e5141e3075e9319dc0
3
+ size 6255593