Color reduction using a set of pens

Tweet


Sample code of color reduction using a set of color pens. A program of error diffusion (dithering). Dithering can be applied not only to binary image but also to color image. You can change the color and the number of pens.

import numpy as np
import cv2
pallette=[
    [0,0,0],
    [0,0,255],
    [0,255,0],
    [0,255,255],
    [255,0,0],
    [255,0,255],
    [255,255,0],
    [255,255,255]
]
image=cv2.imread('input.bmp',cv2.IMREAD_COLOR)
image=image.astype(np.float64)
rows,cols,_=image.shape
for y in range(rows):
    for x in range(cols):
        pixel=[image[y,x,2],image[y,x,1],image[y,x,0]]
        minerror=255*255*3*2*2
        minpen=pallette[0]
        for pen in pallette:
            error=(pixel[0]-pen[0])**2+(pixel[1]-pen[1])**2+(pixel[2]-pen[2])**2
            if error<minerror:
                minerror=error
                minpen=pen
        error=[pixel[0]-minpen[0],pixel[1]-minpen[1],pixel[2]-minpen[2]]
        image[y,x,2]=minpen[0]
        image[y,x,1]=minpen[1]
        image[y,x,0]=minpen[2]
        if x<cols-1:
            image[y,x+1,2]+=7/16*error[0]
            image[y,x+1,1]+=7/16*error[1]
            image[y,x+1,0]+=7/16*error[2]
        if x>0 and y<rows-1:
            image[y+1,x-1,2]+=3/16*error[0]
            image[y+1,x-1,1]+=3/16*error[1]
            image[y+1,x-1,0]+=3/16*error[2]
        if y<rows-1:
            image[y+1,x,2]+=5/16*error[0]
            image[y+1,x,1]+=5/16*error[1]
            image[y+1,x,0]+=5/16*error[2]
        if x<cols-1 and y<rows-1:
            image[y+1,x+1,2]+=1/16*error[0]
            image[y+1,x+1,1]+=1/16*error[1]
            image[y+1,x+1,0]+=1/16*error[2]
image=np.clip(image,0,255).astype(np.uint8)
cv2.imwrite('output.bmp',image)


Input image


Output image

Gaussian smoothing the output image is as follows. It is close to the input image.


Back