Hussein El-Hadidy commited on
Commit
3cd94cf
·
1 Parent(s): 29f3df9
Files changed (2) hide show
  1. CPR_Module/Common/chest_initializer.py +47 -49
  2. 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
- """Estimates and stabilizes chest region parameters based on keypoints and bounding box."""
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 parameters based on keypoints and bounding box."""
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
- (left_shoulder[0] + right_shoulder[0]) / 2,
29
- (left_shoulder[1] + right_shoulder[1]) / 2
30
- ])
31
 
32
- #& Handling different patient positions
33
- # If the x-coordinate shoulder center is closer to that of the Bottom-Right bbox corner (2)
34
- # then the orientation is "right"
35
- # If the x-coordinate shoulder center is closer to that of the Top-Left bbox corner (1)
36
- # then the orientation is "left"
37
- if abs(shoulder_center[0] - bbox_x2) < abs(shoulder_center[0] - bbox_x1): # Right orientation
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 = chest_center_x - chest_dx / 2
50
- y1 = chest_center_y - chest_dy / 2
51
- x2 = chest_center_x + chest_dx / 2
52
- y2 = chest_center_y + chest_dy / 2
53
-
54
- # First clamp the bounding box to frame boundaries
55
- bbox_x1 = max(0, min(bbox_x1, frame_width - 1))
56
- bbox_y1 = max(0, min(bbox_y1, frame_height - 1))
57
- bbox_x2 = max(0, min(bbox_x2, frame_width - 1))
58
- bbox_y2 = max(0, min(bbox_y2, frame_height - 1))
59
-
60
- # Clamp to bounding box (which is already clamped to frame)
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
- return (
71
- (x1 + x2) / 2, # cx
72
- (y1 + y2) / 2, # cy
73
- x2 - x1, # cw
74
- y2 - y1 # ch
75
- )
 
76
 
77
  except (IndexError, TypeError, ValueError) as e:
78
- cpr_logger.error(f"Chest estimation error: {e}")
79
  return None
80
 
81
  def estimate_chest_region_weighted_avg(self, frame_width, frame_height, window_size=60, min_samples=3):
82
- """Estimate chest region using weighted average of recent parameters."""
 
 
 
 
 
 
 
 
 
 
 
 
 
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
- cpr_logger.error(f"Chest region estimation error: {e}")
125
  return None
126
 
127
  def draw_expected_chest_region(self, frame):
128
- """Draw the expected chest region on the frame."""
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 # adjust if needed
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()