diff --git a/src/openflexure_microscope_server/things/camera/picamera.py b/src/openflexure_microscope_server/things/camera/picamera.py index 95eb06e5..ff7c8867 100644 --- a/src/openflexure_microscope_server/things/camera/picamera.py +++ b/src/openflexure_microscope_server/things/camera/picamera.py @@ -163,6 +163,10 @@ class StreamingPiCamera2(BaseCamera): # a server. But we know this, so we ignore the error. pass + # Also set the colour gains based on the tuning. Set to _colour_gains to not + # trigger a NotConnectedToServerError + self._colour_gains = tf_utils.get_colour_gains_from_lst(self.tuning) + stream_resolution = lt.ThingProperty( tuple[int, int], initial_value=(820, 616), @@ -246,7 +250,7 @@ class StreamingPiCamera2(BaseCamera): with self._streaming_picamera() as cam: cam.set_controls({"ColourGains": value}) - _exposure_time: int = 0 + _exposure_time: int = 500 @lt.thing_setting def exposure_time(self) -> int: @@ -691,8 +695,7 @@ class StreamingPiCamera2(BaseCamera): # Re-initialise the picamera to reload the tuning file. self._initialise_picamera() - # Set colour gains based on the LST results - self.colour_gains = (float(np.min(Cr)), float(np.min(Cb))) + self.colour_gains = tf_utils.get_colour_gains_from_lst(self.tuning) @lt.thing_property def colour_correction_matrix( diff --git a/src/openflexure_microscope_server/things/camera/picamera_tuning_file_utils.py b/src/openflexure_microscope_server/things/camera/picamera_tuning_file_utils.py index 991296dc..6d80acd0 100644 --- a/src/openflexure_microscope_server/things/camera/picamera_tuning_file_utils.py +++ b/src/openflexure_microscope_server/things/camera/picamera_tuning_file_utils.py @@ -180,6 +180,19 @@ def get_lst(tuning: dict) -> LensShading: ) +def get_colour_gains_from_lst(tuning: dict) -> tuple[float, float]: + """Get the colour gains that are needed from the lens shading tables. + + The lens shading tables are calculated to create a white balanced image, but the + ISP normalises by the minimum Cr and Cb value. So these need to be set as colour + gains. + """ + alsc = find_tuning_algo(tuning, "rpi.alsc") + min_cr = float(min(alsc["calibrations_Cr"][0]["table"])) + min_cb = float(min(alsc["calibrations_Cb"][0]["table"])) + return (min_cr, min_cb) + + def lst_calibrated(tuning: dict) -> bool: """Whether the lens shading table is calibrated. diff --git a/src/openflexure_microscope_server/things/camera/tuning_files/vc4/README.md b/src/openflexure_microscope_server/things/camera/tuning_files/vc4/README.md index dabaafec..8554e440 100644 --- a/src/openflexure_microscope_server/things/camera/tuning_files/vc4/README.md +++ b/src/openflexure_microscope_server/things/camera/tuning_files/vc4/README.md @@ -95,6 +95,11 @@ We also set `n_iter: 0` this stops it adding iterative adaptuion. As there is only one table the colour temperature is ignored. We set the colour temperature to 1234 in the tuning file to make it clear that we have not calibrated it on the microscope. We set the colour temperature to 5000 (our actual illumination colour temperature) once recalibrated. +The tables are flat 1s for luninance on for both sensors. + +For the IMX477 (PiCamera HQ) the Cr and Cb tables are flat, but Cb is 2.0 not 1.0 for all values. This is so that the initial colour gains are set to (1.0, 2.0) + +For the IMX219 (PiCamera v2) the Cr and Cb tables are symmetric tables taken from the top quadrant of a calibrated microscope. They are used to create a good enough correction that the microscope is usable for alignment. ### rpi.contrast - Contrast diff --git a/src/openflexure_microscope_server/things/camera/tuning_files/vc4/imx219.json b/src/openflexure_microscope_server/things/camera/tuning_files/vc4/imx219.json index d92c2b24..30ddfb24 100644 --- a/src/openflexure_microscope_server/things/camera/tuning_files/vc4/imx219.json +++ b/src/openflexure_microscope_server/things/camera/tuning_files/vc4/imx219.json @@ -96,18 +96,18 @@ { "ct": 1234, "table": [ - 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, - 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, - 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, - 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, - 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, - 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, - 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, - 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, - 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, - 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, - 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, - 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 + 1.209, 1.200, 1.197, 1.189, 1.169, 1.150, 1.135, 1.128, 1.128, 1.135, 1.150, 1.169, 1.189, 1.197, 1.200, 1.209, + 1.180, 1.195, 1.216, 1.233, 1.240, 1.238, 1.235, 1.233, 1.233, 1.235, 1.238, 1.240, 1.233, 1.216, 1.195, 1.180, + 1.147, 1.175, 1.217, 1.264, 1.304, 1.324, 1.338, 1.345, 1.345, 1.338, 1.324, 1.304, 1.264, 1.217, 1.175, 1.147, + 1.110, 1.144, 1.207, 1.279, 1.346, 1.391, 1.414, 1.425, 1.425, 1.414, 1.391, 1.346, 1.279, 1.207, 1.144, 1.110, + 1.083, 1.116, 1.184, 1.278, 1.363, 1.426, 1.464, 1.473, 1.473, 1.464, 1.426, 1.363, 1.278, 1.184, 1.116, 1.083, + 1.068, 1.101, 1.170, 1.267, 1.365, 1.441, 1.485, 1.497, 1.497, 1.485, 1.441, 1.365, 1.267, 1.170, 1.101, 1.068, + 1.068, 1.101, 1.170, 1.267, 1.365, 1.441, 1.485, 1.497, 1.497, 1.485, 1.441, 1.365, 1.267, 1.170, 1.101, 1.068, + 1.083, 1.116, 1.184, 1.278, 1.363, 1.426, 1.464, 1.473, 1.473, 1.464, 1.426, 1.363, 1.278, 1.184, 1.116, 1.083, + 1.110, 1.144, 1.207, 1.279, 1.346, 1.391, 1.414, 1.425, 1.425, 1.414, 1.391, 1.346, 1.279, 1.207, 1.144, 1.110, + 1.147, 1.175, 1.217, 1.264, 1.304, 1.324, 1.338, 1.345, 1.345, 1.338, 1.324, 1.304, 1.264, 1.217, 1.175, 1.147, + 1.180, 1.195, 1.216, 1.233, 1.240, 1.238, 1.235, 1.233, 1.233, 1.235, 1.238, 1.240, 1.233, 1.216, 1.195, 1.180, + 1.209, 1.200, 1.197, 1.189, 1.169, 1.150, 1.135, 1.128, 1.128, 1.135, 1.150, 1.169, 1.189, 1.197, 1.200, 1.209 ] } ], @@ -115,18 +115,18 @@ { "ct": 1234, "table": [ - 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, - 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, - 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, - 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, - 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, - 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, - 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, - 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, - 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, - 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, - 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, - 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 + 1.318, 1.320, 1.322, 1.329, 1.330, 1.327, 1.337, 1.343, 1.343, 1.337, 1.327, 1.330, 1.329, 1.322, 1.320, 1.318, + 1.296, 1.311, 1.332, 1.357, 1.374, 1.382, 1.400, 1.421, 1.421, 1.400, 1.382, 1.374, 1.357, 1.332, 1.311, 1.296, + 1.279, 1.296, 1.334, 1.376, 1.410, 1.435, 1.462, 1.490, 1.490, 1.462, 1.435, 1.410, 1.376, 1.334, 1.296, 1.279, + 1.268, 1.284, 1.325, 1.387, 1.439, 1.471, 1.508, 1.541, 1.541, 1.508, 1.471, 1.439, 1.387, 1.325, 1.284, 1.268, + 1.259, 1.286, 1.324, 1.392, 1.457, 1.506, 1.550, 1.586, 1.586, 1.550, 1.506, 1.457, 1.392, 1.324, 1.286, 1.259, + 1.262, 1.291, 1.337, 1.398, 1.461, 1.522, 1.576, 1.617, 1.617, 1.576, 1.522, 1.461, 1.398, 1.337, 1.291, 1.262, + 1.262, 1.291, 1.337, 1.398, 1.461, 1.522, 1.576, 1.617, 1.617, 1.576, 1.522, 1.461, 1.398, 1.337, 1.291, 1.262, + 1.259, 1.286, 1.324, 1.392, 1.457, 1.506, 1.550, 1.586, 1.586, 1.550, 1.506, 1.457, 1.392, 1.324, 1.286, 1.259, + 1.268, 1.284, 1.325, 1.387, 1.439, 1.471, 1.508, 1.541, 1.541, 1.508, 1.471, 1.439, 1.387, 1.325, 1.284, 1.268, + 1.279, 1.296, 1.334, 1.376, 1.410, 1.435, 1.462, 1.490, 1.490, 1.462, 1.435, 1.410, 1.376, 1.334, 1.296, 1.279, + 1.296, 1.311, 1.332, 1.357, 1.374, 1.382, 1.400, 1.421, 1.421, 1.400, 1.382, 1.374, 1.357, 1.332, 1.311, 1.296, + 1.318, 1.320, 1.322, 1.329, 1.330, 1.327, 1.337, 1.343, 1.343, 1.337, 1.327, 1.330, 1.329, 1.322, 1.320, 1.318 ] } ], diff --git a/src/openflexure_microscope_server/things/camera/tuning_files/vc4/imx477.json b/src/openflexure_microscope_server/things/camera/tuning_files/vc4/imx477.json index e518cf07..fc85b715 100644 --- a/src/openflexure_microscope_server/things/camera/tuning_files/vc4/imx477.json +++ b/src/openflexure_microscope_server/things/camera/tuning_files/vc4/imx477.json @@ -115,18 +115,18 @@ { "ct": 1234, "table": [ - 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, - 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, - 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, - 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, - 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, - 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, - 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, - 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, - 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, - 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, - 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, - 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 + 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, + 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, + 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, + 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, + 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, + 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, + 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, + 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, + 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, + 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, + 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, + 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0 ] } ], diff --git a/tests/test_picamera_tuning_files.py b/tests/test_picamera_tuning_files.py index cb2ea8a6..c48b2380 100644 --- a/tests/test_picamera_tuning_files.py +++ b/tests/test_picamera_tuning_files.py @@ -44,7 +44,7 @@ def test_load_tuning(imx219_tuning, imx477_tuning): ("rpi.sdn", True), ("rpi.awb", True), ("rpi.agc", True), - ("rpi.alsc", True), + ("rpi.alsc", False), ("rpi.contrast", True), ("rpi.ccm", False), ("rpi.sharpen", True), @@ -124,6 +124,12 @@ def test_tuning_lst_tools(imx219_tuning, imx477_tuning): assert lst_model.colour_temp == tf_utils.DEFAULT_COLOUR_TEMP +def test_tuning_initial_colour_gains(imx219_tuning, imx477_tuning): + """The initial colour gains are as expected.""" + assert tf_utils.get_colour_gains_from_lst(imx219_tuning) == (1.068, 1.259) + assert tf_utils.get_colour_gains_from_lst(imx477_tuning) == (1.0, 2.0) + + def test_setting_lst(imx219_tuning): """Check that the LST can be set.""" lum = RNG.normal(size=(12, 16))