Restructured text fixes so that pydoctor would return without an error
This commit is contained in:
parent
58b056988a
commit
a84a916719
31 changed files with 269 additions and 256 deletions
|
|
@ -70,12 +70,12 @@ class CameraMemoryBuffer:
|
|||
every time an image is added.
|
||||
|
||||
:param image: The image to add. A PIL image is recommended, but cameras
|
||||
can choose to use other formats
|
||||
can choose to use other formats
|
||||
:param metadata: Optional, a dictionary of the image metadata.
|
||||
:param buffer_max: The maximum number of images that should be in the buffer
|
||||
once this images is added. Default is 1.
|
||||
once this images is added. Default is 1.
|
||||
|
||||
:return buffer_id: The id in the buffer for this image
|
||||
:returns: The id in the buffer for this image
|
||||
"""
|
||||
self._latest_id += 1
|
||||
self._create_space(buffer_max)
|
||||
|
|
@ -94,9 +94,8 @@ class CameraMemoryBuffer:
|
|||
|
||||
:param buffer_id: The buffer id of the image to retrieve
|
||||
:param remove: True (default) to remove this image from the buffer, False
|
||||
to leave the image in the buffer.
|
||||
to leave the image in the buffer.
|
||||
"""
|
||||
|
||||
# No id given
|
||||
if buffer_id is None:
|
||||
# Get the latest image and metadata tuple from storage
|
||||
|
|
@ -128,7 +127,7 @@ class CameraMemoryBuffer:
|
|||
Create space to add an image.
|
||||
|
||||
:param buffer_max: The maximum number of images that should be in the buffer
|
||||
once another images is added.
|
||||
once another images is added.
|
||||
"""
|
||||
# If only one image to be stored just clear the storage and return
|
||||
if buffer_max <= 1:
|
||||
|
|
@ -164,7 +163,8 @@ class BaseCamera(lt.Thing):
|
|||
self, main_resolution: tuple[int, int], buffer_count: int
|
||||
) -> None:
|
||||
"""Start (or stop and restart) the camera with the given resolution
|
||||
for the main stream, and buffer_count number of images in the buffer"""
|
||||
for the main stream, and buffer_count number of images in the buffer
|
||||
"""
|
||||
raise NotImplementedError(
|
||||
"CameraThings must define their own start_streaming method"
|
||||
)
|
||||
|
|
@ -175,9 +175,9 @@ class BaseCamera(lt.Thing):
|
|||
|
||||
This is called when uvicorn gets the a shutdown signal. As this is called from
|
||||
the event loop it cannot interact with the our ThingProperties or run
|
||||
`self.mjpeg_stream.stop()` as the portal cannot be called from this loop.
|
||||
``self.mjpeg_stream.stop()`` as the portal cannot be called from this loop.
|
||||
|
||||
Instead we just set the `_streaming` value to False. This stops the async frame
|
||||
Instead we just set the ``_streaming`` value to False. This stops the async frame
|
||||
generator when the next frame notifies.
|
||||
"""
|
||||
if self.stream_active:
|
||||
|
|
@ -186,7 +186,7 @@ class BaseCamera(lt.Thing):
|
|||
|
||||
@lt.thing_property
|
||||
def stream_active(self) -> bool:
|
||||
"Whether the MJPEG stream is active"
|
||||
"""Whether the MJPEG stream is active"""
|
||||
raise NotImplementedError(
|
||||
"CameraThings must define their own stream_active method"
|
||||
)
|
||||
|
|
@ -221,7 +221,7 @@ class BaseCamera(lt.Thing):
|
|||
) -> JPEGBlob:
|
||||
"""Acquire one image from the preview stream and return as an array
|
||||
|
||||
This differs from `capture_jpeg` in that it does not pause the MJPEG
|
||||
This differs from ``capture_jpeg`` in that it does not pause the MJPEG
|
||||
preview stream. Instead, we simply return the next frame from that
|
||||
stream (either "main" for the preview stream, or "lores" for the low
|
||||
resolution preview). No metadata is returned.
|
||||
|
|
@ -267,11 +267,11 @@ class BaseCamera(lt.Thing):
|
|||
|
||||
:param jpeg_path: The path to save the file to
|
||||
:param logger: This should be injected automatically by Labthings FastAPI
|
||||
when calling the action
|
||||
when calling the action
|
||||
:param metadata_getter: This should be injected automatically by Labthings
|
||||
FastAPI when calling the action
|
||||
FastAPI when calling the action
|
||||
:param save_resolution: can be set to resize the image before saving. By
|
||||
default this is None meaning that the image is saved at original resolution.
|
||||
default this is None meaning that the image is saved at original resolution.
|
||||
"""
|
||||
image, metadata = self._robust_image_capture(
|
||||
metadata_getter,
|
||||
|
|
@ -294,19 +294,19 @@ class BaseCamera(lt.Thing):
|
|||
buffer_max: int = 1,
|
||||
) -> None:
|
||||
"""
|
||||
Capture an image to memory. This can be saved later with `save_from_memory`
|
||||
Capture an image to memory. This can be saved later with ``save_from_memory``
|
||||
|
||||
Note that only one image is held in memory so this will overwrite any image
|
||||
in memory.
|
||||
|
||||
:param logger: This should be injected automatically by Labthings FastAPI
|
||||
when calling the action
|
||||
when calling the action
|
||||
:param metadata_getter: This should be injected automatically by Labthings
|
||||
FastAPI when calling the action
|
||||
FastAPI when calling the action
|
||||
:param buffer_max: The maximum number of images that should be in the buffer
|
||||
once this images is added. Default is 1.
|
||||
once this images is added. Default is 1.
|
||||
|
||||
:return: the buffer id of the image captured
|
||||
:returns: the buffer id of the image captured
|
||||
"""
|
||||
image, metadata = self._robust_image_capture(metadata_getter, logger)
|
||||
return self._memory_buffer.add_image(image, metadata, buffer_max=buffer_max)
|
||||
|
|
@ -324,11 +324,12 @@ class BaseCamera(lt.Thing):
|
|||
|
||||
:param jpeg_path: The path to save the file to
|
||||
:param logger: This should be injected automatically by Labthings FastAPI
|
||||
when calling the action
|
||||
when calling the action
|
||||
:param save_resolution: can be set to resize the image before saving. By
|
||||
default this is None meaning that the image is saved at original resolution.
|
||||
default this is None meaning that the image is saved at original
|
||||
resolution.
|
||||
:param buffer_id: The buffer id of the image to save, this was returned by
|
||||
`capture_to_memory`
|
||||
``capture_to_memory``
|
||||
"""
|
||||
image, metadata = self._memory_buffer.get_image(buffer_id)
|
||||
|
||||
|
|
@ -379,7 +380,8 @@ class BaseCamera(lt.Thing):
|
|||
"""Saving the captured image and metadata to disk
|
||||
logger warning (via InvocationLogger) is raised if metadata is failed to be added
|
||||
IOError is raised if the file cannot be saved
|
||||
nothing is returned on success"""
|
||||
nothing is returned on success
|
||||
"""
|
||||
if save_resolution is not None and image.size != save_resolution:
|
||||
image = image.resize(save_resolution, Image.BOX)
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
"""OpenFlexure Microscope OpenCV Camera
|
||||
|
||||
This module defines a camera Thing that uses OpenCV's
|
||||
`VideoCapture`.
|
||||
``VideoCapture``.
|
||||
|
||||
See repository root for licensing information.
|
||||
"""
|
||||
|
|
@ -45,7 +45,7 @@ class OpenCVCamera(BaseCamera):
|
|||
|
||||
@lt.thing_property
|
||||
def stream_active(self) -> bool:
|
||||
"Whether the MJPEG stream is active"
|
||||
"""Whether the MJPEG stream is active"""
|
||||
if self._capture_enabled and self._capture_thread:
|
||||
return self._capture_thread.is_alive()
|
||||
return False
|
||||
|
|
|
|||
|
|
@ -264,7 +264,6 @@ class StreamingPiCamera2(BaseCamera):
|
|||
@sensor_mode.setter
|
||||
def sensor_mode(self, new_mode: Optional[SensorModeSelector | dict]):
|
||||
"""Change the sensor mode used"""
|
||||
|
||||
if new_mode is None:
|
||||
self._sensor_mode = None
|
||||
elif isinstance(new_mode, SensorModeSelector):
|
||||
|
|
@ -287,9 +286,9 @@ class StreamingPiCamera2(BaseCamera):
|
|||
tuning = lt.ThingSetting(Optional[dict], None, readonly=True)
|
||||
|
||||
def _initialise_picamera(self):
|
||||
"""Acquire the picamera device and store it as `self._picamera`.
|
||||
"""Acquire the picamera device and store it as ``self._picamera``.
|
||||
|
||||
This duplicates logic in `Picamera2.__init__` to provide a tuning file that
|
||||
This duplicates logic in ``Picamera2.__init__`` to provide a tuning file that
|
||||
will be read when the camera system initialises.
|
||||
"""
|
||||
if self._picamera_lock is not None:
|
||||
|
|
@ -332,16 +331,17 @@ class StreamingPiCamera2(BaseCamera):
|
|||
|
||||
@contextmanager
|
||||
def _streaming_picamera(self, pause_stream=False) -> Iterator[Picamera2]:
|
||||
"""Lock access to picamera and return the underlying `Picamera2` instance.
|
||||
"""Lock access to picamera and return the underlying ``Picamera2`` instance.
|
||||
|
||||
Optionally the stream can be paused to allow updating the camera settings.
|
||||
|
||||
:param pause_stream: If False the `Picamera2` instance is simply yielded.
|
||||
If True:
|
||||
* Stop the MJPEG Stream
|
||||
* Yield the `Picamera2` instance for function calling the context manager to
|
||||
make changes.
|
||||
* On closing of the context manager the stream will restart.
|
||||
:param pause_stream: If False the ``Picamera2`` instance is simply yielded.
|
||||
If True:
|
||||
|
||||
* Stop the MJPEG Stream
|
||||
* Yield the ``Picamera2`` instance for function calling the context manager to
|
||||
make changes.
|
||||
* On closing of the context manager the stream will restart.
|
||||
"""
|
||||
already_streaming = self.stream_active
|
||||
with self._picamera_lock:
|
||||
|
|
@ -372,8 +372,9 @@ class StreamingPiCamera2(BaseCamera):
|
|||
manual.
|
||||
|
||||
Create two streams:
|
||||
- `lores_mjpeg_stream` for autofocus at low-res resolution
|
||||
- `mjpeg_stream` for preview. This is the `main_resolution` if this is less
|
||||
|
||||
* ``lores_mjpeg_stream`` for autofocus at low-res resolution
|
||||
* ``mjpeg_stream`` for preview. This is the ``main_resolution`` if this is less
|
||||
than (1280, 960), or the low-res resolution if above. This allows for
|
||||
high resolution capture without streaming high resolution video.
|
||||
|
||||
|
|
@ -489,7 +490,6 @@ class StreamingPiCamera2(BaseCamera):
|
|||
A TimeoutError is raised if this time is exceeded during capture.
|
||||
Default = 0.9s, lower than the 1s timeout default in picamera yaml settings
|
||||
"""
|
||||
|
||||
# This was slower than capture_image for our use case, but directly returning
|
||||
# an image as an array is still a useful feature
|
||||
if stream_name == "full":
|
||||
|
|
@ -523,13 +523,13 @@ class StreamingPiCamera2(BaseCamera):
|
|||
) -> JPEGBlob:
|
||||
"""Acquire one image from the camera as a JPEG
|
||||
|
||||
The JPEG will be acquired using `Picamera2.capture_file`. If the
|
||||
`resolution` parameter is `main` or `lores`, it will be captured
|
||||
The JPEG will be acquired using ``Picamera2.capture_file``. If the
|
||||
``resolution`` parameter is ``main`` or ``lores``, it will be captured
|
||||
from the main preview stream, or the low-res preview stream,
|
||||
respectively. This means the camera won't be reconfigured, and
|
||||
the stream will not pause (though it may miss one frame).
|
||||
|
||||
If `full` resolution is requested, we will briefly pause the
|
||||
If ``full`` resolution is requested, we will briefly pause the
|
||||
MJPEG stream and reconfigure the camera to capture a full
|
||||
resolution image.
|
||||
|
||||
|
|
@ -588,11 +588,12 @@ class StreamingPiCamera2(BaseCamera):
|
|||
the image reaches the specified white level.
|
||||
|
||||
:param target_white_level: The target 10bit white level. 10-bit data has a
|
||||
theoretical maximum of 1023, but with black level correction the true maxiumum
|
||||
is about 950. Default is 700 as this is approximately 70% saturated.
|
||||
theoretical maximum of 1023, but with black level correction the true
|
||||
maximum is about 950. Default is 700 as this is approximately 70%
|
||||
saturated.
|
||||
:param percentile: The percentile to use instead of maximum. Default 99.9. When
|
||||
calculating the brightest pixel, a percentile is used rather than the
|
||||
maximum in order to be robust to a small number of noisy/bright pixels.
|
||||
calculating the brightest pixel, a percentile is used rather than the
|
||||
maximum in order to be robust to a small number of noisy/bright pixels.
|
||||
"""
|
||||
with self._streaming_picamera(pause_stream=True) as cam:
|
||||
recalibrate_utils.adjust_shutter_and_gain_from_raw(
|
||||
|
|
@ -615,7 +616,7 @@ class StreamingPiCamera2(BaseCamera):
|
|||
image with the lens shading correction applied, which should mean
|
||||
that the image is uniform, rather than weighted towards the centre.
|
||||
|
||||
If `method` is `"centre"`, we will correct the mean of the central 10%
|
||||
If ``method`` is ``"centre"``, we will correct the mean of the central 10%
|
||||
of the image.
|
||||
"""
|
||||
with self._streaming_picamera(pause_stream=True) as cam:
|
||||
|
|
@ -657,7 +658,7 @@ class StreamingPiCamera2(BaseCamera):
|
|||
def colour_correction_matrix(
|
||||
self,
|
||||
) -> tuple[float, float, float, float, float, float, float, float, float]:
|
||||
"""The `colour_correction_matrix` from the tuning file.
|
||||
"""The ``colour_correction_matrix`` from the tuning file.
|
||||
|
||||
This is broken out into its own property for convenience and compatibility with
|
||||
the micromanager API
|
||||
|
|
@ -720,11 +721,11 @@ class StreamingPiCamera2(BaseCamera):
|
|||
|
||||
This function will call the other calibration actions in sequence:
|
||||
|
||||
* `flat_lens_shading` to disable flat-field
|
||||
* `auto_expose_from_minimum`
|
||||
* `set_static_green_equalisation` to set geq offset to max
|
||||
* `calibrate_lens_shading`
|
||||
* `calibrate_white_balance`
|
||||
* ``flat_lens_shading`` to disable flat-field
|
||||
* ``auto_expose_from_minimum``
|
||||
* ``set_static_green_equalisation`` to set geq offset to max
|
||||
* ``calibrate_lens_shading``
|
||||
* ``calibrate_white_balance``
|
||||
"""
|
||||
self.flat_lens_shading()
|
||||
self.auto_expose_from_minimum()
|
||||
|
|
@ -804,15 +805,15 @@ class StreamingPiCamera2(BaseCamera):
|
|||
|
||||
The white balance algorithm we use assumes the brightest pixels
|
||||
should be white, and that the only thing affecting the colour of
|
||||
said pixels is the `colour_gains`.
|
||||
said pixels is the ``colour_gains``.
|
||||
|
||||
The lens shading correction is normalised such that the *minimum*
|
||||
gain in the `Cr` and `Cb` channels is 1. The white balance
|
||||
gain in the ``Cr`` and ``Cb`` channels is 1. The white balance
|
||||
assumption above requires that the gain for the brightest pixels
|
||||
is 1. The solution might be that, when calibrating, we note which
|
||||
pixels are brightest (usually the centre) and explicitly use
|
||||
the LST values for there. However, for now I will assume that we
|
||||
need to normalise by the **maximum** of the `Cr` and `Cb`
|
||||
need to normalise by the **maximum** of the ``Cr`` and ``Cb``
|
||||
channels, which is correct the majority of the time.
|
||||
"""
|
||||
if not self.lens_shading_is_static:
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ Functions to set up a Raspberry Pi Camera v2 for scientific use
|
|||
|
||||
This module provides slower, simpler functions to set the
|
||||
gain, exposure, and white balance of a Raspberry Pi camera, using
|
||||
the `picamera2` Python library. It's mostly used by the OpenFlexure
|
||||
the ``picamera2`` Python library. It's mostly used by the OpenFlexure
|
||||
Microscope, though it deliberately has no hard dependencies on
|
||||
said software, so that it's useful on its own.
|
||||
|
||||
|
|
@ -20,14 +20,15 @@ to "memory" or nonlinearities in the camera's image processing
|
|||
pipeline, is to use raw images. This is quite slow, but very
|
||||
reliable. The three steps above can be accomplished by:
|
||||
|
||||
```
|
||||
picamera = picamera2.Picamera2()
|
||||
.. code-block:: python
|
||||
|
||||
picamera = picamera2.Picamera2()
|
||||
|
||||
adjust_shutter_and_gain_from_raw(picamera)
|
||||
adjust_white_balance_from_raw(picamera)
|
||||
lst = lst_from_camera(picamera)
|
||||
picamera.lens_shading_table = lst
|
||||
|
||||
adjust_shutter_and_gain_from_raw(picamera)
|
||||
adjust_white_balance_from_raw(picamera)
|
||||
lst = lst_from_camera(picamera)
|
||||
picamera.lens_shading_table = lst
|
||||
```
|
||||
"""
|
||||
|
||||
# Disable N806 & 803, which checks that all variables and args are lowercase.
|
||||
|
|
@ -55,7 +56,7 @@ def load_default_tuning(cam: Picamera2) -> dict:
|
|||
"""Load the default tuning file for the camera
|
||||
|
||||
This will open and close the camera to determine its model. If you are
|
||||
using a model that's supported by `picamera2` it should have a tuning
|
||||
using a model that's supported by ``picamera2`` it should have a tuning
|
||||
file built in. If not, this will probably crash with an error.
|
||||
|
||||
Error handling for unsupported cameras is not something we are likely
|
||||
|
|
@ -152,25 +153,19 @@ def adjust_shutter_and_gain_from_raw(
|
|||
This routine is slow but effective. It uses raw images, so we
|
||||
are not affected by white balance or digital gain.
|
||||
|
||||
:param camera: A Picamera2 object.
|
||||
:param target_white_level: The raw, 10-bit value we aim for. The brightest pixels
|
||||
should be approximately this bright. Maximum possible is about 900, 700 is
|
||||
reasonable.
|
||||
:param max_iterations: We will terminate once we perform this many iterations,
|
||||
whether or not we converge. More than 10 shouldn't happen.
|
||||
:param tolerance: How close to the target value we consider "done". Expressed as a
|
||||
fraction of the ``target_white_level`` so 0.05 means +/- 5%
|
||||
:param percentile: Rather then use the maximum value for each channel, we calculate
|
||||
a percentile. This makes us robust to single pixels that are bright/noisy.
|
||||
99.9% still picks the top of the brightness range, but seems much more reliable
|
||||
than just ``np.max()``.
|
||||
|
||||
Arguments:
|
||||
target_white_level:
|
||||
The raw, 10-bit value we aim for. The brightest pixels
|
||||
should be approximately this bright. Maximum possible
|
||||
is about 900, 700 is reasonable.
|
||||
max_iterations:
|
||||
We will terminate once we perform this many iterations,
|
||||
whether or not we converge. More than 10 shouldn't happen.
|
||||
tolerance:
|
||||
How close to the target value we consider "done". Expressed
|
||||
as a fraction of the ``target_white_level`` so 0.05 means
|
||||
+/- 5%
|
||||
percentile:
|
||||
Rather then use the maximum value for each channel, we
|
||||
calculate a percentile. This makes us robust to single
|
||||
pixels that are bright/noisy. 99.9% still picks the top
|
||||
of the brightness range, but seems much more reliable
|
||||
than just ``np.max()``.
|
||||
"""
|
||||
# TODO: read black level and bit depth from camera?
|
||||
if target_white_level * (tolerance + 1) >= 959:
|
||||
|
|
@ -351,7 +346,7 @@ def get_16x12_grid(chan: np.ndarray, dx: int, dy: int) -> np.ndarray:
|
|||
def upsample_channels(grids: np.ndarray, shape: tuple[int]) -> np.ndarray:
|
||||
"""Zoom an image in the last two dimensions
|
||||
|
||||
This is effectively the inverse operation of `get_16x12_grid`
|
||||
This is effectively the inverse operation of ``get_16x12_grid``
|
||||
"""
|
||||
zoom_factors = [
|
||||
1,
|
||||
|
|
@ -381,7 +376,7 @@ def downsampled_channels(channels: np.ndarray, blacklevel=64) -> list[np.ndarray
|
|||
def lst_from_channels(channels: np.ndarray) -> LensShadingTables:
|
||||
"""Given the 4 Bayer colour channels from a white image, generate a LST.
|
||||
|
||||
Internally, is just calls `downsampled_channels` and `lst_from_grids`.
|
||||
Internally, is just calls ``downsampled_channels`` and ``lst_from_grids``.
|
||||
"""
|
||||
grids = downsampled_channels(channels)
|
||||
return lst_from_grids(grids)
|
||||
|
|
@ -392,11 +387,10 @@ def lst_from_grids(grids: np.ndarray) -> LensShadingTables:
|
|||
|
||||
The grids are the 4 BAYER channels RGGB
|
||||
|
||||
The LST format has changed with `picamera2` and now uses a fixed resolution,
|
||||
The LST format has changed with ``picamera2`` and now uses a fixed resolution,
|
||||
and is in luminance, Cr, Cb format. This function returns three ndarrays of
|
||||
luminance, Cr, Cb, each with shape (12, 16).
|
||||
"""
|
||||
|
||||
# Calculated red, green, and blue channels from Bayer data
|
||||
r: np.ndarray = grids[3, ...]
|
||||
g: np.ndarray = np.mean(grids[1:3, ...], axis=0)
|
||||
|
|
@ -419,7 +413,7 @@ def grids_from_lst(lum: np.ndarray, Cr: np.ndarray, Cb: np.ndarray) -> np.ndarra
|
|||
|
||||
Note that these will be normalised - the maximum green value is always 1.
|
||||
Also, note that the channels are BGGR, to be consistent with the
|
||||
`channels_from_raw_image` function. This should probably change in the
|
||||
``channels_from_raw_image`` function. This should probably change in the
|
||||
future.
|
||||
"""
|
||||
G = 1 / np.array(lum)
|
||||
|
|
@ -434,9 +428,9 @@ def set_static_lst(
|
|||
cr: np.ndarray,
|
||||
cb: np.ndarray,
|
||||
) -> None:
|
||||
"""Update the `rpi.alsc` section of a camera tuning dict to use a static correcton.
|
||||
"""Update the ``rpi.alsc`` section of a camera tuning dict to use a static correcton.
|
||||
|
||||
`tuning` will be updated in-place to set its shading to static, and disable any
|
||||
``tuning`` will be updated in-place to set its shading to static, and disable any
|
||||
adaptive tweaking by the algorithm.
|
||||
"""
|
||||
for table in luminance, cr, cb:
|
||||
|
|
@ -459,9 +453,9 @@ def set_static_ccm(
|
|||
float, float, float, float, float, float, float, float, float
|
||||
],
|
||||
) -> None:
|
||||
"""Update the `rpi.alsc` section of a camera tuning dict to use a static correcton.
|
||||
"""Update the ``rpi.alsc`` section of a camera tuning dict to use a static correcton.
|
||||
|
||||
`tuning` will be updated in-place to set its shading to static, and disable any
|
||||
``tuning`` will be updated in-place to set its shading to static, and disable any
|
||||
adaptive tweaking by the algorithm.
|
||||
"""
|
||||
ccm = Picamera2.find_tuning_algo(tuning, "rpi.ccm")
|
||||
|
|
@ -469,7 +463,7 @@ def set_static_ccm(
|
|||
|
||||
|
||||
def get_static_ccm(tuning: dict) -> None:
|
||||
"""Get the `rpi.ccm` section of a camera tuning dict"""
|
||||
"""Get the ``rpi.ccm`` section of a camera tuning dict"""
|
||||
ccm = Picamera2.find_tuning_algo(tuning, "rpi.ccm")
|
||||
return ccm["ccms"]
|
||||
|
||||
|
|
@ -484,14 +478,13 @@ def set_static_geq(
|
|||
tuning: dict,
|
||||
offset: int = 65535,
|
||||
) -> None:
|
||||
"""Update the `rpi.geq` section of a camera tuning dict to always use green
|
||||
"""Update the ``rpi.geq`` section of a camera tuning dict to always use green
|
||||
equalisation that averages the green pixels in the red and blue rows.
|
||||
|
||||
`tuning` will be updated in-place to set the geq offest to the given value.
|
||||
``tuning`` will be updated in-place to set the geq offest to the given value.
|
||||
The default 65535 is the maximum allowed value. This means
|
||||
the brightness will always be below the threshold where averaging is used.
|
||||
"""
|
||||
|
||||
geq = Picamera2.find_tuning_algo(tuning, "rpi.geq")
|
||||
geq["offset"] = offset # max out offset to disable the adaptive green equalisation
|
||||
|
||||
|
|
@ -511,7 +504,7 @@ def index_of_algorithm(algorithms: list[dict], algorithm: str) -> int:
|
|||
|
||||
|
||||
def copy_alsc_section(from_tuning: dict, to_tuning: dict) -> None:
|
||||
"""Copy the `rpi.alsc` algorithm from one tuning to another.
|
||||
"""Copy the ``rpi.alsc`` algorithm from one tuning to another.
|
||||
|
||||
This is done in-place, i.e. modifying to_tuning.
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@ class SimulatedCamera(BaseCamera):
|
|||
|
||||
@lt.thing_property
|
||||
def stream_active(self) -> bool:
|
||||
"Whether the MJPEG stream is active"
|
||||
"""Whether the MJPEG stream is active"""
|
||||
if self._capture_enabled and self._capture_thread:
|
||||
return self._capture_thread.is_alive()
|
||||
return False
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue