def highlights_recovery_blend(RGB, multipliers, threshold=0.99): """ Performs highlights recovery using Coffin (1997) method from *dcraw*. Parameters ---------- RGB : array_like *RGB* colourspace array. multipliers : array_like Normalised camera white level or white balance multipliers. threshold : numeric, optional Threshold for the highlights selection. Returns ------- ndarray Highlights recovered *RGB* colourspace array. References ---------- .. [1] Coffin, D. (2015). dcraw. Retrieved from https://www.cybercom.net/~dcoffin/dcraw/ """ M = np.array([[1.0000000, 1.0000000, 1.0000000], [1.7320508, -1.7320508, 0.0000000], [-1.0000000, -1.0000000, 2.0000000]]) clipping_level = np.min(multipliers) * threshold Lab = dot_vector(M, RGB) Lab_c = dot_vector(M, np.minimum(RGB, clipping_level)) s = np.sum((Lab * Lab)[..., 1:3], axis=2) s_c = np.sum((Lab_c * Lab_c)[..., 1:3], axis=2) ratio = np.sqrt(s_c / s) ratio[np.logical_or(np.isnan(ratio), np.isinf(ratio))] = 1 Lab[:, :, 1:3] *= np.rollaxis(ratio[np.newaxis], 0, 3) RGB_o = dot_vector(np.linalg.inv(M), Lab) return RGB_o
def camera_space_to_RGB(RGB, XYZ_to_camera_matrix, RGB_to_XYZ_matrix): """ Converts given *RGB* array from *camera space* to given *RGB* colourspace. Parameters ---------- RGB : array_like Camera space *RGB* colourspace array. XYZ_to_camera_matrix : array_like Matrix converting from *CIE XYZ* tristimulus values to *camera space*. RGB_to_XYZ_matrix : array_like Matrix converting from *RGB* colourspace to *CIE XYZ* tristimulus values. Returns ------- ndarray *RGB* colourspace array. Examples -------- >>> RGB = np.array([0.80660, 0.81638, 0.65885]) >>> XYZ_to_camera_matrix = np.array([ ... [0.47160000, 0.06030000, -0.08300000], ... [-0.77980000, 1.54740000, 0.24800000], ... [-0.14960000, 0.19370000, 0.66510000]]) >>> RGB_to_XYZ_matrix = np.array([ ... [0.41238656, 0.35759149, 0.18045049], ... [0.21263682, 0.71518298, 0.07218020], ... [0.01933062, 0.11919716, 0.95037259]]) >>> camera_space_to_RGB( ... RGB, ... XYZ_to_camera_matrix, ... RGB_to_XYZ_matrix) # doctest: +ELLIPSIS array([ 0.7564180..., 0.8683192..., 0.6044589...]) """ M_RGB_camera = dot_matrix(XYZ_to_camera_matrix, RGB_to_XYZ_matrix) M_RGB_camera /= np.transpose(np.sum(M_RGB_camera, axis=1)[np.newaxis]) RGB_f = dot_vector(np.linalg.inv(M_RGB_camera), RGB) return RGB_f