Search code examples
pythonnumpyopencvcolors

How to use color science and OpenCV in Python


Here is my code using Colour to do color calibration. It uses numpy float64 type but how can I convert back to the format that is compatible in openCV, ideally uint8 because Canny only works with uint8?

import colour
import numpy as np
import cv2 

IMAGE = cv2.imread('/Users/kelsolaar/Downloads/EKcv1.jpeg')
IMAGE = cv2.cvtColor(IMAGE, cv2.COLOR_BGR2RGB)/255

# Reference values a likely non-linear 8-bit sRGB values.
# "colour.cctf_decoding" uses the sRGB EOTF by default.
REFERENCE_RGB = colour.cctf_decoding(
    np.array(
        [
            [240, 0, 22],
            [252, 222, 10],
            [30, 187, 22],
            [26, 0, 165],
        ]
    )
    / 255
)

colour.plotting.plot_multi_colour_swatches(colour.cctf_encoding(REFERENCE_RGB))

# Measured test values, the image is not properly decoded as it has a very specific ICC profile.
TEST_RGB = np.array(
    [
        [0.578, 0.0, 0.144],
        [0.895, 0.460, 0.0],
        [0.0, 0.183, 0.074],
        [0.067, 0.010, 0.070],
    ]
)
corrected = colour.colour_correction(IMAGE, REFERENCE_RGB, TEST_RGB)
colour.plotting.plot_image(
    corrected
)

This is some ways I found on stackoverflow but the image in uint8 doesn't look like the corrected image

#Method 1 which works but not uint8.....
img = cv2.cvtColor(corrected.astype(np.float32), cv2.COLOR_RGB2BGR)

# When I convert to unint8, it doesn't look like the original corrected image
# Method 2
corrected *= 255
corrected = corrected.astype(np.uint8)
img = cv2.cvtColor(corrected, cv2.COLOR_RGB2BGR)
# Method 3
img = cv2.normalize(img, None, 0, 255, cv2.NORM_MINMAX, cv2.CV_8U)
img = img.astype(np.uint8)*255

Solution

  • One more step I need to do after applying as_8_bit_BGR_image(img) is to remove those pixels that are out of range.

    def toOpenCVU8(img):
        out = img * 255
        out[out < 0] = 0
        out[out > 255] = 255
        out = cv2.cvtColor(out.astype(np.uint8), cv2.COLOR_RGB2BGR)