LoginSignup
5
5

More than 1 year has passed since last update.

OpenCVで写真をドット絵調にする

Last updated at Posted at 2022-12-06

概要

ドット絵とはレトロゲーム等に見られる描画方法で, 低スペックのゲーム機内でそれっぽいものを表現する手法です.
現在ではゲーム内の表現手法の一つとして確立しています.

入れた画像をドット絵調にするコードを書きました.

before

after

ドット絵の特徴

ドット絵の特徴として

  • 低画素
  • 色数が絞ってある(カラーパレット)
  • わかりやすい画調

が挙げられます.
それぞれに対し, 「画像の縮小」, 「K-means」, 「輪郭描画+ハイコントラスト」で対応させます.

プログラムの流れ

背景削除

まず用意した画像の背景を削除します.
powerpointの「背景を削除」という機能が便利で, よく使っています.
一応OpenCVにもcv2.grabCutという背景を削除する関数が用意されています.

アルファチャンネル(透過情報)込みの状態で読み込むためには

img_original = cv2.imread(PATH_IMG, -1)

とすればOKです.

低画素 - 画像の縮小

まずは, 画像を縮小させ, 画素が少ない状態にします.

img_small = cv2.resize(img, dsize=size_img)

画像がカクカクになったのがわかるかと思います.

色数を絞る - K-means

画像一枚に使われる色数を絞ります.
頻度が多い色はひとまとまりにして同じ色に上書きするイメージです.
そのようなクラスタリングを実現させるために, 教師なしクラスタリング手法の一つであるK-meansを行います.
各画素がBGRではられた3次元空間上の点とみなし, その距離の近いものにまとめます

OpenCV内にもK-meansがあるようですが, 今回はscikit-learnで色を絞っていきます.

透過度が高い箇所が悪さしないように, ちょっと複雑なコードになっています.

#透過二値変換
is_invisible = (img_small[:,:,3]<128)
img_small[is_invisible==True] = np.array([0,0,0,0],dtype=np.uint8)
img_small[:,:,3][is_invisible==False] = 255

#カラーパレット削減
pred = KMeans(n_clusters=NUMBER_PALETTE-1).fit_predict(img_small[:,:,:3][is_invisible==False])
colors = np.zeros((NUMBER_PALETTE-1,4))
for i in range(NUMBER_PALETTE-1):
    if len(img_small[is_invisible==False][pred==i])>0:
        colors[i] = np.average(img_small[is_invisible==False][pred==i],axis=0)
    else:
        colors[i] = np.array([0,0,0,0])
img_palette = img_small.copy()
img_palette[is_invisible==False] = np.array( [colors[i] for i in pred] ,dtype=np.uint8)

わかりやすい画調 - 輪郭描画・ハイコントラスト

輪郭取得はCanny法が有名で, それっぽい感じになるのでオススメ
ハイコントラストは画像の色を線形変換すればOKです.

# コントラスト
img_tmp = (img_palette[:,:,:3].astype(int)-128)*contrast+128+offset
img_tmp = (np.clip(img_tmp,0,255)+0.5).astype(np.uint8)
# 輪郭
img_canny_bgr = cv2.Canny(img_small[:,:,:3],c_min,c_max)
img_canny_a = cv2.Canny(img_small[:,:,3],c_min,c_max)
img_canny = (img_canny_bgr==255)+(img_canny_a==255)
#表示
img_res[:,:,:3] = img_tmp
img_res[img_canny] = COLOR_OUTLINE
imgShow(bool*img_res,size=4)
5
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5