2019年04月10日

MMDBridgeとTungsten rendererのテスト その2

前回の続きです。thinsheetが良さそうでしたので、使ってみることにしました。
素材自体をthinsheetにすると透明になってしまうので、外側に拡大したモデルを置いて、その材質をthinsheetにしました。単純に座標を拡大すると包むことができないので、頂点座標を法線ベクトル方向に少し移動したモデルを生成しました。

実行結果

拡大しないとわかりにくいかもしれませんが、透明なプラスチックの中に入っている感じが出ているかと思います。

00200_1.png
lambert/transparencyのみ

00200.png
内:lambert/transparency, 外:thinsheet
posted by シンドラー at 20:10| Comment(0) | Rendering | 更新情報をチェックする

2019年04月05日

MMDBridgeとTungsten rendererのテスト

MMDBridge[1]にTungsten[2]用のファイルがあったので、試してみることにしました。Tungstenは物理ベースレンダラで、C++11でIntelのembreeを使っているそうです。

ドキュメントは無くてfinal project reportを探すと[3]にありました。基本的にサンプルやソースコードを見て使い方を調べるしかなさそうですが、リソース集[4]として作者の方が素晴らしいサンプルを置いてくださっていますので、この辺りを参考にすれば何とかなるかもしれません。ライセンスはlibpng/zlibライセンスで、いくつかのサードパーティライブラリも使っているのでそちらはそのライセンスを参照します。

1. Tungstenのコンパイル
Windows 10 + Visual Studio 2017 の場合です。githubの方にはsetup_builds.batを実行するように書かれていますし、それで問題ないかと思います。今回はeditorを試すために、cmake-guiを使って自分で設定しました。editorをコンパイルする場合、Qt5OpenGLとQt5Widgetsのディレクトリを指定する必要があります。Qt5をインストールする際に、MSVC 2017 64-bitにチェックが入っていることを確認します。

qt_msvc_001.PNG

Qt5OpenGL_DIRとQt5Widgetsはcmakeがある場所を指定します。

Qt5Core_DIR: C:/Qt/5.12.2/msvc2017_64/lib/cmake/Qt5Core
Qt5Gui_DIR: C:/Qt/5.12.2/msvc2017_64/lib/cmake/Qt5Gui
Qt5OpenGL_DIR: C:/Qt/5.12.2/msvc2017_64/lib/cmake/Qt5OpenGL
Qt5Widgets_DIR: C:/Qt/5.12.2/msvc2017_64/lib/cmake/Qt5Widgets

あとはConfigure→Generate→Open Projectで良いと思います。

2. MMDBridgeの準備
他のと同様です。mmdbridge_tungsten.pyの中を見た感じでは、MikuMikuDanceのディレクトリの中にtungstenディレクトリを作成して、その中にobj2json.exeとtungsten.exeを置く必要があると思います。デフォルトではtmpに.jsonが出来て、outにレンダリング後の.pngが作成されます。パストレのサンプリング数はデフォルトでは64になっていますので、こちらもスクリプトを書き換えれば変更できると思います。

execute_tungsten(outfile, tangstenpath, jsonpath, 64)

3. Jsonファイルの変更
サンプルも含めてシーン情報はJsonファイルに記述されていますので、変更する場合にはJsonファイルをテキストエディタなどで編集することになると思います。TungstenのJsonを吐き出すモデリングソフトなども探せばありそうですが。

問題はどう書き換えれば良いかですが、基本的にサンプルを参考にしたので良いと思います。ただ、項目の一覧などはソースコードを確認する必要がありそうです。見たところ、DEFINE_STRINGABLE_ENUMというマクロが定義されており、Jsonで使われている文字列は大体網羅されていそうです。

例:
"primitives"の"type"
"mesh", "cube", "sphere", "quad", "disk", "curves", "point", "skydome", "cylinder", "infinite_sphere", "infinite_sphere_cap", "minecraft_map"

"distribution"
"beckmann", "phong", "ggx"

"integrator"の"type"
"path_tracer", "light_tracer", "photon_map", "progressive_photon_map", "bidirectional_path_tracer", "kelemen_mlt", "multiplexed_mlt", "reversible_jump_mlt"

"bsdfs"の"type"
"lambert", "phong", "mixed", "dielectric", "conductor", "mirror", "rough_conductor", "rough_dielectric", "smooth_coat", "null", "forward", "thinsheet", "oren_nayar", "plastic", "rough_plastic", "rough_coat", "transparency", "lambertial_fiber", "rough_wire", "hair", "diffuse_transmission"

また、化学式だと思いますが、conductorに出てくるmaterialのCuなどは、ComplexlorData.hppに記述されています。

"a-C", "Ag", "Al", "AlAs", "AlSb", "Au", "Be", "Cr", "CsI", "Cu", "Cu2O", "CuO", "d-C", "Hg", "HgTe", "Ir", "K", "Li", "MgO", "Mo", "Na", "Nb", "Ni", "Rh", "Se-e", "Se", "SiC", "SnTe", "Ta", "Te-e", "Te", "ThF4", "TiC", "TiN", "TiO2-e", "TiO2", "VC", "VN", "V", "W"

とりあえず書き換えに必要な情報は上記辺りかと思います。

実行結果

あぴミクさん[5]と[6]のvmdファイルを使用させていただいております。手抜きで背景なしなので微妙かもしれませんが、物理ベースレンダリングになっているかと思います。

後は[4]のTeapotを改変させていただき、マテリアルをいくつか試してみました。同じくdining-roomのサンプルを参考にさせていただきました。

teapot_9.png

上:"rough_conductor""Al", "rough_conductor""Cr", "plastic"
中:"conductor""Cu", "rough_plastic""Albedo:0.05", "thinsheet"
下:"rough_conductor""TiO2-e""Albedo:0.1", "rough_conductor""Au", "rough_plastic"

[1] MMDBridge
[2] Tungsten
[3] final report
[4] resources
[5] https://piapro.jp/t/KPU3
[6] http://www.nicovideo.jp/watch/sm23692832
posted by シンドラー at 22:22| Comment(0) | Rendering | 更新情報をチェックする

2019年03月31日

RPAに関するメモ

また今月も全然更新していませんね…。最近RPAが流行っているというニュースを見たのでメモしておきます。RPA(ロボットによる業務自動化:Robotics Process Automation)[1]ということで、業務を自動化しようというお話のようです。AIと組み合わされば面白そうですが、まだ事例は少なそうです。

とりあえずオープンソースで使えるものとしてSikuliX[2]というものがありました。現在の最新バージョンは1.1.4のようです。OpenCVで画像認識して処理を書いたりできるようです。Jtyhonを使っているので、Pythonに慣れていれば使いやすいかもしれません[3]。

ちょっと試してみましたが、細かい指定は大変そうな感じでした。

[1] http://www.soumu.go.jp/menu_news/s-news/02tsushin02_04000043.html
[2] http://sikulix.com/
[3] https://qiita.com/YHayama@github/items/483198cba0e7c4baa78c
posted by シンドラー at 23:43| Comment(0) | 日記 | 更新情報をチェックする

2019年02月28日

pix2pixのテスト

pix2pixという画像間の関係を学習するネットワークがありますので、試してみることにしました。こちらも色々な実装がGithubにありますが、今回は[1]のtensorflow版を使用させていただくことにしました。

今回はUbuntu 16.04 + Anaconda3環境でテストします。もうそろそろ安定していそうなので、18.04でもいいかもしれません。

1. Ubuntu 16.04のインストール
2. Anacondaのインストール[2]
3. noise2noiseの取得[3]
  $ git clone https://github.com/NVlabs/noise2noise
4. n2n用の環境構築([3]の手順通り)
  $ conda create -n n2n python=3.6
  $ conda activate n2n
  $ conda install tensorflow-gpu
  $ python -m pip install --upgrade pip
  $ pip install -r requirements.txt
5. pix2pix-tensorflowの取得[1]
  $ git clone https://github.com/affinelayer/pix2pix-tensorflow
5. 画像の準備、resizeで256x256に変換, combineで左右に並べた画像を生成[1]
6. 学習の実行、テスト[1]

noise2noiseは入れる必要はないと思いますが、必要な環境は大体同じだと思いますので、一つ一つ自分で入れるより早いかと思いました。

実行結果

参考サイトの例の通り、200エポックで学習させました。GTX 980とひと昔前のGPUですので、画像5000枚ぐらいで学習させて30時間かかりました。下記はテスト画像1000枚に対する結果の一部です。顔のあたりがちょっとぼけていますが、AutoEncoderオンリーと比べるとかなりそれっぽいのができているかと思います。

pix2pix_lic_001.PNG

今回カラー画像をグレースケール化した画像とLIC画像をペアとして学習させましたが、顔が白とびしていて微妙なものですので、元のカラー画像やマテリアル番号をカラー化した画像などを使えばもっとうまくいきそうな気がします。



[1] https://github.com/affinelayer/pix2pix-tensorflow
[2] https://www.anaconda.com/distribution/
[3] https://github.com/NVlabs/noise2noise
posted by シンドラー at 01:57| Comment(0) | Machine Learning | 更新情報をチェックする

2019年01月31日

Noise2Noiseについてのメモ

気が付けば1月が終わってしまいました。今回は小ネタですらないメモです。

NVIDIAがNoise2Noiseというノイズ除去手法を提案しています。
https://github.com/NVlabs/noise2noise

これまではノイズが入った画像とノイズに入っていない画像の両方が必要だったのですが、この手法はノイズが入った画像だけで良いという手法です。使い方はgithubのページの通りにやればできると思います。

これの発展手法として、Noise2Voidという手法が提案されています。こちらは教師に使うノイズ画像すらいならいらしいです。
https://github.com/juglab/n2v

jupyter notebookのサンプルがあるのですが、自前のカラー画像を使う場合などについて調査中です。

2月はもう少し頻繁に更新したいところですね。
posted by シンドラー at 21:27| Comment(0) | 日記 | 更新情報をチェックする

2018年12月31日

Appleseedレンダリングエンジンのテスト その13

大晦日ですね。今年もあまりブログ更新できませんでした。今回はappleseed rendererが2.0.0-betaでRandom-walk SSSが改良されたということで試してみました。

サンプルとしてはGitHub[1]のsandbox/tests/test scenes/bssrdfの中のものが参考になると思います。ダウンロード用zipの中にはtest scenesが入っていなかったようなので、git cloneで取ってきた方がいいかもしれません。今回は"068 - shadow - randomwalk.appleseed"のパラメータを参考にさせていただきました。

実行結果

とりあえず肌色にしてみました。羊羹とかできそうですね。

no_weight_no_normal.png

肌のテクスチャをbump mappingとして適用してみました。シミみたいになっちゃいましたね。

no_weight_use_bump.png

こちらはrandomwalk_bssrdfのweightに肌のテクスチャを適用してみた結果です。ちょっと暗いですが、雰囲気としては一番近い気がします。

use_weight_no_bump.png

以下はかこみき様のAB5モデルに適用した結果です。上がbssrdf無しで、下が上記のbssrdfを追加したものです。

skin_no_bssrdf.png
bssrdf無し

skin_add_bssrdf.png
bssrdf追加

ノイズが残っていますが、色としてはいい感じではないかと思います。

[1] https://github.com/appleseedhq/appleseed
posted by シンドラー at 18:17| Comment(0) | Rendering | 更新情報をチェックする

2018年12月16日

ガウシアンフィルタの生成

任意サイズのガウシアンフィルタが必要になって、以前作ったような気がしたんですが、あれはSobelフィルタでした(過去記事)。OpenCVの2.4まではcreateGaussianFilterという関数があったみたいですが、3.0からなくなったみたいですね。引数を見るにX軸とY軸は独立っぽいですが。


posted by シンドラー at 19:05| Comment(0) | Image Processing | 更新情報をチェックする

2018年11月02日

Google ColabでDeep Learningのテスト その3

よく見ると記事数が500件突破していますね。よく続いているものです。今回は自分用のメモです。自前のデータセットを使う場合の方法が良くわからなかったので、適当に調べてやってみました。何か間違っている気がするので、ちゃんとしたやり方がわかるといいのですが。

まず、Google Driveの接続です。[1]の方法を1つのセルにまとめただけです。2回リンクのクリックとコードの代入が必要です。
    
    !pip install -U -q PyDrive
    !apt-get install -y -qq software-properties-common module-init-tools
    !add-apt-repository -y ppa:alessandro-strada/ppa 2>&1 > /dev/null
    !apt-get update -qq 2>&1 > /dev/null
    !apt-get -y install -qq google-drive-ocamlfuse fuse
    from pydrive.auth import GoogleAuth
    from pydrive.drive import GoogleDrive
    from google.colab import auth
    from oauth2client.client import GoogleCredentials
    from google.colab import auth
    auth.authenticate_user()
    from oauth2client.client import GoogleCredentials
    creds = GoogleCredentials.get_application_default()
    import getpass
    !google-drive-ocamlfuse -headless -id={creds.client_id} -secret={creds.client_secret} < /dev/null 2>&1 | grep URL
    vcode = getpass.getpass()
    !echo {vcode} | google-drive-ocamlfuse -headless -id={creds.client_id} -secret={creds.client_secret}
    !mkdir -p drive
    !google-drive-ocamlfuse drive
    
続いて、画像読込用にPILなどをimportします。imtoolsは実践コンピュータビジョンという本にあったimtools.py[2]というファイルを、Google Driveにdrive/path/to/libsというディレクトリを作ってそこに置きました。get_imlistという関数しか使っていなかったと思いますが…。
    
    import matplotlib.pyplot as plt
    from matplotlib.image import imread
    import tensorflow as tf
    import numpy as np
    from PIL import Image
    import os
    from pylab import *
    import sys
    sys.path.append('drive/path/to/libs')
    from imtools import *
    
続いて画像の読込みです。drive/image/inputというディレクトリを作って、そこに画像を置きました。このために月額380円プランに入って200GBに容量増やしました…。空の行列を作る→画像を読み込んで変換→appendで追加という処理を画像枚数分繰り返しています。この辺もっとスマートにできそうな気がするんですが、やり方がわからなかったのでC言語っぽいベタ処理です。また、毎回画像を読み込んで変換は時間がかかるので、numpyの行列に変換して保存しました。savez_compressedを使いましたが、圧縮しない方が読み書きの時間は早かったかなと思っています。
    
    folder = "drive/image/input"
    filelist = get_imlist(folder, '.png')
    imnbr = len(filelist) # 画像数を得る

    # 6000枚の画像を1000枚ずつ6個のファイルに分割して保存
    for div in range(0,6):
        # 空の行列を作成
        immatrix = np.empty((0, 512,512), np.float32)
        # 保存するファイル名
        matname = "drive/image/input/input512_%02d.npz" % div
        # 画像の開始番号
        startNo = 1000*div
        # 1000枚ずつ保存
        for num in range(startNo, startNo+1000):
            # 画像のファイル名はsrc00000.pngなど
            filename = "drive/image/input/src%05d.png" % num
            print(num, ", ", filename)
            # PILで画像を開いてfloat型に変換
            samp = array(Image.open(filename), dtype='f')
            # R(B?)だけ取り出し
            samp = samp[:,:,0]
            # リサイズするためにImageに戻す
            pilImg = Image.fromarray(np.float32(samp))
            gray = pilImg.resize((512,512), Image.BICUBIC)
            # arrayに戻す
            graymat = np.asarray(gray)
            # appendで追加
            immatrix = np.append(immatrix, np.array([graymat]), axis=0)

        print("immatrix.shape=", immatrix.shape)
        # npzファイルとして保存
        np.savez_compressed(matname, immatrix)
    
使うときはloadで開きます。savez_compressedは複数の行列をまとめて保存できるので、取り出す場合はキーを指定する必要があります。キーを指定していない場合、デフォルトで'arr_0'になるみたいです。
    
    # 入力画像の読込み
    src_mat = np.load('drive/image/input/input512_03.npz')
    src_mat = src_mat['arr_0']
    print('src_mat.shape=', src_mat.shape)
    
U-Netもやってみたのですが、誤差が減らないので検討中です。

[1] Google Colaboratory内で画像やCSVファイルにアクセスするのが一苦労だった話
[2] Programming Computer Vision with Python


posted by シンドラー at 20:38| Comment(0) | Machine Learning | 更新情報をチェックする

2018年10月30日

Google ColabでDeep Learningのテスト その2

今日は画風変換を試してみました。[1]のサイトのコードをほぼそのまま使用させていただきました。Google Colabで画像ファイルを扱う場合、Google Driveにデータを置くと便利だと思いますので、[2]を参考にGoogle Driveへのアクセスの追加と、画像のパスだけ変更しました。

実行結果

スタイル画像
style_lic.jpg

グレースケール画像を入力画像にした場合
result_src.png

白飛びしているしうまくいっていないですね。

前回の出力画像を入力画像にした場合
result_test.png

それっぽくはなっていますが、顔の領域にも線が入って微妙ですね。パラメータを色々調整したり、参考サイトのリンクに改良法が色々あるので、それを試せばもう少しよくなるかもしれません。

[1] https://qiita.com/isboj/items/4e25f0bd0a2577d7b857
[2] https://qiita.com/yoshizaki_kkgk/items/bf01842d1a80c0f9e56c
posted by シンドラー at 21:58| Comment(0) | Machine Learning | 更新情報をチェックする

Google ColabでDeep Learningのテスト

AIが流行っているような、そろそろ幻滅期のような感じですが、Google Colab[1]が楽そうだったのと、そういえば昔LIC[2]を実装していたので、Deep LearningでLICっぽいことができるか試してみることにしました。

まずは教師画像の生成ということで、自前のコンバータにLICを実装しました。FBOで必要な情報をテクスチャに保存して、画像処理でやっているので1fpsぐらいしか出ていません。

実行結果

lic_test_002.png

あぴみくさんと[3]のモーションとMMDBridgeを使用させていただき、6055フレーム分の画像を出力しました。入力画像をグレースケール画像、教師画像をLIC計算後の画像で学習させてみます。

ネットワーク構成

今回はまずはテストということで、畳み込み層オンリーという簡単なネットワークにしてみました。プーリング層すら入れてないです。
  input_img = Input(shape=(512, 512, 1))
  x = Conv2D(16, (9, 9), padding='same')(input_img)
  x = Conv2D(16, (9, 9), padding='same')(x)
  x = BatchNormalization()(x)
  x = Activation('relu')(x)
  x = Conv2D(64, (9, 9), padding='same')(x)
  x = Conv2D(64, (9, 9), padding='same')(x)
  x = BatchNormalization()(x)
  x = Activation('relu')(x)
  x = Conv2D(64, (9, 9), padding='same')(x)
  x = Conv2D(64, (9, 9), padding='same')(x)
  x = BatchNormalization()(x)
  x = Activation('relu')(x)
  x = Conv2D(16, (9, 9), padding='same')(x)
  x = Conv2D(16, (9, 9), padding='same')(x)
  x = BatchNormalization()(x)
  x = Activation('relu')(x)
  x = Conv2D(3, (9, 9), padding='same')(x)
  x = Activation('relu')(x)
損失関数はMSEを使いました。平均なので結果がぼけてしまう気がしますね。
  model = Model(input_img, x)
  tpu_model = tf.contrib.tpu.keras_to_tpu_model(
    model,
      strategy=tf.contrib.tpu.TPUDistributionStrategy(
        tf.contrib.cluster_resolver.TPUClusterResolver(
         tpu='grpc://' + os.environ['COLAB_TPU_ADDR'])
    )
  )
  tpu_model.compile(
    optimizer=tf.keras.optimizers.Adam(lr=0.05),
     loss=tf.keras.losses.MSE,
    metrics=['mse']
  )
学習に800枚、検証に200枚使って、エポック数は100回ぐらいで、MSEが160ぐらいから下がらなくなりました。平均40の誤差ってかなり大きいですね。

実行結果

入力画像

出力画像

教師画像

エッジはしっかり出ているみたいですが、中の線がつぶれている感じですね。画風変換とかU-Netとか使った方がうまくいきそうな気がするので、そちらも試してみたいですね。

[1] https://colab.research.google.com/
[2] http://sssiii.seesaa.net/article/393573439.html
[3] https://www.nicovideo.jp/watch/sm23692832

posted by シンドラー at 00:17| Comment(0) | Machine Learning | 更新情報をチェックする