Create gradient image in numpy for LUT (Look Up Tables)

Question:

What I’m trying to achieve: lookup tables to create duotone effect also called false color.

Say I have two colours: pure red and pure green provided in hex format ff0000 and 00ff00 respectively. We know its essentially (255, 0, 0) and (0, 255, 0). I need to create a 256×1 gradient image in numpy with red and green at both ends of the gradient.

I would strongly prefer to limit the dependancies to numpy and cv2.

Below is a code that works for me just fine, however all the rgb values are already hardcoded and I need to compute LUT gradient map dynamically for any given left and right colors (LUT tables truncated for brevity):

lut = np.zeros((256, 1, 3), dtype=np.uint8)

lut[:, 0, 0] = [250,248,246,244,242,240,238,236,234,232,230, ...]
lut[:, 0, 1] = [109,107,105,103,101,99,97,95,93,91,89,87,85, ...]
lut[:, 0, 2] = [127,127,127,127,127,127,127,127,127,127,127, ...]

im_color = cv2.LUT(image, lut)
Asked By: Pono

||

Answers:

From here modifying to give numpy arrays

def hex_to_rgb(hex):
     hex = hex.lstrip('#')
     hlen = len(hex)
     return np.array([int(hex[i:i+hlen//3], 16) for i in range(0, hlen, hlen//3)])

Then the numpy part:

def gradient(hex1, hex2):
    np1 = hex_to_rgb(hex1)
    np2 = hex_to_rgb(hex2)
    return np.linspace(np1[:, None], np2[:, None], 256, dtype = int)
Answered By: Daniel F

I know the question has been answered, but just want to ask the author if the code for duotone effect can be shared. I have a brute-forth solution that updates an image pixel by pixel, it works but is really inefficient. So I’m looking for a more efficient algorithm, and found this post inspiring, but haven’t figured out a working solution using the clues. @Pono, it’d be great if you can share the code to create a duotone image using any 2 colors.

Never mind, I figured it out, and share the code below in case someone else looks for the same thing.

def gradient1d(rbg1, rbg2):
    bgr1 = np.array((rbg1[2], rbg1[1], rbg1[0]))
    bgr2 = np.array((rbg2[2], rbg2[1], rbg2[0]))
    return np.linspace(bgr2, bgr1, 256, dtype = int)

def duotone(image, color1, color2):
    img = image.copy()
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    table = gradient1d(color1, color2) 
    result = np.zeros((*gray.shape,3), dtype=np.uint8)
    np.take(table, gray, axis=0, out=result)
    return result 
Answered By: Richard Shu
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.