Python アスキーアートを作った

追記: 続きでは、AAの横幅が半分になる問題を解決しました。joinを使うのをやめました。

先日CERNから帰ったばかりだが、さっそく宮崎出張。飛行機が早朝のため、成田空港で夜を明かす間、Python Image Library (PIL) を使ってアスキーアートを作りました。画像やフォントサイズの仕組みなど、いい勉強になった。
参考にしたのはこちらのサイト。お世話になりました。
from PIL import Image
import os

def image2ascii(input_image):
    from PIL import Image, ImageDraw, ImageFont
    w, h = input_image.size
    character, line = "", []
    fontsize = 10
    DIV = w//fontsize
    font = ImageFont.truetype("C:/Windows/Fonts/msgothic.ttc", fontsize, encoding="utf-8")
    input_pix = input_image.load()
    output_image = Image.new("RGBA", (w, h), (255,255,255))
    draw = ImageDraw.Draw(output_image)

    for y in range(0, h, fontsize):
        line = []
        for x in range(0, w, fontsize):
            r, g, b = input_pix[x, y]
            gray = r*0.2126 + g*0.7152 + b*0.0722
            if gray > 250:
                character = " "
            elif gray > 230:
                character = "`"
            elif gray > 200:
                character = ":"
            elif gray > 175:
                character = "*"
            elif gray > 150:
                character = "+"
            elif gray > 125:
                character = "#"
            elif gray > 50:
                character = "W"
            line.append(character)
        draw.text((0, y), "".join(line), font = font, fill="#000000")
        print("".join(line), end='\n')
    return output_image

if __name__ == "__main__":
    filename='Mona_Lisa.jpg'
    input_image = Image.open(filename)
    output_image = image2ascii(input_image)
    output_image.save(os.path.splitext(filename)[0]+'_AA.png')




fontsizeを10にして画像の横幅が1920ピクセルだと、文字は横に192個並ぶことになる。同様に、縦幅が1080ピクセルだと、 文字は縦方向に108個――改行107回――並ぶことになる。このままだと縦長になってしまうので、行間を詰めるために15行目で、ステップ幅を
   for y in range(0, h, fontsize*0.8):
のように例えば0.8倍に詰めるとよいのかもしれない。試してはいない。
ちなみに、輝度は黒0 - 白255の値をとる。

数枚の画像で実験

上記コードによって画像をアスキーアートに変換したもの。
映画"Godfather II"の哀愁ただようラストシーン
真っ暗になった。画像の輝度が均一すぎたらしい。ちなみに明度と輝度は違うものらしい (参考: 画像のモノクロ化は輝度で変換しないとヒドイことになる 知らなきゃ絶対損するPCマル秘ワザ)。


映画『マトリックス』のワンシーンより
これは少しわかる。いや、わからないか。

ハイコントラストにした。参考ウェブサイトの四番目コントラストを上げるの関数にしたがって輝度を変換した。ますますわからなくなった。失敗

Leonardo da Vinciによる"Mona Lisa"。

どうしても痩せる。道路に描かれた標識のように、モニターを目元に寄せて水平にすると、まともに見える。

金閣寺 (鹿苑寺)

遠目で見るとわかるようなわからないような。


のっぺりしたものはわかりやすい。ポケモンXY攻略 最新情報の著作権なのかポケットモンスターの著作権なのかよくわからない。

テキストファイルをスクリーンショットに撮った


テキストファイルをスクリーンショットしたものはこちら。参考サイト三番目で、輝度と文字の対応を少し変えたもの。PrtScする際に、スクリーンに収まりきらなかった。



モナリザしかわからない。

フォントサイズの変更

上記に掲載したソースコードでフォントサイズを変更した実験。フォントサイズが大きい時は、まるで何か原始的な単細胞を覗いているようだが、フォントサイズが20を下回ると、ようやく認識できるようになってくる。だが、予想外の結末を迎えた。ちなみに、背景に白指定を忘れたため、どれもプレビューすると真っ暗になる。フォントサイズ4は白指定をしたので、プレビューしても見える。

フォントサイズ64

フォントサイズ48

フォントサイズ32

フォントサイズ16

フォントサイズ14

フォントサイズ12

フォントサイズ10

フォントサイズ8

フォントサイズ6


フォントサイズ4

フォントサイズ2

フォントサイズ1

最後のフォントサイズ1は何だ!?最後のフォントサイズ1は時間が20秒以上かかった気がする。字間が詰まりすぎたのだろうか、潰れている。フォントサイズ2 - 8において白い横線が走るのはなぜかわからない。フォントサイズ48あたりでは画像というよりテキストのゲシュタルトとして認識してしまう。フォントサイズ32がモナリザに見えるかどうかはともかく、画像に見えるかは人によって別れるのではないか。フォントサイズを細かくすればするほど鮮明に綺麗に映るのかと思ったが、フォントサイズ6ぐらいが最も美しく見える。サイズを細かくすると黒くなる。

きっかけ

2ちゃんねるでモナーを描くアスキーアート職人のような地道な芸当には、それほど惹かれなかった。
そんな折り、たまたま見かけた映画"THE MATRIX"をアスキーアート動画にしたものは、鮮烈な印象が残り、いつか自分も作ってみたいと思っていた。そのときの僕にとっての動画は探したら出てきた。









コメント

人気の投稿