はじめに
先日、ASCII Cameraという面白いサイトを見つけました。
こんな風に、ブラウザからカメラ映像を取得してASCII文字列に変換してくれます。
このぐらいだったらもしかして自分で作れるんじゃないかと思ったので、画像をアスキーアートに変換するプログラムを作ってみることにしました。
仕組み
仕組みとしては、以下のようになります。
- 画像をグレースケールに変換する
- 各ピクセルの色の濃さを取得し、それに応じて文字を決定する
- 列ごとに改行する
PythonとOpenCVを使えばこれらの処理をかなり簡単に行えます。
グレースケールに変換
読み込む画像のパスはinputで取得するようにします。
これでグレースケールに変換され、grayには各ピクセルの濃度(0~255)が格納されます。
import cv2
imgpath = input("Path: ")
img = cv2.imread(imgpath)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ASCII文字を決定する
各ピクセルの濃度(0~255)ごとにASCII文字を決定する必要がありますが、実際に使えるASCII文字は256個もありません。
仕方がないので、使う文字を64個に厳選し、濃度を4ごとに区切って文字を選ぶことにしました。
例えば濃度が0~3なら「M」、252~255なら「 (空白)」、といった具合です。
以下が「濃度が高い」順番に並べた64個の文字です。
MWN$@%#&B89EGA6mK5HRkbYT43V0JL7gpaseyxznocv?jIftr1li*=-~^`':;,.
この順番を決めるのがけっこう大変でした。
順番は見た目で決めただけなので、超適当です。
変換処理はこんな感じになりました。
colorset = "MWN$@%#&B89EGA6mK5HRkbYT43V0JL7gpaseyxznocv?jIftr1li*=-~^`':;,. "
for gray2 in gray:
output += "\n"
for dark in gray2:
output += colorset[dark // 4] * 2
濃度を4で割って切り捨てることで、ちょうどよくcolorsetのインデックスを取得できます。
ASCII文字の縦横比は2:1なので、書き込む文字を2倍にしています。
完成
完成したプログラムはこんな感じです。
結果はファイルに出力する形式にしました。
import cv2
colorset = "MWN$@%#&B89EGA6mK5HRkbYT43V0JL7gpaseyxznocv?jIftr1li*=-~^`':;,. "
imgpath = input("Path:")
img = cv2.imread(imgpath)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
output = ""
for gray2 in gray:
output += "\n"
for dark in gray2:
output += colorset[dark // 4] * 2
with open("output.txt", mode="w") as f:
f.write(output)
試しに私のアイコン(これ↓)を変換してみます。
結果は...
こんな感じ。
意外とちゃんと変換できていてびっくりしました。
次に、ぱくたそ様から頂いたイギリス北部の自然風景のフリー画像を、300×200pxに変換したもので試してみます。
結果は...
最後に、This person does not existという、AIが顔写真を自動生成してくれるサイトで入手した、
この画像を250×250pxに変換して実行してみます。
結果は...
かなりいい感じですね!
これは良い...頑張った甲斐があった...
おわりに
という訳で、たった12行のコードで実現できてしまいました。
今回初めてOpenCVに触れたのですが、こんなに便利だとは思いませんでした。
これと同じことを256文字のUnicodeでやってみるのも面白いかもしれません。