ごはんと飲み物は紙一重

あんまり更新できてないです

html5のcanvasで書いた文字をbase64に変換して画像保存したときに透過してしまう問題

めずらしくpython以外を調べてました

uchidama.hatenablog.com

手書き文字をデモンストレーションするべく、上記のサイトを見ながらcanvasで書いた文字を、base64に変換してモデルに食わせて分類してもらうと思っていたのです。

普通に食わせる文には問題ないのですが、通常canvasで作った画像は透過する(RGBA情報をもった状態)らしく、alpha情報を保持したままbase64に保存されるらしいです。

普通に聞けば、アルファ情報を持ってくれていてありがたいのですが、これが今回の場合は罠になっており、

背景白の描画色黒だと、RGBはすべて0として保存されるみたいです(要検証)。

つまり、上記のコードを使って普通に手書き画像を生成すると、実際に描画した際の色パラメータはアルファチャンネルに保存されるわけです。

アルファチャンネルに情報を残す問題

これの何が問題なのかというと

f:id:ST_ha1cyon:20180627232947p:plain

opencvでいじろうとするときに、rgb情報に色情報はのこってないので、変換した際に真っ黒になるわけです。

そりゃそうなんですけどね。当たり前の話なんですが、この原因を突き止めるまでに時間を食いまして・・・

「描画したはずの情報がぜんぜん保存されねえ!background-colorをホワイトにしたり、canvasのcontext.fillStyleでRGB指定してるのに全然反映されない!なんでやねーん(キレ気味)」

という状態が発生するわけです。まぁそりゃRGBに値が保存されないか(ry

白黒画像をどうにか抽出するべく我々はnp.arrayの奥地へ

チャンネルの保存場所はわかったので、

アルファチャンネルのマスク情報を抽出して元の白黒画像に変換するわけです。

もともとJupyterで作業していたので、base64で抽出したRGBA画像に対して、

img_prop = []
for x in img:
    tmp = []
    for y in x:
        tmp.append(255 - y[3]) # Aの値を抽出して白黒反転
    img_prop.append(tmp)
img_prop = np.array(img_prop).astype("uint8")

マスク情報を抽出して、値を反転させてあげるわけです。そうすると。

f:id:ST_ha1cyon:20180627233540p:plain

ほら、できた。こうすればOpenCVで引き続き、手書き画像に前処理ができるようになります。

原因を解決してみて

お恥ずかしながら、この問題タイトルにキーワードガッツリ書いたのに、一つも問題がかすらない(そもそも画像の保存形式の問題)という悲しい自体に。html5さんすまねぇ。

分類モデルに通す前に一度前処理を通したかったという理由でこの問題にぶち当たったので、どうにか私と同じような「pythonしか触ったことないけどtensorflow.jsとか使ってリアルタイム手書き画像分類とかしたい」っていうコアな層の助けになってくれればと思います。

それと同時に調べながら、「フロントエンドも勉強してみたいな」と思いました。


6月28日(木) 0:17 追記 ソースに追記しました。astype("uint8")つけないと、結果がfloatになるので、opencvで画像処理できなくなる問題が発生します。気をつけよう。