指定した色のペンのセットで減色

Tweet


あらかじめ用意した種類の色鉛筆だけを使って減色するプログラムの実装例.ディザリング手法の一つである誤差拡散法(error diffusion)を使った実装です.二値画像に対するディザリングしか習ったことがないと思いますが,このソースコードのようにディザリングはカラー画像に対しても実行できます.ペンの色の数や種類の数は自由に変えられるように実装しています.

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)


入力画像


出力画像

確認のため,出力画像にガウシアンフィルタを適用すると以下のようになります.入力画像に近いことが分かると思います.


もどる