From 82e2a250fcd1492e6f50c0ac1ca2b9b0b3b77a94 Mon Sep 17 00:00:00 2001 From: Richard Bowman Date: Thu, 15 Feb 2024 16:38:15 +0000 Subject: [PATCH] Include colour correction matrix and gamma in saved images I've replicated more of the camera pipeline in the images saved during scans - in particular, I've added the colour correction matrix (increases saturation) and the contrast agorithm (implements gamma correction). This slows down saving to ~0.5-2 seconds, but that's still less time than it takes to move. --- .../things/smart_scan.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/openflexure_microscope_server/things/smart_scan.py b/src/openflexure_microscope_server/things/smart_scan.py index 807e869a..3c9d3be6 100644 --- a/src/openflexure_microscope_server/things/smart_scan.py +++ b/src/openflexure_microscope_server/things/smart_scan.py @@ -12,6 +12,7 @@ from PIL import Image from pydantic import BaseModel from scipy.stats import norm from scipy.ndimage import zoom +from scipy.interpolate import interp1d from copy import deepcopy from datetime import datetime from subprocess import CompletedProcess, Popen, PIPE, SubprocessError, run @@ -554,6 +555,14 @@ class SmartScanThing(Thing): white_norm_lores = np.stack([R, G, B], axis=2) zoom_factors = [i/n for i, n in zip(rgb[...,:3].shape, white_norm_lores.shape)] white_norm = zoom(white_norm_lores, zoom_factors, order=1)[:rgb.shape[0], :rgb.shape[1], :] # Could use some work + colour_correction_matrix = np.array(cam.colour_correction_matrix).reshape((3,3)) + contrast_algorithm = cam.tuning["algorithms"][9]["rpi.contrast"] + gamma = np.array(contrast_algorithm["gamma_curve"]).reshape((-1,2)) + gamma_8bit = interp1d(gamma[:, 0]/255, gamma[:, 1]/255) + def process_raw_image(img): + normed = img/white_norm + corrected = np.dot(colour_correction_matrix, normed.reshape((-1, 3)).T).T.reshape(normed.shape) + return gamma_8bit(corrected) logger.info( f"Generated normalisation image with shape {white_norm.shape}, " f"max {white_norm.max(axis=(0,1))}, min {white_norm.min(axis=(0,1))}" @@ -579,7 +588,7 @@ class SmartScanThing(Thing): # Save the raw image np.savez(os.path.join(raw_images_folder, name + ".npz"), raw_image=raw_image, **norm_inputs) # Process it into 8 bit RGB - processed = rggb2rgb(raw2rggb(raw_image)) / white_norm + processed = process_raw_image(rggb2rgb(raw2rggb(raw_image))) processed[processed > 255] = 255 processed[processed < 0] = 0 img = Image.fromarray(processed.astype(np.uint8), mode="RGB")