Hussein El-Hadidy commited on
Commit ·
3cd94cf
1
Parent(s): 29f3df9
fixes
Browse files- CPR_Module/Common/chest_initializer.py +47 -49
- app.py +1 -1
CPR_Module/Common/chest_initializer.py
CHANGED
|
@@ -1,11 +1,10 @@
|
|
| 1 |
import cv2
|
| 2 |
import numpy as np
|
| 3 |
-
|
| 4 |
from CPR_Module.Common.keypoints import CocoKeypoints
|
| 5 |
from CPR_Module.Common.logging_config import cpr_logger
|
| 6 |
|
| 7 |
class ChestInitializer:
|
| 8 |
-
"""
|
| 9 |
|
| 10 |
def __init__(self):
|
| 11 |
self.chest_params = None
|
|
@@ -13,7 +12,7 @@ class ChestInitializer:
|
|
| 13 |
self.expected_chest_params = None
|
| 14 |
|
| 15 |
def estimate_chest_region(self, keypoints, bounding_box, frame_width, frame_height):
|
| 16 |
-
"""Estimate chest region
|
| 17 |
try:
|
| 18 |
# Unpack bounding box and calculate shoulder dimensions
|
| 19 |
bbox_x1, bbox_y1, bbox_x2, bbox_y2 = bounding_box
|
|
@@ -24,62 +23,61 @@ class ChestInitializer:
|
|
| 24 |
right_shoulder = keypoints[CocoKeypoints.RIGHT_SHOULDER.value]
|
| 25 |
|
| 26 |
# Midpoints calculation
|
| 27 |
-
shoulder_center = np.array([
|
| 28 |
-
|
| 29 |
-
(left_shoulder[1] + right_shoulder[1]) / 2
|
| 30 |
-
])
|
| 31 |
|
| 32 |
-
#
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
chest_center_x = shoulder_center[0] - 0.3 * bbox_delta_y
|
| 39 |
-
chest_center_y = shoulder_center[1] - 0.1 * bbox_delta_y
|
| 40 |
-
else: # Left orientation
|
| 41 |
-
chest_center_x = shoulder_center[0] + 1.0 * bbox_delta_y
|
| 42 |
-
chest_center_y = shoulder_center[1] - 0.1 * bbox_delta_y
|
| 43 |
-
|
| 44 |
-
# Chest dimensions
|
| 45 |
chest_dx = bbox_delta_y * 0.8
|
| 46 |
chest_dy = bbox_delta_y * 1.75
|
| 47 |
|
| 48 |
# Calculate region coordinates
|
| 49 |
-
x1 =
|
| 50 |
-
y1 =
|
| 51 |
-
x2 =
|
| 52 |
-
y2 =
|
| 53 |
-
|
| 54 |
-
#
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
#
|
| 61 |
-
x1 = max(bbox_x1, min(x1, bbox_x2))
|
| 62 |
-
y1 = max(bbox_y1, min(y1, bbox_y2))
|
| 63 |
-
x2 = max(bbox_x1, min(x2, bbox_x2))
|
| 64 |
-
y2 = max(bbox_y1, min(y2, bbox_y2))
|
| 65 |
-
|
| 66 |
-
# Final validity check
|
| 67 |
if x2 <= x1 or y2 <= y1:
|
| 68 |
return None
|
| 69 |
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
|
|
|
|
| 76 |
|
| 77 |
except (IndexError, TypeError, ValueError) as e:
|
| 78 |
-
|
| 79 |
return None
|
| 80 |
|
| 81 |
def estimate_chest_region_weighted_avg(self, frame_width, frame_height, window_size=60, min_samples=3):
|
| 82 |
-
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 83 |
if not self.chest_params_history:
|
| 84 |
return None
|
| 85 |
|
|
@@ -121,11 +119,11 @@ class ChestInitializer:
|
|
| 121 |
)
|
| 122 |
|
| 123 |
except Exception as e:
|
| 124 |
-
|
| 125 |
return None
|
| 126 |
|
| 127 |
def draw_expected_chest_region(self, frame):
|
| 128 |
-
"""
|
| 129 |
if self.expected_chest_params is None:
|
| 130 |
return frame
|
| 131 |
|
|
@@ -140,7 +138,7 @@ class ChestInitializer:
|
|
| 140 |
|
| 141 |
cv2.circle(frame, (int(cx), int(cy)), 8, (128, 128, 0), -1)
|
| 142 |
|
| 143 |
-
cv2.putText(frame, "CHEST", (x1, max(10, y1 - 5)),
|
| 144 |
cv2.FONT_HERSHEY_SIMPLEX, 0.8, (128, 128, 0), 2)
|
| 145 |
|
| 146 |
return frame
|
|
|
|
| 1 |
import cv2
|
| 2 |
import numpy as np
|
|
|
|
| 3 |
from CPR_Module.Common.keypoints import CocoKeypoints
|
| 4 |
from CPR_Module.Common.logging_config import cpr_logger
|
| 5 |
|
| 6 |
class ChestInitializer:
|
| 7 |
+
"""Handles chest point detection with validations in estimation."""
|
| 8 |
|
| 9 |
def __init__(self):
|
| 10 |
self.chest_params = None
|
|
|
|
| 12 |
self.expected_chest_params = None
|
| 13 |
|
| 14 |
def estimate_chest_region(self, keypoints, bounding_box, frame_width, frame_height):
|
| 15 |
+
"""Estimate and validate chest region. Returns (cx, cy, cw, ch) or None."""
|
| 16 |
try:
|
| 17 |
# Unpack bounding box and calculate shoulder dimensions
|
| 18 |
bbox_x1, bbox_y1, bbox_x2, bbox_y2 = bounding_box
|
|
|
|
| 23 |
right_shoulder = keypoints[CocoKeypoints.RIGHT_SHOULDER.value]
|
| 24 |
|
| 25 |
# Midpoints calculation
|
| 26 |
+
shoulder_center = np.array([(left_shoulder[0] + right_shoulder[0]) / 2,
|
| 27 |
+
(left_shoulder[1] + right_shoulder[1]) / 2])
|
|
|
|
|
|
|
| 28 |
|
| 29 |
+
# Calculate chest center by applying directional adjustment separately for x and y
|
| 30 |
+
chest_center_from_shoulder_x = shoulder_center[0] - 0.3 * bbox_delta_y
|
| 31 |
+
chest_center_from_shoulder_y = shoulder_center[1] - 0.1 * bbox_delta_y
|
| 32 |
+
chest_center_from_shoulder = np.array([chest_center_from_shoulder_x, chest_center_from_shoulder_y])
|
| 33 |
+
|
| 34 |
+
# Chest dimensions (85% of shoulder width, 40% height)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 35 |
chest_dx = bbox_delta_y * 0.8
|
| 36 |
chest_dy = bbox_delta_y * 1.75
|
| 37 |
|
| 38 |
# Calculate region coordinates
|
| 39 |
+
x1 = chest_center_from_shoulder[0] - chest_dx / 2
|
| 40 |
+
y1 = chest_center_from_shoulder[1] - chest_dy / 2
|
| 41 |
+
x2 = chest_center_from_shoulder[0] + chest_dx / 2
|
| 42 |
+
y2 = chest_center_from_shoulder[1] + chest_dy / 2
|
| 43 |
+
|
| 44 |
+
# Clamp to frame boundaries
|
| 45 |
+
x1 = max(0, min(x1, frame_width - 1))
|
| 46 |
+
y1 = max(0, min(y1, frame_height - 1))
|
| 47 |
+
x2 = max(0, min(x2, frame_width - 1))
|
| 48 |
+
y2 = max(0, min(y2, frame_height - 1))
|
| 49 |
+
|
| 50 |
+
# Check validity
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 51 |
if x2 <= x1 or y2 <= y1:
|
| 52 |
return None
|
| 53 |
|
| 54 |
+
# Adjusted parameters
|
| 55 |
+
cx = (x1 + x2) / 2
|
| 56 |
+
cy = (y1 + y2) / 2
|
| 57 |
+
cw = x2 - x1
|
| 58 |
+
ch = y2 - y1
|
| 59 |
+
|
| 60 |
+
return (cx, cy, cw, ch)
|
| 61 |
|
| 62 |
except (IndexError, TypeError, ValueError) as e:
|
| 63 |
+
print(f"Chest estimation error: {e}")
|
| 64 |
return None
|
| 65 |
|
| 66 |
def estimate_chest_region_weighted_avg(self, frame_width, frame_height, window_size=60, min_samples=3):
|
| 67 |
+
"""
|
| 68 |
+
Calculate stabilized chest parameters using weighted averaging with boundary checks.
|
| 69 |
+
|
| 70 |
+
Args:
|
| 71 |
+
self.chest_params_history: List of recent chest parameters [(cx, cy, cw, ch), ...]
|
| 72 |
+
frame_width: Width of the video frame
|
| 73 |
+
frame_height: Height of the video frame
|
| 74 |
+
window_size: Number of recent frames to consider (default: 5)
|
| 75 |
+
min_samples: Minimum valid samples required (default: 3)
|
| 76 |
+
|
| 77 |
+
Returns:
|
| 78 |
+
Tuple of (cx, cy, cw, ch) as integers within frame boundaries,
|
| 79 |
+
or None if insufficient data or invalid rectangle
|
| 80 |
+
"""
|
| 81 |
if not self.chest_params_history:
|
| 82 |
return None
|
| 83 |
|
|
|
|
| 119 |
)
|
| 120 |
|
| 121 |
except Exception as e:
|
| 122 |
+
print(f"Chest region estimation error: {e}")
|
| 123 |
return None
|
| 124 |
|
| 125 |
def draw_expected_chest_region(self, frame):
|
| 126 |
+
"""Draws the chest region without validation."""
|
| 127 |
if self.expected_chest_params is None:
|
| 128 |
return frame
|
| 129 |
|
|
|
|
| 138 |
|
| 139 |
cv2.circle(frame, (int(cx), int(cy)), 8, (128, 128, 0), -1)
|
| 140 |
|
| 141 |
+
cv2.putText(frame, "EXPECTED CHEST", (x1, max(10, y1 - 5)),
|
| 142 |
cv2.FONT_HERSHEY_SIMPLEX, 0.8, (128, 128, 0), 2)
|
| 143 |
|
| 144 |
return frame
|
app.py
CHANGED
|
@@ -39,7 +39,7 @@ import signal
|
|
| 39 |
|
| 40 |
from CPR_Module.Educational_Mode.CPRAnalyzer import CPRAnalyzer as OfflineAnalyzer
|
| 41 |
from CPR_Module.Emergency_Mode.main import CPRAnalyzer as RealtimeAnalyzer
|
| 42 |
-
from CPR_Module.Common.analysis_socket_server import AnalysisSocketServer
|
| 43 |
from CPR_Module.Common.logging_config import cpr_logger
|
| 44 |
|
| 45 |
app = FastAPI()
|
|
|
|
| 39 |
|
| 40 |
from CPR_Module.Educational_Mode.CPRAnalyzer import CPRAnalyzer as OfflineAnalyzer
|
| 41 |
from CPR_Module.Emergency_Mode.main import CPRAnalyzer as RealtimeAnalyzer
|
| 42 |
+
from CPR_Module.Common.analysis_socket_server import AnalysisSocketServer
|
| 43 |
from CPR_Module.Common.logging_config import cpr_logger
|
| 44 |
|
| 45 |
app = FastAPI()
|