mayoko’s diary

プロコンとかいろいろ。

畳み込みニューラルネットワークを使って質感を学習してみた

背景

世の中の物質は様々な材質をしており, その材質により物の見え方は大きく異なります。たとえば, アルミニウムなどの金属を見ると光沢感があるように感じると思いますが, 布はそのような光沢感を感じません。今回は, この物体の見え方の意味での質感を機械に学習させて, 「質感 A と質感 B は, 感覚的に(人の直感的に)どれくらい異なるか」ということを学習させることを目標にします。
下の絵は質感の違いの例です。右側の物体は光沢感があって, 中央, 左の物体は光沢感はないですが白黒の違いがあります。
f:id:mayokoex:20181123215235p:plain

質感の違いを計算出来ると, 質感のデザインを行う際に, 今デザインしている質感と目標の質感がどれくらい異なるのかを数値化できたり, さらに応用すると自分が使いたい質感のデザインを直感的に選択したり(色の選択については, HSV 色空間を使って直感的に出来るようになっていると思いますが, それを質感でも出来るようになる)出来るかもしれません。これを機械学習的にやってみようかなと思ったのがこの記事です。

質感の違いを測る

まず質感の違いをどう測るのかを考えます。何となくの直感ですが, 人はものをパッと見るだけで質感がどんな感じなのかを推測することが出来ると思います。そこで今回はいろいろな質感の画像を作って, 被験者が画像の「似てる・似てない」を判定することで学習データを作ります。
ということで, 考えることは「質感の画像をどう作るか」と「質感の画像をどのように比べて似てる・似てないのデータを作るか」「データからどのように学習するか」の 3 つです。

質感の画像生成

実は質感が決まってもまだものがどう見えるかは決定しません。対象がどう見えるかは, 対象の形, 環境光, そして質感が必要となります。今回は(かなりサボって)これらのうち主に質感のみしか変化させず, 形と環境光はほぼ fix して画像を生成していきます。*1ただ, 形に関しては少し変えます。

画像は BRDF Explorer というものを使って生成しました。また, 質感のデータは MERL BRDF Database を用いました。
https://www.disneyanimation.com/technology/brdf.html
https://www.merl.com/brdf/

下の画像は生成した画像の一例です。コンピュータービジョン的な研究をやってる人ならおなじみだと思いますが, 形状は armadillo です(環境光も論文でよく見るやつだと思いますが名前を知りません, にわかなので)。
f:id:mayokoex:20181123210015p:plain:w300

質感の画像比較

質感の画像比較に関しては, 過去に似たような研究がなされていたので, それを参考にしました。
Toward a perceptual space for gloss

この論文では, 被験者に対して 3 枚の質感画像を見せます。そして, 「中央の写真に左右どちらの写真の質感が似ていると思うか?」を質問し, 被験者に答えてもらいます。
今回の場合もこれに倣って, この実験を繰り返し行ってデータを作ります。20 代の男性 1 名が実験に参加しましたが, 被験者が苦痛を訴えたので, 比較データはだいたい 400 個しかありません。

学習手法

学習に関して何も知識がないので, 割と適当です。「ネットワークこういう風にした方が良い」とかあったら教えてほしいです。
自分の作ったネットワークは,

  • A: 画像を低次元のベクトルにする(今回は可視化がしたかったので 2 次元)畳み込みネットワーク
  • B: 低次元のベクトル同士の距離を計算することで, 「似てる・似てない」を計算する層

の 2 つに分かれています。各被験者実験データは 3 枚の画像から構成されていますが, まず 3 枚の画像それぞれを A のネットワークに入れて低次元ベクトルにし, それを B のネットワーク(?)に入れて「被験者が『左の方が近い』と答える確率はこうだよ」ということを計算します。

1 つ目のネットワークは, VGG16 を単純化したものを使いました。VGG16 を参考にした理由は, どっかの話で「VGG16 でスタイル変換が出来るよ」という話を聞いたからで, これを用いると(質感とスタイルは似てるところがあるので)質感を計測したい対象の形が変わってももある程度正確に質感の違いを予測できるのではないかと考えたからです。
普通の VGG16 では 1000 クラス分類をしてますが今回は上で書いた通り 2 次元ベクトル化したいだけなので出力ベクトルは 2 次元です。

2 つ目のネットワーク(?)では, 低次元化したベクトルに関して, 左画像と中央画像のベクトルの距離を d_L, 右画像と中央画像のベクトルの距離を d_R とし, 1 / (1 + exp(d_L - d_R)) を計算することで, 被験者が左と答えるか右と答えるかをモデル化しました。

一応コードも置いておきます。Google Colaboratory で実装しました。
BrdfNetwork.ipynb - Google ドライブ

実験結果

上記のような方針で実験を行った際の, 質感の二次元分布を示します。
まず armadillo オンリーで実験を行った場合ですが, この場合は結構いい感じに分布してる気がします。傾向として, 右側に白色が, 左上側に黒色が分布しており, かつ下側の光沢感が強い傾向が読み取れます。
f:id:mayokoex:20181123213555p:plain
次に, sphere と armadillo を混ぜた場合の結果です。うーむ。何となく分かれてる気がする。
f:id:mayokoex:20181123213935p:plain
bunny と armadillo です。大きく見ると分かれてる感がありますが細かく見ると一か所にいろんな質感(白黒)があってダメな感じがします。
f:id:mayokoex:20181123214214p:plain

まとめ

  • 質感の違いをニューラルネットワークを使って学習してみた
  • 形が 1 種類の時は結構いい感じに分布している
  • 形が増えるとイマイチだけどそもそも学習データ少ないからかもしれない
  • Persona 5 と大神は良かったぞ

*1:質感に関しては, 今回は質感として最も単純なモデルである BRDF というものを使います。これは簡単に言うと「ある向きで入ってきた光を別のある向きから見た時, 光がどれくらいの強さで見えるか」を測ったものです。上で述べた金属光沢感のある物体はこの BRDF は, 鏡面反射の方向に強く出てるので光沢感を感じ, 光沢感のない物体での BRDF は, どの反射角でも同じような明るさに見えているということです。