アイドルのセトリツイートを解読してみる※あんまり上手くいってない(Python & Cloud Vision API)
はじめに
最近あまりにプログラムを書いていなかったのでアイドルさんへの欲望とちょっとした技術検証と気分転換をかねてプログラミングをしてみました。
問題意識
アイドルさんが毎回せっせとセトリツイートをしているのに、オタクはそういうものを全然読み取ろうとしていないよね?
今回やること
クマリデパートのセトリツイート画像をOCRで読み取ってセトリ情報を集める
クマリデパートとは
- 2016年結成の(若干の入れ替わりを経て今は)6人組のアイドルグループ
- アイドルっぽい曲でありながら決してチープではなく、むしろ強い
- メンバーがみんな明るいので病みツイなどでオタクを病ませることがない ☆大事
クマリデパートはライブの後にだいたいこんな感じのセトリツイートイラストがあります。(メンバー直筆)
#NPP2022 ありがとうございました❣️
— 小田アヤネ (@qumali_ayane) 2022年1月2日
年初めからたっぷりライブできて嬉しかったです~ #クマリのセトリ✌️
2️⃣0️⃣2️⃣2️⃣も笑顔沢山届けたい!
よろしくお願いします✨ pic.twitter.com/m1dolTeMUj
--
今回試したこと:これを収集してセトリ情報を整理してみましょう
環境
OS: Bigsur Python3.9.9 google-cloud-vision==2.6.3 Pillow==8.4.0 pycharmで開発
ここで学べること
今回できなかったこと
結局まともに読めなかった。
注意点
筆者はクマリデパートの曲は聴くし必要になればライブにもちょいちょい顔を出してますが、認知がないので間違っても現場で僕の名前出さないでください。
画像収集
- まずは小田アヤネさん(以降小田ちゃん)のTwitterからセトリツイート画像を収集します。
本来ならここもプログラムで収集したいところですが、正直人力で収集した方が早いのでそうします。
というわけで小田ちゃんのメディア欄を見ていきましょう
もこもこサンタさんだよ~ pic.twitter.com/mIm7oxys7d
— 小田アヤネ (@qumali_ayane) 2021年12月23日
かわいい...
ちりもつもれば大和撫子?🦊🍁 pic.twitter.com/a8zqDQedBy
— 小田アヤネ (@qumali_ayane) 2021年11月17日
神様、ありがとう
運命のいたずらでも
巡り会えたことが
幸せなの....
珍しい感じだ~🤍🤎 pic.twitter.com/KgHmIZEb8H
— 小田アヤネ (@qumali_ayane) 2021年9月18日
大人っぽいのもいいね...
小田にフリフリを着せたらこうなる…🖤 pic.twitter.com/I7gLkUwp0v
— 小田アヤネ (@qumali_ayane) 2021年6月25日
ほっぺを膨らました画像がとてもいいんですよ.....
.....
.....
オレハイッタイナニヲ....(;゚〇゚)
気を取り直して画像収集しましょう....
ということでなんとか画像が集まりました(とりあえず2021年6月〜12月まで)
画像を読み込む
pyocr
まず最初は pyocr というライブラリを使って読み込ませてみました →精度がほぼ0で使い物にならず。。
Cloud Vision API
次にgcpのサービスであるCloud vison APIを使ってみます。
設定の仕方はだいたいこの辺参照
月1000件まで無料で使えて、それ以上でも1000件ごとに1.5㌦なのであんまりお金かからないのでお得
呼び出し方
from google.cloud import vision files = glob.glob("image/*") # image配下に画像がある想定 for file in files: img = Image.open(file) enhancer = ImageEnhance.Contrast(img) # 字を読みやすくするためにコントラストを上げる img_enhanced = enhancer.enhance(2.0) # 変換した画像のbinary取得 output = io.BytesIO() img_enhanced.save(output, format='JPEG') content = output.getvalue() image = vision.Image(content=content) client = vision.ImageAnnotatorClient() response = client.document_text_detection( image=image, image_context = {'language_hints': ['ja']} )
googleのAPIを呼び出すためにはで取得したjsonのパスを環境変数に設定しますがとりあえず実行時の環境変数に追加でいいかな...
比較画像を作る
受け取った値から元の画像の隣に読み込んだ文字列だけの画像を作ってみます
最終的にできたもの
文字だけの画像の作り方
from PIL import Image, ImageEnhance, ImageDraw, ImageFont im = Image.new('RGB', (w, h), "white") draw = ImageDraw.Draw(im) # 二つ目の引数はfont size # fontのpathはMacの場合 font = ImageFont.truetype('/System/Library/Fonts/ヒラギノ明朝 ProN.ttc', 40) # ページ→ブロック→段落→文?→char? for page in response.full_text_annotation.pages: for block in page.blocks: for paragraph in block.paragraphs: for word in paragraph.words: for s in word.symbols: # 文字の四隅の位置を取得する x1 = s.bounding_box.vertices[0].x y1 = s.bounding_box.vertices[0].y x2 = s.bounding_box.vertices[2].x y2 = s.bounding_box.vertices[2].y y = y1 if y1 < y2 else y2 x = x1 if x1 < x2 else x2 draw.text(xy=(x, y), text=s.text, font=font, align="center", fill="black")
symbol.bounding_box.verticesで文字の四隅の位置情報が取れるのでとりあえず左上寄せに画像が置かれるようにします。
im2 = create_diff_image(img.width, img.height, response) # imageとim2を合体させた画像をつくる im3 = Image.new("RGB", (img.width * 2, img.height)) # 横に新たに文字だけの画像を置くので横幅を二倍にした新規画像を作る im3.paste(img, box=(0,0)) # 最初の読み込み元の画像を左側に貼り付ける im3.paste(im2, (img.width, 0)) # 上で作成したvison APIで読み込んだテキストだけの画像を貼り付けます im3.save(file.replace('image/', 'image_diff/')) # 保存するパスを image/XXX → image_diff/XXX に変更して保存する
結果
良い感じの画像と全然だめな画像の差が激しい
このくらい読んで欲しい...
めちゃくちゃ精度がいいやつ
ちなみに画像のコントラストを上げたりもしてみましたが、はっきりとした優位差はあんまり出せず(そもそも画像による?)
この先
Cloud vison APIのレスポンスには自信という項目があり、判定結果にどの程度自信があるのかという値が0〜1で帰ってくるのでその辺りをみてみたい
- 毎回API叩くとお金がかかってしまうのでCloud Vison APIのレスポンスをsqlalchemyか何かを使ってデータベースに保存したい
- 全文字読めなくてもセトリが推測がつくように文字列の距離をはかる方法を使って、正しいセトリに直してみる。(レーベンシュタイン距離など)
- なにかもっとこう違うアプローチが必要かもしれない.....
おまけ
新曲の「あみだ☆ふぉーちゅーん」が1/18に発売になるので是非聴いてみましょう!
ー 初めて知ったよ!って人にオススメの一曲(この頃はまだ4人だったんだなぁ...感慨)
ー ソースコード