Wordでしきにゃんを一ノ瀬志希で表現する


はじめに

Excelで佐々木希を描く with pythonこの動画に影響を受けています
題名通り、pythonで絵を文字で表現したwordファイルを生成します。

動画の文言をそのまま使わせてもらいます。
名は体を表す」という言葉があります。ことわざとして今日まで残っているということは真であるとしてよいでしょう。
しかしその逆である「体は名を表す」という言葉はどうでしょうか?おそらくこれは真ではないですね。ある事象が真であっても逆や裏は真とは限らないのは当然のことです。

しかし、それでは非常に困ります。我々が推しているキャラであったり、担当アイドルを見せたときに「へー、可愛いね。で、誰なの?」と言われるのと「へー。可愛いね。一ノ瀬志希ちゃんって言うんだ、担当しよ」っと言われるのでは天と地の差があります。
では、「体は名を表す」ということはどのようにすれば実装できるでしょうか?これは単純なことです。ピクセルを文字で置換するだけです。
さらに「一ノ瀬志希」という文字のフォントサイズを小さくして並べることで、濃淡が表現できるのはわかるでしょうか?

つまり、適切に文字を配置してそこに色をつけてあげれば「体は名を表す」ことができるのではないでしょうか。
ということで、「体は名を表す」をpythonで実装してみました。

実行環境

python2.7
anaconda2(python2の関係)
opencv3
word2013以降(それ以前は未確認)

プログラム

pythonでWordファイルを扱うためにpython-docxを用います。そのために、以下のコマンドでインストールしてください。

pip install python-docx

実際のソースコードがこちら

shiki_word.py
# -*- coding:utf-8 -*-

import cv2
import numpy as np
from numpy.random import *

# ワード扱うライブラリのインクルード
from docx import *
from docx.shared import Pt
from docx.shared import Length
from docx.shared import Inches
from docx.shared import RGBColor

# ピクセルの値から使う文字を判定して返す
def color2string(color_ave):
    if 0 <= color_ave and color_ave < 256 * 1 / 4:
        return u"瀬"
    elif 256 * 1 / 4 <= color_ave and color_ave < 256 * 2 / 4:
        # numppyの乱数
        temp = rand()
        if temp <= 0.5:
            return u"志"
        else:
            return u"希"
    elif 256 * 2 / 4 <= color_ave and color_ave < 256 * 3 / 4:
        return u"ノ"
    elif 256 * 3 / 4 <= color_ave and color_ave <= 256:
        return u"一"


# 画像読み込み(画像サイズは320*400程度にしておく)
image = cv2.imread("shiki.jpg")
dst = cv2.imread("shiki.jpg", 0)

# ワードファイルの準備
document = Document()

# セクションのページ設定をする
sections = document.sections
section = sections[0]
section.right_margin = 1
section.left_margin = 1
section.header_distance = 1
section.footer_distance = 1

for x in range(image.shape[0]):
    # 新しい行の設定
    runs = document.add_paragraph("")
    runs_format = runs.paragraph_format
    runs_format.space_before, runs_format.space_after
    runs_format.space_before = Pt(0)
    runs_format.space_after = Pt(0)
    print(x)
    for y in range(image.shape[1]):
        # どの文字を使うかを判定する
        # 白黒画像からピクセルの値を取得する
        color_ave = dst.item(x, y)
        # 実際に文字を設置する
        runs_font = runs.add_run(color2string(color_ave)).font
        # フォントサイズの設定
        runs_font.size = Pt(1)
        # 色の設定
        red = image.item(x, y, 2)
        green = image.item(x, y, 1)
        blue = image.item(x, y, 0)
        runs_font.color.rgb = RGBColor(red, green, blue)

# ワードファイルの保存
document.save('shiki.docx')

「志」と「希」の濃さがほぼ同じだったので乱数でどちらを使用するかを乱数で選ぶようにしてます。

結果

この画像にしきにゃんが
!
このようなワードファイルになりました

拡大版

まとめ

これで、推したいキャラや担当アイドルの宣伝をするときに画像を送ると警戒されますが、 wordファイルを送ることで警戒されることなく、自然な流れで見せることができます!

補足

画像サイズについて

今回の画像サイズは320×400程度まで画像サイズを縮小しています。これは画像サイズが大きすぎると横列の文字が1列で表現できなくなるため、大きく崩れてしまいます。

別のキャラでやる時の注意点は?

color2string内の返り値を変更すれば問題ないと思います。上から順に濃い文字にしています。

さいごに

一ノ瀬志希をよろしくお願いします!!