下町柚子黄昏記 by @yuzutas0

したまち発・ゆずたそ作・個人開発の瓦礫の記録

ニコニコ学会データ研究会に参加しました&モザイク画生成スクリプトを作りました

ニコニコ学会データ研究会というイベントに招待いただき、セッション3「数学」で発表を行いました。

f:id:yuzutas0:20160330215626j:plain

どんなイベントか

Peatixのイベント紹介ページによると

データ研究会は「データ分析を始めたい人」「データ分析を仕事にしている人」「面白い発表が好きな人」などなど、誰でも参加できる気軽な研究会です。 ...... (中略) ...... データで面白ければ節操のない研究会です。最近は夏コミで薄い本「ニコ知能」も上梓し、データおもしろがり分野のエッジをひた走っています。

とのことです。

他の参加者のブログ・スライド

多種多様な方々が登壇して、普段なかなか接する機会のない魅力的な話を聴けました。

参加のいきさつ

  • 昨夏にはニコニコ学会、昨秋には日曜数学会(=趣味で数学をする人たちの集まり)、それぞれのイベントに参加しました。そこでのご縁からお声掛けいただきました。
  • 100人以上のデータサイエンティストの前で立派な話をする自信はありませんでしたが、せっかくなので恥をかいて勉強しよう!という気概で参加しました。

yuzutas0.hatenablog.com

yuzutas0.hatenablog.com

どんな話をしてきたか

こちらが当日の発表資料になります。

苦労話

当日は時間の都合で省略しましたが、実装上の苦労について、この場で振り返りたいと思います。

画像サイズ

特に1番苦労したのは画像のサイズです。 最終的に完成したモザイク画は160MBにもなってしまいました。

サイズが大きくなった理由

  • 今回使った対象画像(target_image)のサイズは 200 pixel x 200 pixel です。
    • いくつかサイズを試してみて、これが荒すぎないギリギリでした。
    • これより小さいと最終出力がただのモザイクになってしまいます。
  • 同様に、要素画像群(element_images)は 100 pixel x 100 pixel です。
    • モザイク画を拡大したときに1つ1つの画像が潰れないギリギリでした。
    • 個々の画像が判別できないと、プレゼンの魅力が半減します。
  • 上記を組み合わせると 20,000 pixel x 20,000 pixel となります。
    • ラップトップで1人で楽しむなら縮小余地があるのですが、大画面での発表を想定するとこれが最小サイズとなりました。
    • まぁ結局スライドに収まらなくて 1/3 に縮小したんですけどね!!!最初から 1/3 スケールで処理すれば良かったよ!!!

サイズが大きくなったことによる影響

  • ソースコード上にjpgとpngが混在している
    • 最初はjpg拡張子のみを使うつもりでした
    • 160MBになるとjpg拡張子の限界を超えるのですね
    • 結果として割れ窓理論でコードベースの汚さが加速しました
  • モザイク画を自慢したいのにSNSにアップできない
    • 泣く泣く小サイズ版をTwitterにアップしました!が!拡大しても潰れています!
    • png拡張子の画像ファイルはzipにしても圧縮効果がないのですね
  • とにかく処理が大変
    • 目視しながらトリミングしようと思ってもFireworksが落ちます
    • メモリの読み込みや解放を工夫しないとRubyが落ちます

Ruby

スクリプト開発で利用したライブラリについて。

RMagick (Problem)

画像処理に利用した RMagick のリファレンスが分かりにくかったです。

  • 後で Ruby Style Guide(和訳)を読んで知ったのですが、今は RMagick は非推奨で、代わりに MiniMagick を使った方が良いそうです。そういえば、Rails Tutorial(和訳) にも同じことが書いてあったような。
  • どのライブラリがデファクトスタンダードなのか把握しておけば、もっと効率的に開発できるのだと反省しました。
  • ちなみに、 OpenCV であれば Python が公式でサポートされている、とのことでした。機械学習や画像処理は Python に任せた方が良いのかな。

Rubocop (Keep)

コーディング規約を Rubocop で遵守しました。規約違反を指摘するだけでなく、ある程度は自動でフォーマッターを掛けてくれます。最高。

  • 過去に作ったWebサービスを手直しできていない理由の1つに、コードの保守性が低い、というのがありました(エンタープライズな大規模アプリケーションの技術的負債に比べれば可愛いものですが)。
  • ついつい甘えがちな個人開発において、規約を確実に遵守するには、自動化するしかありません。ということで Rubocop を導入して、 .rubocop_todo.yml に反映される指摘事項が常にゼロとなるように心掛けました。
  • チーム開発でも同じで、静的解析で十分なはずの指摘に、わざわざ人間が時間を費やすのは勿体ないように思います。その分を他のことに費やした方が生産性が高まるのではないかと。
  • まぁ、結局汚くなっちゃったんですけどね!!!

質疑応答

長丁場で集中力を欠いていたこともあり、かなり雑な回答ばかりしてしまいました。 非常に申し訳なかったなぁと反省しています。

終了後に感想・質問を書いた付箋を何枚かいただいたので、リベンジも兼ねて回答します。

画像は何枚くらい取得して使用しているのですか?

  • 実際に使った element_images は 1,712枚 となります。
  • 同じ画像を何回か使いまわして 40,000枚 の画像群でモザイク画を構成しています。

最も多く使われた画像はどれですか?

  • 著作権アウトなので掲載できませんが、平均色が白となる画像です。
  • 数式の画像だと全体的に白の出現頻度が多くなりますね。

画像1枚当たりが担う領域を大きくしていくとモザイクが崩れてしまわないですか?

  • 考えなしにやると崩れるので、最初にサイズを計測しました。
  • 詳しくは前述「サイズが大きくなった理由」をご参照ください。

ベクトル比較の仕方を教えていただけますか?

  • 説明を省略した部分なので、理論面は上記スライドを見ていただければ良いかと。
  • 機械学習の分類問題として扱うことができるかと思います。初学者ならCourseraがオススメです。

yuzutas0.hatenablog.com

なお、スクリプトの実際の処理は以下の通りです。閾値を決めて簡単化しています。

  • 明度 0, 1, 2, ..., 253, 254, 255 をちょうど8分割するように閾値を設けて 0 から 7 までのグループを定義する。
  • target_image の各Pixelの色が、どのグループに所属するか判定する。
  • element_images の各画像の平均色が、どのグループに所属するか判定する。
  • 同じグループであれば十分に近いものとして扱い、適当に組み合わせる。

感想

  • 至らない点が多かったですが、学びや気付きも多かったかなと思います。
  • 他の方々の発表は、各分野のプロダクトやコンテンツならではのデータ研究が多く、「これまで知らなかったことを知る」「試行錯誤して知にアクセスする」といったサイエンスの魅力を再確認できました。
  • 今回は数学枠でしたが、機会があれば別トピックでも話してみたいです。

おわりに

改めて、運営者・登壇者・参加者の皆様、素敵な時間をご提供いただき、ありがとうございました。