Skip to content

Commit 9aeb31a

Browse files
authored
Merge branch 'main' into dependabot/pip/manager/django-5.2.13
2 parents b4d394d + 0411ae3 commit 9aeb31a

File tree

30 files changed

+1702
-467
lines changed

30 files changed

+1702
-467
lines changed

.github/skills/python.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,12 +147,15 @@ result = client.getScene(scene_id)
147147

148148
### Logging
149149

150+
- Use f-strings for interpolated log messages.
151+
- Do not use printf-style placeholders (for example `%s`, `%d`) in log statements.
152+
150153
```python
151154
from scene_common import log
152155

153156
log.info("Processing started")
154-
log.error("Failed to process")
155-
log.debug("Debug information")
157+
log.error(f"Failed to process scene {scene_id}")
158+
log.debug(f"Debug information: {debug_payload}")
156159
```
157160

158161
## Type Hints

controller/src/controller/detections_builder.py

Lines changed: 46 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import numpy as np
55

66
from controller.scene import TripwireEvent
7+
from scene_common import log
78
from scene_common.earth_lla import convertXYZToLLA, calculateHeading
89
from scene_common.geometry import DEFAULTZ, Point, Size
910
from scene_common.timestamp import get_iso_time
@@ -134,23 +135,53 @@ def computeCameraBounds(scene, aobj, obj_dict):
134135
camera_bounds = {}
135136
for cameraID in obj_dict['visibility']:
136137
bounds = None
137-
if aobj and len(aobj.vectors) > 0 and hasattr(aobj.vectors[0].camera, 'cameraID') \
138-
and cameraID == aobj.vectors[0].camera.cameraID:
138+
projected = False
139+
is_source_camera = (
140+
aobj and len(aobj.vectors) > 0 and hasattr(aobj.vectors[0].camera, 'cameraID')
141+
and cameraID == aobj.vectors[0].camera.cameraID
142+
)
143+
144+
# Prefer source detector pixel bbox when available. This preserves the
145+
# detector-provided 2D box instead of a reprojected estimate.
146+
if is_source_camera:
139147
bounds = getattr(aobj, 'boundingBoxPixels', None)
140-
elif scene:
148+
projected = False
149+
if bounds is None:
150+
log.debug(
151+
f"computeCameraBounds: source camera {cameraID} has no boundingBoxPixels; "
152+
"falling back to projected bounds when possible."
153+
)
154+
155+
# For non-source cameras (or source camera without pixel bbox), project
156+
# 3D/metric object state into each visible camera image plane.
157+
if bounds is None and scene:
141158
camera = scene.cameraWithID(cameraID)
142-
if camera is not None and 'bb_meters' in obj_dict:
143-
obj_translation = None
144-
obj_size = None
145-
if aobj:
146-
obj_translation = aobj.sceneLoc
147-
obj_size = aobj.bbMeters.size
148-
else:
149-
obj_translation = Point(obj_dict['translation'])
150-
obj_size = Size(obj_dict['bb_meters']['width'], obj_dict['bb_meters']['height'])
151-
bounds = camera.pose.projectEstimatedBoundsToCameraPixels(obj_translation,
152-
obj_size)
159+
if camera is None:
160+
log.debug(
161+
f"computeCameraBounds: camera {cameraID} not found in scene; cannot project bounds."
162+
)
163+
continue
164+
elif 'bb_meters' not in obj_dict and (not aobj or not hasattr(aobj, 'bbMeters') or aobj.bbMeters is None):
165+
log.debug(
166+
f"computeCameraBounds: missing bb_meters for camera {cameraID}; cannot project bounds."
167+
)
168+
continue
169+
170+
obj_translation = None
171+
obj_size = None
172+
if aobj and hasattr(aobj, 'bbMeters') and aobj.bbMeters is not None:
173+
obj_translation = aobj.sceneLoc
174+
obj_size = aobj.bbMeters.size
175+
else:
176+
obj_translation = Point(obj_dict['translation'])
177+
obj_size = Size(obj_dict['bb_meters']['width'], obj_dict['bb_meters']['height'])
178+
bounds = camera.pose.projectEstimatedBoundsToCameraPixels(obj_translation,
179+
obj_size)
180+
projected = True
181+
153182
if bounds:
154-
camera_bounds[cameraID] = bounds.asDict
183+
bound_dict = dict(bounds.asDict)
184+
bound_dict['projected'] = projected
185+
camera_bounds[cameraID] = bound_dict
155186
obj_dict['camera_bounds'] = camera_bounds
156187
return

controller/src/controller/scene.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -502,9 +502,6 @@ def _deserializeTrackedObjects(self, serialized_objects):
502502
'confidence': obj.confidence,
503503
}
504504

505-
if 'center_of_mass' in obj_data:
506-
obj.info['center_of_mass'] = obj_data['center_of_mass']
507-
508505
if 'camera_bounds' in obj_data and obj_data['camera_bounds']:
509506
obj._camera_bounds = obj_data['camera_bounds']
510507
else:

controller/src/controller/time_chunking.py

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,8 @@ def run(self):
130130
class TimeChunkedIntelLabsTracking(IntelLabsTracking):
131131
"""Time-chunked version of IntelLabsTracking."""
132132

133+
EMPTY_FRAME_CAMERA_ID = "__empty_frame__"
134+
133135
def __init__(self, max_unreliable_time, non_measurement_time_dynamic, non_measurement_time_static, time_chunking_rate_fps, suspended_track_timeout_secs=DEFAULT_SUSPENDED_TRACK_TIMEOUT_SECS, reid_config_data=None):
134136
# Call parent constructor to initialize IntelLabsTracking
135137
super().__init__(max_unreliable_time, non_measurement_time_dynamic, non_measurement_time_static, time_chunking_rate_fps, suspended_track_timeout_secs, reid_config_data)
@@ -150,18 +152,19 @@ def trackObjects(self, objects, already_tracked_objects, when, categories,
150152
# Create IntelLabs trackers if not already created
151153
self._createIlabsTrackers(categories, max_unreliable_time, non_measurement_time_dynamic, non_measurement_time_static)
152154

153-
if len(objects) == 0:
154-
return
155-
156155
if not categories:
157156
categories = self.trackers.keys()
158157

159158
# Extract camera_id from objects - required for time chunking
160-
try:
161-
camera_id = objects[0].camera.cameraID
162-
except (AttributeError, IndexError):
163-
log.warning("No camera ID found in objects, skipping time chunking processing")
164-
return
159+
if len(objects) > 0:
160+
try:
161+
camera_id = objects[0].camera.cameraID
162+
except (AttributeError, IndexError):
163+
log.warning("No camera ID found in objects, skipping time chunking processing")
164+
return
165+
else:
166+
# Keep retirement moving when a camera/category has no detections.
167+
camera_id = self.EMPTY_FRAME_CAMERA_ID
165168

166169
for category in categories:
167170
# Use time chunking

controller/src/schema/metadata.schema.json

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -90,32 +90,6 @@
9090
},
9191
"required": ["x", "y", "width", "height"]
9292
},
93-
"center_of_mass": {
94-
"title": "Center of Mass",
95-
"type": "object",
96-
"description": "Center of mass region of a detected object in pixel coordinates of a detected object in an image frame. It is a smaller bounding box that is used for determining average distance from the camera when using RealSense, for example.",
97-
"properties": {
98-
"x": {
99-
"type": "number",
100-
"description": "Number of horizontal pixels from the left side of the image to the center of mass bounding box."
101-
},
102-
"y": {
103-
"type": "number",
104-
"description": "Number of vertical pixels from the top of the image to the center of mass bounding box."
105-
},
106-
"width": {
107-
"type": "number",
108-
"description": "Horizontal width of the center of mass bounding box in pixels.",
109-
"minimum": 0
110-
},
111-
"height": {
112-
"type": "number",
113-
"description": "Vertical height of the center of mass bounding box in pixels.",
114-
"minimum": 0
115-
}
116-
},
117-
"required": ["x", "y", "width", "height"]
118-
},
11993
"semantic_metadata_attribute": {
12094
"type": "object",
12195
"title": "Semantic Metadata Attribute",
@@ -233,9 +207,6 @@
233207
"$ref": "#/definitions/semantic_metadata",
234208
"description": "Semantic metadata describing what an object is (age, gender, clothing, embedding vectors, etc)."
235209
},
236-
"center_of_mass": {
237-
"$ref": "#/definitions/center_of_mass"
238-
},
239210
"distance": {
240211
"title": "Distance to Object",
241212
"type": "number",

controller/tools/tracker/standard-tests.json

Lines changed: 0 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -576,12 +576,6 @@
576576
"width": 0.20656122377186442,
577577
"height": 0.3816131083242918
578578
},
579-
"center_of_mass": {
580-
"x": 560,
581-
"y": 75,
582-
"width": 39.333333333333336,
583-
"height": 54.5
584-
},
585579
"bounding_box_px": {
586580
"x": 521,
587581
"y": 21,
@@ -1685,12 +1679,6 @@
16851679
"width": 0.159297214942709,
16861680
"height": 0.44638230560868997
16871681
},
1688-
"center_of_mass": {
1689-
"x": 310,
1690-
"y": 149,
1691-
"width": 30.333333333333332,
1692-
"height": 63.75
1693-
},
16941682
"bounding_box_px": {
16951683
"x": 280,
16961684
"y": 86,
@@ -1708,12 +1696,6 @@
17081696
"width": 0.13128891341432058,
17091697
"height": 0.3728605140966705
17101698
},
1711-
"center_of_mass": {
1712-
"x": 488,
1713-
"y": 78,
1714-
"width": 25.0,
1715-
"height": 53.25
1716-
},
17171699
"bounding_box_px": {
17181700
"x": 463,
17191701
"y": 25,
@@ -2390,12 +2372,6 @@
23902372
"width": 0.22931796876368,
23912373
"height": 0.4516338621452628
23922374
},
2393-
"center_of_mass": {
2394-
"x": 44,
2395-
"y": 84,
2396-
"width": 43.666666666666664,
2397-
"height": 64.5
2398-
},
23992375
"bounding_box_px": {
24002376
"x": 1,
24012377
"y": 20,
@@ -3048,12 +3024,6 @@
30483024
"width": 0.20656122377186437,
30493025
"height": 0.5251556536572823
30503026
},
3051-
"center_of_mass": {
3052-
"x": 370,
3053-
"y": 203,
3054-
"width": 39.333333333333336,
3055-
"height": 75.0
3056-
},
30573027
"reid": "vTGGvSaJeL4ktus9yj24PhxMs77yXuO++DwsP4D5fzsGec49heCovX3fCD6Ffvy+pgiBvkjKHj3Yx6e9xLW0vhjOJj2SXZI+0KZkvrDs871LdMq+maQ/vZMj0b6I1LO+vhugvn8ltT70vlI9kv8PPlTbZL6uyse9VWDwvQY8SD/h0K++/t+Pvl/uzD7oR2+/sVXevXAKtb5EuZs+M4bdvmjjs74NjJK+Lg/RvvZ8Ib+7Enk+kO8Kv3xbBj5hjj69mu8+PmkmvT5JopC+PEapPQcW474gHIe+1IIqvunHJT6Yg4W+asdBPjASPD+zR7o+MsFsPobqTz/xFxc/gPLHPXh9JD3El6w9HA1ePqoRmb5SMt498kgcP3P6Nj+s7sk+17+gvB4oSz7zveu+VsdnvoAB0T5pu8k+e8nZvqS2bT4gwZ0+5AwtPxAK7TzY5C48ga15vnSVaT/N/kO+xhDcPsAALDwm5EU+rVVFP0GxS77cLrI+y6xdv8IzPz9DwpE+ip/YPZyFSj6Gq7W+rULnvrzsYT9Ypug+1ayRPjbXKL9EBFK+htnTvk5ykr6gej2/1x9KP1/sxL73D9++4HqFPP8QHT4/Iv290NtpPhoSXT7UZ7U/3nD2PRO0wb11Yqq+mIUYPzMmgT6yvAY+nskWvxnIpz7up2K+SbKWvsUHkb3dnbQ+sCzAPTtgEr7xPDS+nZHzvgA75zz6LPO+qyOmPlGYG7+KqA8+q2BQP8T26j7AnpY+UmFyPrabJT74iyq/YskaP6QoL78kKqm9bwdIvkL0y76/NCW/rPSdPmTe8T11cPK9zKu7PUzSqz28JUW/qzmxvkHsrr4AVKE+8yMnPzL0PD/ajZI+dy6TvngM5L1SioA+mJk3P3bJNj+9uyy+AfsHvLKxqT54xj4+Ij7svtTxEL8ccmQ/U5cAPyD2hT1h3yc/BTxMvif72b6EiQc+3CPDPmd16z4ek0i+q99KPnimX75tir++lzbAvLJ9UL4g/QI/Y1+4PY4kij7cZXy/HPB+Pthu076BGYG+hEkZPobQB78GrAA/GHXAPGBH0z2SVsq9vEi0PojqID+yZxa9kJ3bPnhUbj3Fima+jMgHPtDAwzwH/yG9x318vgSZNj+xxpu9zH2svgjDqz6S0BA/AqYGv+/N174Nynw+EP+WP7ZX175qwcU+mOrgPbXGXj7s+fe+bHTCvRzZnjzFOPa+juksPaybrTzdJoy+NrAGP8ezGz82U5e9nGC0Pm6zKb6/wTi9Aw3mPoosOT3q8LK+22YnP3M+F71cArg+0c7JvpzOPD+Coxi/XZ6LvqT+Nz+8Hg2/MlMMvyWV2L1utg0/L1qKPsEc6r3/aQ4+zgYyPg==",
30583028
"bounding_box_px": {
30593029
"x": 331,
@@ -3072,12 +3042,6 @@
30723042
"width": 0.1557961772516604,
30733043
"height": 0.3746110329421948
30743044
},
3075-
"center_of_mass": {
3076-
"x": 574,
3077-
"y": 62,
3078-
"width": 29.666666666666668,
3079-
"height": 53.5
3080-
},
30813045
"reid": "vTGGvSaJeL4ktus9yj24PhxMs77yXuO++DwsP4D5fzsGec49heCovX3fCD6Ffvy+pgiBvkjKHj3Yx6e9xLW0vhjOJj2SXZI+0KZkvrDs871LdMq+maQ/vZMj0b6I1LO+vhugvn8ltT70vlI9kv8PPlTbZL6uyse9VWDwvQY8SD/h0K++/t+Pvl/uzD7oR2+/sVXevXAKtb5EuZs+M4bdvmjjs74NjJK+Lg/RvvZ8Ib+7Enk+kO8Kv3xbBj5hjj69mu8+PmkmvT5JopC+PEapPQcW474gHIe+1IIqvunHJT6Yg4W+asdBPjASPD+zR7o+MsFsPobqTz/xFxc/gPLHPXh9JD3El6w9HA1ePqoRmb5SMt498kgcP3P6Nj+s7sk+17+gvB4oSz7zveu+VsdnvoAB0T5pu8k+e8nZvqS2bT4gwZ0+5AwtPxAK7TzY5C48ga15vnSVaT/N/kO+xhDcPsAALDwm5EU+rVVFP0GxS77cLrI+y6xdv8IzPz9DwpE+ip/YPZyFSj6Gq7W+rULnvrzsYT9Ypug+1ayRPjbXKL9EBFK+htnTvk5ykr6gej2/1x9KP1/sxL73D9++4HqFPP8QHT4/Iv290NtpPhoSXT7UZ7U/3nD2PRO0wb11Yqq+mIUYPzMmgT6yvAY+nskWvxnIpz7up2K+SbKWvsUHkb3dnbQ+sCzAPTtgEr7xPDS+nZHzvgA75zz6LPO+qyOmPlGYG7+KqA8+q2BQP8T26j7AnpY+UmFyPrabJT74iyq/YskaP6QoL78kKqm9bwdIvkL0y76/NCW/rPSdPmTe8T11cPK9zKu7PUzSqz28JUW/qzmxvkHsrr4AVKE+8yMnPzL0PD/ajZI+dy6TvngM5L1SioA+mJk3P3bJNj+9uyy+AfsHvLKxqT54xj4+Ij7svtTxEL8ccmQ/U5cAPyD2hT1h3yc/BTxMvif72b6EiQc+3CPDPmd16z4ek0i+q99KPnimX75tir++lzbAvLJ9UL4g/QI/Y1+4PY4kij7cZXy/HPB+Pthu076BGYG+hEkZPobQB78GrAA/GHXAPGBH0z2SVsq9vEi0PojqID+yZxa9kJ3bPnhUbj3Fima+jMgHPtDAwzwH/yG9x318vgSZNj+xxpu9zH2svgjDqz6S0BA/AqYGv+/N174Nynw+EP+WP7ZX175qwcU+mOrgPbXGXj7s+fe+bHTCvRzZnjzFOPa+juksPaybrTzdJoy+NrAGP8ezGz82U5e9nGC0Pm6zKb6/wTi9Aw3mPoosOT3q8LK+22YnP3M+F71cArg+0c7JvpzOPD+Coxi/XZ6LvqT+Nz+8Hg2/MlMMvyWV2L1utg0/L1qKPsEc6r3/aQ4+zgYyPg==",
30823046
"bounding_box_px": {
30833047
"x": 545,

dlstreamer-pipeline-server/user_scripts/gvapython/sscape/sscape_policies.py

Lines changed: 28 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,9 @@ def detectionPolicy(pobj, item, fw, fh):
1414
'category': category,
1515
'confidence': detection['confidence']
1616
})
17-
computeObjBoundingBoxParams(pobj, fw, fh, item['x'], item['y'], item['w'],item['h'],
18-
item['detection']['bounding_box']['x_min'],
19-
item['detection']['bounding_box']['y_min'],
20-
item['detection']['bounding_box']['x_max'],
21-
item['detection']['bounding_box']['y_max'])
17+
pobj.update({
18+
'bounding_box_px': {'x': item['x'], 'y': item['y'], 'width': item['w'], 'height': item['h']}
19+
})
2220
return
2321

2422
def detection3DPolicy(pobj, item, fw, fh):
@@ -27,14 +25,8 @@ def detection3DPolicy(pobj, item, fw, fh):
2725
'confidence': item['detection']['confidence'],
2826
})
2927

30-
if 'extra_params' in item:
31-
computeObjBoundingBoxParams3D(pobj, item)
32-
else:
33-
computeObjBoundingBoxParams(pobj, fw, fh, item['x'], item['y'], item['w'],item['h'],
34-
item['detection']['bounding_box']['x_min'],
35-
item['detection']['bounding_box']['y_min'],
36-
item['detection']['bounding_box']['x_max'],
37-
item['detection']['bounding_box']['y_max'])
28+
computeObjBoundingBoxParams3D(pobj, item)
29+
3830
if not ('bounding_box_px' in pobj or 'rotation' in pobj):
3931
print(f"Warning: No bounding box or rotation data found in item {item}")
4032
return
@@ -91,53 +83,29 @@ def ocrPolicy(pobj, item, fw, fh):
9183

9284
## Utility functions
9385

94-
def computeObjBoundingBoxParams(pobj, fw, fh, x, y, w, h, xminnorm=None, yminnorm=None, xmaxnorm=None, ymaxnorm=None):
95-
# use normalized bounding box for calculating center of mass
96-
xmax, xmin = int(xmaxnorm * fw), int(xminnorm * fw)
97-
ymax, ymin = int(ymaxnorm * fh), int(yminnorm * fh)
98-
comw, comh = (xmax - xmin) / 3, (ymax - ymin) / 4
99-
100-
pobj.update({
101-
'center_of_mass': {'x': int(xmin + comw), 'y': int(ymin + comh), 'width': comw, 'height': comh},
102-
'bounding_box_px': {'x': x, 'y': y, 'width': w, 'height': h}
103-
})
104-
return
105-
10686
def computeObjBoundingBoxParams3D(pobj, item):
107-
pobj.update({
108-
'translation': item['extra_params']['translation'],
109-
'rotation': item['extra_params']['rotation'],
110-
'size': item['extra_params']['dimension']
111-
})
87+
if 'extra_params' in item and all(k in item['extra_params'] for k in ['translation', 'rotation', 'dimension']):
88+
pobj.update({
89+
'translation': item['extra_params']['translation'],
90+
'rotation': item['extra_params']['rotation'],
91+
'size': item['extra_params']['dimension']
92+
})
93+
94+
x_min, y_min, z_min = pobj['translation']
95+
x_size, y_size, z_size = pobj['size']
96+
x_max, y_max, z_max = x_min + x_size, y_min + y_size, z_min + z_size
97+
98+
bbox_width = x_max - x_min
99+
bbox_height = y_max - y_min
100+
bbox_depth = z_max - z_min
101+
102+
pobj['bounding_box_3D'] = {
103+
'x': x_min,
104+
'y': y_min,
105+
'z': z_min,
106+
'width': bbox_width,
107+
'height': bbox_height,
108+
'depth': bbox_depth
109+
}
112110

113-
x_min, y_min, z_min = pobj['translation']
114-
x_size, y_size, z_size = pobj['size']
115-
x_max, y_max, z_max = x_min + x_size, y_min + y_size, z_min + z_size
116-
117-
bbox_width = x_max - x_min
118-
bbox_height = y_max - y_min
119-
bbox_depth = z_max - z_min
120-
121-
com_w, com_h, com_d = bbox_width / 3, bbox_height / 4, bbox_depth / 3
122-
123-
com_x = int(x_min + com_w)
124-
com_y = int(y_min + com_h)
125-
com_z = int(z_min + com_d)
126-
127-
pobj['bounding_box_3D'] = {
128-
'x': x_min,
129-
'y': y_min,
130-
'z': z_min,
131-
'width': bbox_width,
132-
'height': bbox_height,
133-
'depth': bbox_depth
134-
}
135-
pobj['center_of_mass'] = {
136-
'x': com_x,
137-
'y': com_y,
138-
'z': com_z,
139-
'width': com_w,
140-
'height': com_h,
141-
'depth': com_d
142-
}
143111
return

0 commit comments

Comments
 (0)