Skip to content

Commit a4345b1

Browse files
committed
Track actual pixel/output formats in camera backends
Expose actual_pixel_format and actual_output_format across backends and track the camera-reported formats for UI/telemetry. Aravis: add actual_pixel_format/actual_output_format properties and record _camera_pixel_format when setting pixel format. GenTL: initialize _camera_pixel_format/_actual_output_format, add _output_format_for_frame to infer output format from numpy frames, populate _actual_output_format on read, and record detected camera pixel format in several places. OpenCV: add actual_pixel_format (None) and actual_output_format (BGR8). These changes provide a consistent way to report native and emitted pixel formats to callers.
1 parent 1b5a8af commit a4345b1

3 files changed

Lines changed: 60 additions & 0 deletions

File tree

dlclivegui/cameras/backends/aravis_backend.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,16 @@ def actual_fps(self) -> float | None:
6969
"""Return the actual frame rate of the camera after opening."""
7070
return self._actual_fps
7171

72+
@property
73+
def actual_pixel_format(self) -> str | None:
74+
"""Camera/native pixel format requested/reported for Aravis."""
75+
return self._camera_pixel_format or self._pixel_format
76+
77+
@property
78+
def actual_output_format(self) -> str | None:
79+
"""Current Aravis backend emits BGR uint8 frames."""
80+
return self._actual_output_format or "BGR8"
81+
7282
@classmethod
7383
def is_available(cls) -> bool:
7484
"""Check if Aravis is available on this system."""
@@ -615,10 +625,12 @@ def _configure_pixel_format(self) -> None:
615625

616626
if self._pixel_format in format_map:
617627
self._camera.set_pixel_format(format_map[self._pixel_format])
628+
self._camera_pixel_format = self._pixel_format
618629
LOG.info(f"Pixel format set to '{self._pixel_format}'")
619630
else:
620631
# Try setting as string
621632
self._camera.set_pixel_format_from_string(self._pixel_format)
633+
self._camera_pixel_format = self._pixel_format
622634
LOG.info(f"Pixel format set to '{self._pixel_format}' (from string)")
623635
except Exception as e:
624636
LOG.warning(f"Failed to set pixel format '{self._pixel_format}': {e}")

dlclivegui/cameras/backends/gentl_backend.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,9 @@ def __init__(self, settings):
9999

100100
self._pixel_format: str = ns.get("pixel_format") or props.get("pixel_format", "auto")
101101
self._pixel_format = str(self._pixel_format).strip()
102+
self._camera_pixel_format: str | None = None
103+
self._actual_output_format: str | None = None
104+
102105
self._rotate: int = int(ns.get("rotate", props.get("rotate", 0))) % 360
103106
self._crop: tuple[int, int, int, int] | None = self._parse_crop(ns.get("crop", props.get("crop")))
104107

@@ -176,6 +179,16 @@ def actual_exposure(self) -> float | None:
176179
def actual_gain(self) -> float | None:
177180
return self._actual_gain
178181

182+
@property
183+
def actual_pixel_format(self) -> str | None:
184+
"""Camera/native pixel format selected on the GenICam PixelFormat node."""
185+
return self._camera_pixel_format or (self._pixel_format if self._pixel_format != "auto" else None)
186+
187+
@property
188+
def actual_output_format(self) -> str | None:
189+
"""Current GenTL backend emits OpenCV-native BGR uint8 frames."""
190+
return self._actual_output_format or "BGR8"
191+
179192
@classmethod
180193
def is_available(cls) -> bool:
181194
return Harvester is not None
@@ -587,6 +600,21 @@ def waits_for_hardware_trigger(self) -> bool:
587600
role = str(self._trigger_attr(getattr(self, "_trigger", None), "role", "off") or "off").lower()
588601
return role in {"external", "follower"}
589602

603+
@staticmethod
604+
def _output_format_for_frame(frame: np.ndarray) -> str:
605+
if frame.ndim == 2:
606+
if frame.dtype == np.uint8:
607+
return "Mono8"
608+
return f"Mono{frame.dtype}"
609+
if frame.ndim == 3:
610+
channels = frame.shape[2]
611+
if channels == 3 and frame.dtype == np.uint8:
612+
return "BGR8"
613+
if channels == 4 and frame.dtype == np.uint8:
614+
return "BGRA8"
615+
return f"{channels}ch-{frame.dtype}"
616+
return str(frame.dtype)
617+
590618
def read(self) -> tuple[np.ndarray, float]:
591619
if self._acquirer is None:
592620
raise RuntimeError("GenTL image acquirer not initialised")
@@ -625,6 +653,7 @@ def read(self) -> tuple[np.ndarray, float]:
625653
self._read_telemetry(self._acquirer.remote_device.node_map)
626654
except Exception:
627655
pass
656+
self._actual_output_format = self._output_format_for_frame(frame)
628657

629658
return frame, timestamp
630659

@@ -1312,11 +1341,14 @@ def _configure_pixel_format(self, node_map) -> None:
13121341

13131342
pixel_format_node.value = selected
13141343
self._pixel_format = str(pixel_format_node.value)
1344+
self._actual_pixel_format = self._pixel_format
13151345

13161346
LOG.debug("GenTL pixel format selected: %s", self._pixel_format)
13171347

13181348
except Exception as e:
13191349
LOG.warning("Failed to configure pixel format '%s': %s", self._pixel_format, e)
1350+
if self._pixel_format and self._pixel_format.lower() != "auto":
1351+
self._camera_pixel_format = self._pixel_format
13201352

13211353
def _configure_trigger(self, node_map) -> None:
13221354
cfg = self._trigger
@@ -1783,7 +1815,13 @@ def _read_telemetry(self, node_map) -> None:
17831815

17841816
pixel_format = self._node_str(node_map, "PixelFormat")
17851817
if pixel_format is not None:
1818+
self._camera_pixel_format = pixel_format
17861819
ns["actual_pixel_format"] = pixel_format
1820+
ns["detected_pixel_format"] = pixel_format
1821+
1822+
output_format = self.actual_output_format
1823+
if output_format is not None:
1824+
ns["actual_output_format"] = output_format
17871825

17881826
except Exception:
17891827
pass

dlclivegui/cameras/backends/opencv_backend.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,16 @@ def actual_gain(self) -> None:
254254
"""Not supported by OpenCV backend."""
255255
return None
256256

257+
@property
258+
def actual_pixel_format(self) -> str | None:
259+
"""OpenCV does not reliably expose native camera pixel format."""
260+
return None
261+
262+
@property
263+
def actual_output_format(self) -> str | None:
264+
"""OpenCV VideoCapture returns BGR frames in this backend."""
265+
return "BGR8"
266+
257267
# ----------------------------
258268
# Internal helpers
259269
# ----------------------------

0 commit comments

Comments
 (0)