Update the picamera tuning file utilities to not modify the dictionaries in place
This commit is contained in:
parent
93ff7999f5
commit
815b112069
2 changed files with 51 additions and 27 deletions
|
|
@ -730,7 +730,7 @@ class StreamingPiCamera2(BaseCamera):
|
||||||
# luminance (L), red-difference chroma (Cr), and blue-difference chroma
|
# luminance (L), red-difference chroma (Cr), and blue-difference chroma
|
||||||
# (Cb).
|
# (Cb).
|
||||||
L, Cr, Cb = recalibrate_utils.lst_from_camera(cam, self._sensor_info) # noqa: N806
|
L, Cr, Cb = recalibrate_utils.lst_from_camera(cam, self._sensor_info) # noqa: N806
|
||||||
tf_utils.set_static_lst(self.tuning, L, Cr, Cb)
|
self.tuning = tf_utils.set_static_lst(self.tuning, L, Cr, Cb)
|
||||||
|
|
||||||
# Re-initialise the picamera to reload the tuning file.
|
# Re-initialise the picamera to reload the tuning file.
|
||||||
self._initialise_picamera()
|
self._initialise_picamera()
|
||||||
|
|
@ -760,7 +760,7 @@ class StreamingPiCamera2(BaseCamera):
|
||||||
self,
|
self,
|
||||||
value: tuple[float, float, float, float, float, float, float, float, float],
|
value: tuple[float, float, float, float, float, float, float, float, float],
|
||||||
) -> None:
|
) -> None:
|
||||||
tf_utils.set_static_ccm(self.tuning, value)
|
self.tuning = tf_utils.set_static_ccm(self.tuning, value)
|
||||||
|
|
||||||
if self._picamera is not None:
|
if self._picamera is not None:
|
||||||
with self._streaming_picamera(pause_stream=True):
|
with self._streaming_picamera(pause_stream=True):
|
||||||
|
|
@ -813,7 +813,7 @@ class StreamingPiCamera2(BaseCamera):
|
||||||
A value of 0 here does nothing, a value of 65535 is maximum correction.
|
A value of 0 here does nothing, a value of 65535 is maximum correction.
|
||||||
"""
|
"""
|
||||||
with self._streaming_picamera(pause_stream=True):
|
with self._streaming_picamera(pause_stream=True):
|
||||||
tf_utils.set_static_geq(self.tuning, offset)
|
self.tuning = tf_utils.set_static_geq(self.tuning, offset)
|
||||||
self._initialise_picamera()
|
self._initialise_picamera()
|
||||||
|
|
||||||
@lt.thing_action
|
@lt.thing_action
|
||||||
|
|
@ -824,7 +824,7 @@ class StreamingPiCamera2(BaseCamera):
|
||||||
of view, causing inconsistent settings when capturing.
|
of view, causing inconsistent settings when capturing.
|
||||||
"""
|
"""
|
||||||
with self._streaming_picamera(pause_stream=True):
|
with self._streaming_picamera(pause_stream=True):
|
||||||
tf_utils.set_ce_to_disabled(self.tuning)
|
self.tuning = tf_utils.set_ce_to_disabled(self.tuning)
|
||||||
self._initialise_picamera()
|
self._initialise_picamera()
|
||||||
|
|
||||||
@lt.thing_action
|
@lt.thing_action
|
||||||
|
|
@ -863,7 +863,9 @@ class StreamingPiCamera2(BaseCamera):
|
||||||
with self._streaming_picamera(pause_stream=True):
|
with self._streaming_picamera(pause_stream=True):
|
||||||
# Generate and array of ones of the correct size for each channel
|
# Generate and array of ones of the correct size for each channel
|
||||||
flat_array = np.ones((12, 16))
|
flat_array = np.ones((12, 16))
|
||||||
tf_utils.set_static_lst(self.tuning, flat_array, flat_array, flat_array)
|
self.tuning = tf_utils.set_static_lst(
|
||||||
|
self.tuning, flat_array, flat_array, flat_array
|
||||||
|
)
|
||||||
self._initialise_picamera()
|
self._initialise_picamera()
|
||||||
|
|
||||||
@lt.thing_property
|
@lt.thing_property
|
||||||
|
|
@ -985,7 +987,7 @@ class StreamingPiCamera2(BaseCamera):
|
||||||
def lens_shading_tables(self, lst: LensShading) -> None:
|
def lens_shading_tables(self, lst: LensShading) -> None:
|
||||||
"""Set the lens shading tables."""
|
"""Set the lens shading tables."""
|
||||||
with self._streaming_picamera(pause_stream=True):
|
with self._streaming_picamera(pause_stream=True):
|
||||||
tf_utils.set_static_lst(
|
self.tuning = tf_utils.set_static_lst(
|
||||||
self.tuning,
|
self.tuning,
|
||||||
luminance=lst.luminance,
|
luminance=lst.luminance,
|
||||||
cr=lst.Cr,
|
cr=lst.Cr,
|
||||||
|
|
@ -1005,7 +1007,7 @@ class StreamingPiCamera2(BaseCamera):
|
||||||
alsc = self.get_tuning_algo("rpi.alsc")
|
alsc = self.get_tuning_algo("rpi.alsc")
|
||||||
luminance = alsc["luminance_lut"]
|
luminance = alsc["luminance_lut"]
|
||||||
flat = np.ones((12, 16))
|
flat = np.ones((12, 16))
|
||||||
tf_utils.set_static_lst(self.tuning, luminance, flat, flat)
|
self.tuning = tf_utils.set_static_lst(self.tuning, luminance, flat, flat)
|
||||||
self._initialise_picamera()
|
self._initialise_picamera()
|
||||||
|
|
||||||
@lt.thing_action
|
@lt.thing_action
|
||||||
|
|
@ -1016,7 +1018,9 @@ class StreamingPiCamera2(BaseCamera):
|
||||||
by the Raspberry Pi camera.
|
by the Raspberry Pi camera.
|
||||||
"""
|
"""
|
||||||
with self._streaming_picamera(pause_stream=True):
|
with self._streaming_picamera(pause_stream=True):
|
||||||
tf_utils.copy_alsc_section(self.default_tuning, self.tuning)
|
self.tuning = tf_utils.copy_tuning_with_alsc_section_from_other(
|
||||||
|
base_tuning_file=self.tuning, copy_alsc_from=self.default_tuning
|
||||||
|
)
|
||||||
self._initialise_picamera()
|
self._initialise_picamera()
|
||||||
|
|
||||||
@lt.thing_property
|
@lt.thing_property
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@ The functions that edit the tuning files edit them in place. This will change in
|
||||||
the future.
|
the future.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from copy import deepcopy
|
||||||
|
|
||||||
from picamera2 import Picamera2
|
from picamera2 import Picamera2
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
|
|
@ -31,16 +33,17 @@ def set_static_lst(
|
||||||
luminance: np.ndarray,
|
luminance: np.ndarray,
|
||||||
cr: np.ndarray,
|
cr: np.ndarray,
|
||||||
cb: np.ndarray,
|
cb: np.ndarray,
|
||||||
) -> None:
|
) -> dict:
|
||||||
"""Update the ``rpi.alsc`` section of a camera tuning dict to use a static correction.
|
"""Update the ``rpi.alsc`` section of a camera tuning dict to use a static correction.
|
||||||
|
|
||||||
``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.
|
adaptive tweaking by the algorithm.
|
||||||
"""
|
"""
|
||||||
|
output_tuning = deepcopy(tuning)
|
||||||
for table in luminance, cr, cb:
|
for table in luminance, cr, cb:
|
||||||
if np.array(table).shape != (12, 16):
|
if np.array(table).shape != (12, 16):
|
||||||
raise ValueError("Lens shading tables must be 12x16!")
|
raise ValueError("Lens shading tables must be 12x16!")
|
||||||
alsc = Picamera2.find_tuning_algo(tuning, "rpi.alsc")
|
alsc = Picamera2.find_tuning_algo(output_tuning, "rpi.alsc")
|
||||||
alsc["n_iter"] = 0 # disable the adaptive part
|
alsc["n_iter"] = 0 # disable the adaptive part
|
||||||
alsc["luminance_strength"] = 1.0
|
alsc["luminance_strength"] = 1.0
|
||||||
alsc["calibrations_Cr"] = [
|
alsc["calibrations_Cr"] = [
|
||||||
|
|
@ -50,6 +53,7 @@ def set_static_lst(
|
||||||
{"ct": 4500, "table": _as_flat_rounded_list(cb, round_to=3)}
|
{"ct": 4500, "table": _as_flat_rounded_list(cb, round_to=3)}
|
||||||
]
|
]
|
||||||
alsc["luminance_lut"] = _as_flat_rounded_list(luminance, round_to=3)
|
alsc["luminance_lut"] = _as_flat_rounded_list(luminance, round_to=3)
|
||||||
|
return output_tuning
|
||||||
|
|
||||||
|
|
||||||
def set_static_ccm(
|
def set_static_ccm(
|
||||||
|
|
@ -57,20 +61,22 @@ def set_static_ccm(
|
||||||
col_corr_matrix: tuple[
|
col_corr_matrix: tuple[
|
||||||
float, float, float, float, float, float, float, float, float
|
float, float, float, float, float, float, float, float, float
|
||||||
],
|
],
|
||||||
) -> None:
|
) -> dict:
|
||||||
"""Update the ``rpi.alsc`` section of a camera tuning dict to use a static correction.
|
"""Update the ``rpi.alsc`` section of a camera tuning dict to use a static correction.
|
||||||
|
|
||||||
``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.
|
adaptive tweaking by the algorithm.
|
||||||
"""
|
"""
|
||||||
ccm = Picamera2.find_tuning_algo(tuning, "rpi.ccm")
|
output_tuning = deepcopy(tuning)
|
||||||
|
ccm = Picamera2.find_tuning_algo(output_tuning, "rpi.ccm")
|
||||||
ccm["ccms"] = [{"ct": 5000, "ccm": col_corr_matrix}]
|
ccm["ccms"] = [{"ct": 5000, "ccm": col_corr_matrix}]
|
||||||
|
return output_tuning
|
||||||
|
|
||||||
|
|
||||||
def get_static_ccm(tuning: dict) -> None:
|
def get_static_ccm(tuning: dict) -> None:
|
||||||
"""Get the ``rpi.ccm`` section of a camera tuning dict."""
|
"""Get a copy of the the ``rpi.ccm`` section of a camera tuning dict."""
|
||||||
ccm = Picamera2.find_tuning_algo(tuning, "rpi.ccm")
|
ccm = Picamera2.find_tuning_algo(tuning, "rpi.ccm")
|
||||||
return ccm["ccms"]
|
return deepcopy(ccm["ccms"])
|
||||||
|
|
||||||
|
|
||||||
def lst_is_static(tuning: dict) -> bool:
|
def lst_is_static(tuning: dict) -> bool:
|
||||||
|
|
@ -82,7 +88,7 @@ def lst_is_static(tuning: dict) -> bool:
|
||||||
def set_static_geq(
|
def set_static_geq(
|
||||||
tuning: dict,
|
tuning: dict,
|
||||||
offset: int = 65535,
|
offset: int = 65535,
|
||||||
) -> None:
|
) -> dict:
|
||||||
"""Update the ``rpi.geq`` section of a camera tuning dict.
|
"""Update the ``rpi.geq`` section of a camera tuning dict.
|
||||||
|
|
||||||
:param tuning: the raspberry pi tuning file. This will be updated in-place to
|
:param tuning: the raspberry pi tuning file. This will be updated in-place to
|
||||||
|
|
@ -94,8 +100,11 @@ def set_static_geq(
|
||||||
chief ray angle compensation issue when the the stock lens is replaced by an
|
chief ray angle compensation issue when the the stock lens is replaced by an
|
||||||
objective.
|
objective.
|
||||||
"""
|
"""
|
||||||
geq = Picamera2.find_tuning_algo(tuning, "rpi.geq")
|
output_tuning = deepcopy(tuning)
|
||||||
geq["offset"] = offset # max out offset to disable the adaptive green equalisation
|
geq = Picamera2.find_tuning_algo(output_tuning, "rpi.geq")
|
||||||
|
# max out offset to disable the adaptive green equalisation
|
||||||
|
geq["offset"] = offset
|
||||||
|
return output_tuning
|
||||||
|
|
||||||
|
|
||||||
def geq_is_static(tuning: dict) -> bool:
|
def geq_is_static(tuning: dict) -> bool:
|
||||||
|
|
@ -106,14 +115,16 @@ def geq_is_static(tuning: dict) -> bool:
|
||||||
|
|
||||||
def set_ce_to_disabled(
|
def set_ce_to_disabled(
|
||||||
tuning: dict,
|
tuning: dict,
|
||||||
) -> None:
|
) -> dict:
|
||||||
"""Set ``ce_enable`` in ``rpi.contrast`` to zero to disable adaptive contrast enhancement.
|
"""Set ``ce_enable`` in ``rpi.contrast`` to zero to disable adaptive contrast enhancement.
|
||||||
|
|
||||||
:param tuning: the raspberry pi tuning file. This will be updated in-place to
|
:param tuning: The raspberry pi tuning file.
|
||||||
set ce_enable to 0.
|
:returns: A deepcopu of the input file set ce_enable to 0.
|
||||||
"""
|
"""
|
||||||
contrast = Picamera2.find_tuning_algo(tuning, "rpi.contrast")
|
output_tuning = deepcopy(tuning)
|
||||||
|
contrast = Picamera2.find_tuning_algo(output_tuning, "rpi.contrast")
|
||||||
contrast["ce_enable"] = 0
|
contrast["ce_enable"] = 0
|
||||||
|
return output_tuning
|
||||||
|
|
||||||
|
|
||||||
def ce_enable_is_static(tuning: dict) -> bool:
|
def ce_enable_is_static(tuning: dict) -> bool:
|
||||||
|
|
@ -122,16 +133,25 @@ def ce_enable_is_static(tuning: dict) -> bool:
|
||||||
return contrast["ce_enable"] == 0
|
return contrast["ce_enable"] == 0
|
||||||
|
|
||||||
|
|
||||||
def copy_alsc_section(from_tuning: dict, to_tuning: dict) -> None:
|
def copy_tuning_with_alsc_section_from_other(
|
||||||
"""Copy the ``rpi.alsc`` algorithm from one tuning to another.
|
*, base_tuning_file: dict, copy_alsc_from: dict
|
||||||
|
) -> dict:
|
||||||
|
"""Return a copy of tuning_file with the lens shading correction from another file.
|
||||||
|
|
||||||
This is done in-place, i.e. modifying to_tuning.
|
All parameters are keyword only for clarity.
|
||||||
|
|
||||||
|
:param base_tuning_file: The tuning file to copy.
|
||||||
|
:param copy_alsc_from: The tuning file to take the alsc section from.
|
||||||
|
:return: A deep copy of base_tuning_file with the alsc section copied in from the
|
||||||
|
other tuning file.
|
||||||
"""
|
"""
|
||||||
|
output_tuning = deepcopy(base_tuning_file)
|
||||||
# Using Picamera2 function to find the relevant sub-dict for each tuning file
|
# Using Picamera2 function to find the relevant sub-dict for each tuning file
|
||||||
from_i = _index_of_algorithm(from_tuning["algorithms"], "rpi.alsc")
|
from_i = _index_of_algorithm(copy_alsc_from["algorithms"], "rpi.alsc")
|
||||||
to_i = _index_of_algorithm(to_tuning["algorithms"], "rpi.alsc")
|
to_i = _index_of_algorithm(base_tuning_file["algorithms"], "rpi.alsc")
|
||||||
# Updating the dictionary in place.
|
# Updating the dictionary in place.
|
||||||
to_tuning["algorithms"][to_i] = from_tuning["algorithms"][from_i]
|
output_tuning["algorithms"][to_i] = deepcopy(copy_alsc_from["algorithms"][from_i])
|
||||||
|
return output_tuning
|
||||||
|
|
||||||
|
|
||||||
def _index_of_algorithm(algorithms: list[dict], algorithm: str) -> int:
|
def _index_of_algorithm(algorithms: list[dict], algorithm: str) -> int:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue