Color to grayscale algorithm

The technical term you’re looking for is Relative Luminance. It is a specific standard for calculating the brightness of colors as perceived by humans, with scientifically derived weights.

A rather well-illustrated Twitter/X thread on the subject.

Although the Processing algorithm for grayscale conversion (using filter(GRAY)) is not an exact implementation of relative luminance, it’s conceptually similar and a close approximation for general use (only the weights differ slightly).

For comparison, here’s what the grayscale conversion function would look like if it used perceptual precision weightings.

def relative_luminance(img):
    
    """
    Convert the image to grayscale using true relative luminance weights and bit shifting.
    Reference -> https://en.wikipedia.org/wiki/Relative_luminance
    
    """
    
    lum_img = createImage(img.width, img.height, RGB)
    
    img.loadPixels()
    lum_img.loadPixels()
    
    for i in range(len(img.pixels)):
        
        col = img.pixels[i]
        
        # Extract RGB components using bit shifts
        r = (col >> 16) & 0xff  # Red component
        g = (col >> 8) & 0xff   # Green component
        b = col & 0xff          # Blue component
        
        # Calculate the true relative luminance using scaled weights:
        # Luminance = 0.2126 * Red + 0.7152 * Green + 0.0722 * Blue
        # Approximation: 0.2126 * 256 = 54, 0.7152 * 256 = 183, 0.0722 * 256 = 18
        lum = (54 * r + 183 * g + 18 * b) >> 8  # Bit-shift by 8 (dividing by 256)
        
        # Set the grayscale pixel by combining the luminance value into RGB format
        lum_img.pixels[i] = (col & 0xff000000) | (lum << 16) | (lum << 8) | lum
    
    lum_img.updatePixels()
    
    return lum_img

grayscale

3 Likes