search
LoginSignup
3
Help us understand the problem. What are the problem?

More than 3 years have passed since last update.

posted at

updated at

Pythonで画像からアスキーアートを生成してみる

はじめに

Pythonには画像処理のライブラリとしてPILがあります。
今回はPILを使って、画像からアスキーアートを作るプログラムを雑に作ってみます。

準備

PILの基本機能を確認してみます。

from PIL import Image

Image.open('imgae.png')
img.show()

上記を実行すると、image.png がデフォルトに設定されているソフトで画像が表示されます。

image.png
今回の生贄:嫁に描いてもらったオタサーの姫

また.convert()メソッドを用いることで画像を簡単に加工できます。

gray = img.convert('L') #グレースケール化
gray.show()

gray.png
白黒になったオタサーの姫

rotate = img.rotate(90, expand=True) #90°回転
rotate.show()

rotate.png
回転したオタサーの姫

resize = img.resize((160, 128), Image.LANCZOS) #リサイズ
resize.show()

resize.png
小さくなったオタサーの姫

この .resize を使うとかんたんなモザイク加工ができる。
極端に縮小をしてから元のサイズに拡大してあげればおk

moza = img.resize([x // 32 for x in img.size]).resize(img.size)
moza.show()

moza.png
18禁になったオタサーの姫

AA化

.convert('L')によって得られるグレースケール画像は、画像の各ドットごとに0~255の値を持った配列情報を持っています。
なので、'np.array'でその中身が見えます。
多分数値が大きいほど白(薄)く、0に近いほど黒(濃)い(はず

from PIL import Image
import numpy as np

img = Image.open('image.png')
gray = img.convert('L')

gray_dot_array = np.array(gray)
print(gray_dot_array)
[[216 216 216 ... 216 216 216]
 [216 216 216 ... 216 216 216]
 [216 216 216 ... 216 216 216]
 ...
 [216 216 216 ... 216 216 216]
 [216 216 216 ... 216 216 216]
 [216 216 216 ... 216 216 216]]

配列になったオタサーの姫

各要素を255で割ってやれば0~1に正規化できるので、その値からAA化をしてみます。
要素の値の大きさによって、ドットを濃淡のある文字に置き換えて表示すれば濃淡AAの出来上がりという算段です。

from PIL import Image
import numpy as np
import tkinter as tk

root = tk.Tk()

img = Image.open('image.png')
resize = img.resize((100, 80), Image.LANCZOS) 
gray_img = resize.convert('L')

img_dot_array = np.array(gray_img)
norm_img_array = img_dot_array / 255

img_ascii = {}
img_label = {}

for i in range(0, gray_img.size[1]):
  for j in range(0, gray_img.size[0]):
      if j == 0:
          if norm_img_array[i,j] > 0.9:
              img_ascii[i] = "米"
          elif norm_img_array[i,j] > 0.8:
              img_ascii[i] = "髟"
          elif norm_img_array[i,j] > 0.7:
              img_ascii[i] = "面"
          elif norm_img_array[i,j] > 0.6:
              img_ascii[i] = "鼎"
          elif norm_img_array[i,j] > 0.5:
              img_ascii[i] = "蠻"
          elif norm_img_array[i,j] > 0.4:
              img_ascii[i] = "鬣"
          elif norm_img_array[i,j] > 0.3:
              img_ascii[i] = "麌"
          elif norm_img_array[i,j] > 0.2:
              img_ascii[i] = "黌"
          elif norm_img_array[i,j] > 0.1:
              img_ascii[i] = "鬱"
          else:
              img_ascii[i] = "䨻"
      else:
          if norm_img_array[i,j] > 0.9:
              img_ascii[i] = img_ascii[i] + "米"
          elif norm_img_array[i,j] > 0.8:
              img_ascii[i] = img_ascii[i] + "髟"
          elif norm_img_array[i,j] > 0.7:
              img_ascii[i] = img_ascii[i] + "面"
          elif norm_img_array[i,j] > 0.6:
              img_ascii[i] = img_ascii[i] + "鼎"
          elif norm_img_array[i,j] > 0.5:
              img_ascii[i] = img_ascii[i] + "蠻"
          elif norm_img_array[i,j] > 0.4:
              img_ascii[i] = img_ascii[i] + "鬣"
          elif norm_img_array[i,j] > 0.3:
              img_ascii[i] = img_ascii[i] + "麌"
          elif norm_img_array[i,j] > 0.2:
              img_ascii[i] = img_ascii[i] + "黌"
          elif norm_img_array[i,j] > 0.1:
              img_ascii[i] = img_ascii[i] + "鬱"
          else:
              img_ascii[i] = img_ascii[i] + "䨻"

for i in range(0, gray_img.size[1]):
   img_label[i] = tk.Label(text=img_ascii[i], font=(u'MSP ゴシック', 5))

for i in range(0, gray_img.size[1]):
    img_label[i].pack()

root.mainloop()

さて、上記から出来上がったのがこちら。
2019-08-12 (3).png
姫・・・?

遠くから見れば姫に見えなくもないけどよくわからないですね。。

最後に

AA職人はすごい!

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
What you can do with signing up
3
Help us understand the problem. What are the problem?