【リビルド】イラストを文字列で再表現
背景
プログラマーをやっています。champayaと申します💻
最近、「身の回りのものにある関数を通したら、別の表現ができるんじゃないか?」と考えつきました。ある関数=アルゴリズムです。
個人的には、汎用性もあるし、割と面白い考えだと思っています。
それではやっていきましょう。何卒何卒。
イラスト→文字列
イラスト全体を文字列のみで再表現します。イラストの各ピクセルを文字列に置き換えるようなイメージです。
元の画像はこちら。ずとまよさんの「綺羅キラー」サムネです。
手順
以下の手順で処理します:
画像を縮小:画像を小さくして処理を軽くします。
文字を割り当て:画像の各ピクセルに、好きな文字列からランダムに文字を配置します。
色を適用:元の画像の色を文字に反映させます。
新しい画像を生成:文字で描かれた新しい画像を作成して保存します。
これで、元画像が好きな文字で描かれた画像として再表現されます。
使用するライブラリ
random:文字をランダムに選ぶため
cv2 (OpenCV):画像の読み込みやリサイズ
numpy:画像データを効率的に扱うため
PIL (Pillow):新しい画像を作成し、文字を描画
pathlib:ファイルパスの操作
argparse:コマンドライン引数の処理
import random
import cv2
import numpy as np
from PIL import Image, ImageDraw, ImageFont
import pathlib
import argparse
プログラムの流れ
1. 画像の読み込みと縮小
まず、指定した画像を読み込み、画像を縮小する関数を作ります。
def process_image(image_path, scale_factor):
# 画像ファイルを読み込む
image = cv2.imread(image_path)
# 新しい幅と高さを計算
new_width = image.shape[1] // scale_factor
new_height = image.shape[0] // scale_factor
# 画像をリサイズ
resized_image = cv2.resize(image, (new_width, new_height), interpolation=cv2.INTER_AREA)
# BGRからRGBへ変換
compressed_image_rgb = cv2.cvtColor(resized_image, cv2.COLOR_BGR2RGB)
# 画像のRGB配列を取得
rgb_array = np.array(compressed_image_rgb)
return rgb_array
2. 文字の割り当て
次に、画像の各ピクセルにランダムな文字を割り当てる関数を作ります。
def assign_random_characters(height, width, characters):
return [[random.choice(characters) for _ in range(width)] for _ in range(height)]
3. メイン処理
`main` 関数では、以下の順序で処理を実行します。
インポートするフォルダから `jpg` ファイルを取得
画像に対してランダムに文字列を割り当てる関数を実行
文字列を配置するためのベースとなる画像を作成(背景色はグレー)
フォントをロード(等幅フォントを使用してください)
文字列をベース画像に配置
アウトプット用のフォルダに `png` として保存
def main(args):
input_list = list(pathlib.Path(args.input_dir).glob("*.jpg"))
for input_path in input_list:
rgb_values = process_image(input_path, args.scale_factor)
# 画像のサイズを取得
height, width, _ = rgb_values.shape
# ランダムに文字を割り当てる
randomized_display_strings = assign_random_characters(height, width, list(args.characters))
# 画像を作成(背景をグレーに設定)
im = Image.new("RGB", (width * args.image_width_multiplier, height * args.image_height_multiplier), (200, 200, 200))
draw = ImageDraw.Draw(im)
# 日本語フォントのロード
font = ImageFont.truetype(args.font_path, args.font_size)
# 描画処理
x, y = 0, 0
for i, line in enumerate(randomized_display_strings):
for j, char in enumerate(line):
# RGB値を取得し、文字の色に設定
R, G, B = rgb_values[i, j]
color = (int(R), int(G), int(B)) # RGB値をそのまま文字の色に使用
# テキストを描画
draw.text((x + j * args.image_width_multiplier, y), char, fill=color, font=font)
y += args.font_size # 行間を含めたY座標の調整
# ファイルに出力
output_file_path = pathlib.Path(args.output_dir) / (input_path.stem + ".png")
im.save(output_file_path)
4. ファイル実行時の処理
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="画像を文字化して処理するプログラム")
# コマンドライン引数の設定
parser.add_argument('--input_dir', type=str, default="./_image_color_input", help="入力画像のディレクトリ")
parser.add_argument('--output_dir', type=str, default="./_image_color_output", help="出力画像のディレクトリ")
parser.add_argument('--font_path', type=str, default='C:/Windows/Fonts/msgothic.ttc', help="日本語フォントのパス")
parser.add_argument('--font_size', type=int, default=10, help="フォントサイズ")
parser.add_argument('--image_width_multiplier', type=int, default=10, help="文字の幅を調整する倍率")
parser.add_argument('--image_height_multiplier', type=int, default=10, help="文字の高さを調整する倍率")
parser.add_argument('--characters', type=str, default="ずっと真夜中でいいのに。", help="ランダムに使用する文字列")
parser.add_argument('--scale_factor', type=int, default=10, help="解像度を下げる値")
# 引数を解析してメイン関数を呼び出す
args = parser.parse_args()
main(args)
実際に出力された画像
よーーーーーく見てみると文字列(「ずっと真夜中でいいのに。」)で画像ができてることがわかります。
フォントサイズや解像度の調整を工夫すると、さらに繊細な画像の作成も可能です。
似たようなプログラムでモノクロ画像も作れます。
カスタマイズ可能な引数
プログラムはコマンドライン引数でさまざまな設定が可能です:
`--input_dir`:入力画像のフォルダを指定(デフォルト:`./_image_color_input`)
`--output_dir`:出力画像のフォルダを指定(デフォルト:`./_image_color_output`)
`--font_path`:使用するフォントのパス(デフォルト:`C:/Windows/Fonts/msgothic.ttc`)
`--font_size`:フォントサイズを指定(デフォルト:`10`)
`--image_width_multiplier`:文字の横方向の間隔(デフォルト:`10`)
`--image_height_multiplier`:文字の縦方向の間隔(デフォルト:`10`)
`--characters`:使用する文字列を指定(デフォルト:`"ずっと真夜中でいいのに。"`)
`--scale_factor`:画像の縮小倍率を指定(デフォルト:`10`)
まとめ
このプログラムを使えば、普段の画像を一味違ったアート作品に変身させることができます!
アルゴリズムでの再表現、これからも続けていきたいです。。。。
ぜひ、Instagramもフォローしていただけると嬉しいです!!!