背景差分法でFGOQuestのサーヴァント部分だけを保存してみる

はじめに

今年のエイプリルフールも各社気合いを入れたコンテンツを眺めたり遊んだりしていろいろ楽しませてもらった。
中でもFGOQuestがとても完成度高くてこれを1日しかやらせてくれないとか正気か!?って本気で思った。
そのFGOQuestにはモンスターとしてFGOのサーヴァントが出て来るんだが、ドット絵のサーヴァントがすごい良かった。

f:id:panchiga:20190415013145p:plain
戦闘中の画像例

このとてもいいドット絵サーヴァントを1日しか楽しめないのは辛い。
戦闘画面から画像処理的な処理してサーヴァントだけを透過PNGで保存できないかなって考えた。

※ 今回取得した画像は配布したり二次利用をするためのものではなく, 自分一人で眺めてニヤニヤするためのものです。

方法

今回は戦闘画面の背景画像が固定なのを利用して、サーヴァントから背景画像を取り除く。
背景差分法とか呼ばれるらしい。

処理の流れ

  1. 背景画像読み込み
    bg_img = cv2.imread(背景画像)
  2. サーヴァントあり画像読み込み
    target_img = cv2.imread(サーヴァントあり画像)
  3. 両方の画像から戦闘ウィンドウ部分をトリミング
    trim_bg = bg_img[ウィンドウ部分], trim_target = target_img[ウィンドウ部分]
  4. トリミングした画像に対して, サーヴァントあり画像 - 背景画像
    numpyがクソ強いのでこれだけでいい感じに背景が消える
    diff_img = trim_target - trim_bg
  5. 差分画像のうち, 0なら背景, そうでないならサーヴァントとしてマスク作る mask = np.where(diff_img == 0, diff_img, trim_target)
  6. マスクを見て0のところをサーヴァント画像の方も透明にする イメージの3次元目がBGRの色情報になってるのでそこに1次元0-255のアルファチャンネルを追加
  7. 各サーヴァントごとにトリミング(3体いるなら3枚の画像作る感じ)
  8. それぞれ保存 cv2.imwrite

結果

こんな感じに画像が取れた。 BBちゃんかわいい。

f:id:panchiga:20190415014622p:plain
透過サーヴァントたち

感想

  • OpenCVとNumpyがクソ強い。
  • いつか使いたいって思ってた背景差分法使えてよかった。
  • シンプルな実装でも意外といい感じになるもんだなって。
    • 一部画素の色が背景と同じだったりしてノイズが入るのできれいな画像作りたければ穴埋めはしたほうが良いかも
  • 実装力上げていきたい。
  • 画像処理はいいぞ。

  • スクショそんなに取ってなくて全然サーヴァント網羅できてないのが大変つらい...