Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

common/lib/camera: Test docs #190

Merged
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions doc/source/library_reference/common/lib/camera/config.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
Base Class
==========

.. currentmodule:: opencsp.common.lib.camera.Camera

.. automodule:: opencsp.common.lib.camera.Camera
:members:
:special-members: __init__
:undoc-members:
:show-inheritance:
:member-order: groupwise

Image Acquisition Classes
=========================

.. currentmodule:: opencsp.common.lib.camera.ImageAcquisitionAbstract

.. automodule:: opencsp.common.lib.camera.ImageAcquisitionAbstract
:members:
:special-members: __init__
:undoc-members:
:show-inheritance:
:member-order: groupwise

.. currentmodule:: opencsp.common.lib.camera.ImageAcquisition_DCAM_color

.. automodule:: opencsp.common.lib.camera.ImageAcquisition_DCAM_color
:members:
:special-members: __init__
:undoc-members:
:show-inheritance:
:member-order: groupwise

UCamera Classes and Utility Functions
e10harvey marked this conversation as resolved.
Show resolved Hide resolved
=====================================

.. currentmodule:: opencsp.common.lib.camera.UCamera

.. automodule:: opencsp.common.lib.camera.UCamera
:members:
:special-members: __init__
:undoc-members:
:show-inheritance:
:member-order: groupwise

Utility Functions
=================

.. currentmodule:: opencsp.common.lib.camera.image_processing

.. automodule:: opencsp.common.lib.camera.image_processing
:members:
:special-members: __init__
:undoc-members:
:show-inheritance:
:member-order: groupwise
9 changes: 9 additions & 0 deletions doc/source/library_reference/common/lib/camera/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Camera
======

This is a collection of camera utilities for OpenCSP.

.. toctree::
:maxdepth: 1

config.rst
3 changes: 2 additions & 1 deletion doc/source/library_reference/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ This section describes the OpenCSP classes and interfaces.
app/target/index.rst
app/camera_calibration/index.rst
app/scene_reconstruction/index.rst
common/lib/cv/index.rst
common/lib/cv/index.rst
common/lib/camera/index.rst
4 changes: 2 additions & 2 deletions opencsp/app/camera_calibration/lib/calibration_camera.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def calibrate_camera(

Returns
-------
Camera : Camera
Camera : opencsp.common.lib.camera.Camera.Camera
Camera class.
r_cam_object : list[Rotation, ...]
Camera-object rotation vector
Expand Down Expand Up @@ -74,7 +74,7 @@ def view_distortion(camera: Camera, ax1: Axes, ax2: Axes, ax3: Axes, num_samps:

Parameters
----------
camera : Camera
camera : opencsp.common.lib.camera.Camera.Camera
Camera to visualize.
ax1 : Axes
Axis to plot radial distortion.
Expand Down
48 changes: 48 additions & 0 deletions opencsp/common/lib/camera/ImageAcquisition_DCAM_color.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,24 @@ def __init__(self, instance: int = 0, pixel_format: str = 'BayerRG12'):
self._shutter_cal_values = np.linspace(shutter_min, shutter_max, 2**13).astype(int)

def instance_matches(self, possible_matches: list[ImageAcquisitionAbstract]) -> bool:
"""
Determine whether this camera instance matches any instance in the provided list.
This method checks if there is another camera instance in the `possible_matches`
list that has the same `basler_index` as the current instance.
Parameters
----------
possible_matches : list[ImageAcquisitionAbstract]
A list of camera instances to check against. Each instance should be of
type `ImageAcquisitionAbstract` and may have a `basler_index` attribute.
Returns
-------
bool
True when the first matching instance is found; False otherwise.
"""
# "ChatGPT 4o-mini" assisted with generating this docstring.
for camera in possible_matches:
if not hasattr(camera, 'basler_index'):
continue
Expand All @@ -84,6 +102,35 @@ def instance_matches(self, possible_matches: list[ImageAcquisitionAbstract]) ->
return False

def get_frame(self, encode: bool = True) -> np.ndarray:
"""
Captures a single frame from the camera.
This method initiates the frame capture process and retrieves the image data
from the camera. The captured image can be returned in its raw Bayer format
or converted to an RGB format based on the `encode` parameter.
Parameters
----------
encode : bool, optional
If True (default), the captured Bayer-encoded image will be converted to
a 3D RGB image using the `encode_RG_to_RGB` function. If False, the raw
Bayer-encoded image will be returned.
Returns
-------
np.ndarray
The captured image as a NumPy array. The shape of the array will depend
on the encoding:
- If `encode` is True, the shape will be (height, width, 3) for RGB images.
- If `encode` is False, the shape will be (height, width) for Bayer images.
Raises
------
pylon.RuntimeException
If the frame grab is unsuccessful, an exception is raised indicating the
failure to capture the frame.
"""
# "ChatGPT 4o-mini" assisted with generating this docstring.
# Start frame capture
self.cap.StartGrabbingMax(1)
grabResult = self.cap.RetrieveResult(5000, pylon.TimeoutHandling_ThrowException)
Expand Down Expand Up @@ -147,6 +194,7 @@ def shutter_cal_values(self) -> np.ndarray:
return self._shutter_cal_values

def close(self):
"""Closes the camera connection"""
with et.ignored(Exception):
super().close()
with et.ignored(Exception):
Expand Down
46 changes: 46 additions & 0 deletions opencsp/common/lib/camera/ImageAcquisition_DCAM_mono.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,24 @@ def _check_pypylon_version(cls):
cls._has_checked_pypylon_version = True

def instance_matches(self, possible_matches: list[ImageAcquisitionAbstract]) -> bool:
"""
Determine whether this camera instance matches any instance in the provided list.
This method checks if there is another camera instance in the `possible_matches`
list that has the same `basler_index` as the current instance.
Parameters
----------
possible_matches : list[ImageAcquisitionAbstract]
A list of camera instances to check against. Each instance should be of
type `ImageAcquisitionAbstract` and may have a `basler_index` attribute.
Returns
-------
bool
True when the first matching instance is found; False otherwise.
"""
# "ChatGPT 4o-mini" assisted with generating this docstring.
for camera in possible_matches:
if not hasattr(camera, 'basler_index'):
continue
Expand All @@ -108,6 +126,33 @@ def instance_matches(self, possible_matches: list[ImageAcquisitionAbstract]) ->
return False

def get_frame(self) -> np.ndarray:
"""
Captures a single frame from the Basler DCAM monochromatic camera.
This method initiates the frame capture process and retrieves the image data
from the camera. The method waits for the frame to be captured and returns
the image data as a NumPy array.
Returns
-------
np.ndarray
The captured image as a NumPy array. The shape of the array will depend
on the pixel format set during initialization (e.g., Mono8, Mono12).
Raises
------
pylon.RuntimeException
If the frame grab is unsuccessful, an exception is raised indicating the
failure to capture the frame.
Notes
-----
The method calculates the expected exposure time in milliseconds and uses
this value to set a timeout for the frame retrieval. The timeout is set to
1.5 times the expected image acquisition time to ensure that the frame is
captured successfully.
"""
# "ChatGPT 4o-mini" assisted with generating this docstring.
# Start frame capture
self.cap.StartGrabbingMax(1)
exposure_time_ms = self.cap.ExposureTimeRaw.Max / 1000 # exposure time, ms
Expand Down Expand Up @@ -170,6 +215,7 @@ def shutter_cal_values(self) -> np.ndarray:
return self._shutter_cal_values

def close(self):
"""Closes the camera connection"""
with et.ignored(Exception):
super().close()
with et.ignored(Exception):
Expand Down
48 changes: 48 additions & 0 deletions opencsp/common/lib/camera/ImageAcquisition_MSMF.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,60 @@ def __init__(self, instance: int = 0):
raise IOError("Error opening webcam")

def instance_matches(self, possible_matches: list[ImageAcquisitionAbstract]) -> bool:
"""
Determine whether this camera instance matches any instance in the provided list.
This method checks if there is another instance of the `ImageAcquisition` class
in the `possible_matches` list. Since only one MSMF camera is supported,
the method returns True if any instance of `ImageAcquisition` is found; otherwise,
it returns False.
Parameters
----------
possible_matches : list[ImageAcquisitionAbstract]
A list of camera instances to check against. Each instance should be of
type `ImageAcquisitionAbstract`.
Returns
-------
bool
True if a matching instance of `ImageAcquisition` is found; False otherwise.
"""
# "ChatGPT 4o-mini" assisted with generating this docstring.
for camera in possible_matches:
if isinstance(camera, ImageAcquisition):
# only one MSMF camera is supported
return True
return False

def get_frame(self) -> np.ndarray:
"""
Captures a single frame from the connected camera.
This method reads a frame from the camera and returns it as a NumPy array.
If the captured frame is in color (3-dimensional), it is converted to a
grayscale image by averaging the color channels. The method raises an
exception if the frame capture is unsuccessful.
Returns
-------
np.ndarray
The captured image as a NumPy array. The shape of the array will be:
- (height, width) for grayscale images.
- If the input frame is in color, it will be converted to grayscale
by averaging the channels.
Raises
------
Exception
If the frame was not captured successfully, an exception is raised
indicating the failure to capture the frame.
ValueError
If the output frame does not have 2 or 3 dimensions, a ValueError
is raised indicating the incorrect number of dimensions.
"""
# "ChatGPT 4o-mini" assisted with generating this docstring.
# Capture image
ret, frame = self.cap.read()

Expand Down Expand Up @@ -90,6 +137,7 @@ def shutter_cal_values(self) -> np.ndarray:
raise ValueError('exposure_time cannot be adjusted with MSMF camera; adjust screen brightness instead.')

def close(self):
"""Closes the camera connection"""
with et.ignored(Exception):
super().close()
with et.ignored(Exception):
Expand Down
Loading
Loading