2019年05月25日

C++でTensorflowのテスト その3

前回の続きです。自作のライブラリとEnhanceNetを試しに使ってみるところまで試せました。

1. 自作ライブラリのダウングレード

今Visual Studio 2017で開発しているので、2015にダウングレードしました。プロジェクトのプロパティ→構成プロパティ→全般にプラットフォームツールセットがあるので、これをVisual Studio 2015 (v140)に変更します。事前にVisual Studio 2015に関する何かをインストールしないと出てこないかもしれません。

続いて、使用している外部ライブラリ(OpenCVやboostなど)があれば、それもVS2015用のものに変更します。とりあえずビルドが通れば大丈夫だと思います。

2. cl.exeを使ってビルド

最終的にはBazelでビルドするのですが、その前段階としてVS2015 x64 Native Tools コマンドプロンプト上でのビルドを行います。とりあえず以下のような感じになりました。
  cl c:\mylib\src\common.cpp mylib_test.cpp /MD \
/I c:\mylib\include /I c:\opencv-4.0\include \
/I c:\boost\include\boost-1_70 /EHsc /link \
/LIBPATH:c:\mylib\lib /LIBPATH:c:\opencv-4.0\stage\x64\vc14\lib \
/LIBPATH:c:\boost\lib\x64 /LIBPATH:c:\assimp\lib \
mylib.lib assimp-vc140-mt.lib comdlg32.lib

clを使う場合、インクルードディレクトリの指定が/I, ライブラリディレクトリの指定が/LIBPATH, 後はリンクするときは/linkが必要みたいです。

これをBazel用のBUILDファイルに書き換えると以下のようになります。本当は前回のOpenCVのようにWORKSPACEファイルなどに設定すべきですが、手抜きでオプション設定の所に全部入れてしまっています。
  load("//tensorflow:tensorflow.bzl", "tf_cc_binary")

tf_cc_binary(
name = "MyLibTest",
srcs = [
"mylib_test.cpp",
"stdafx.cpp",
"EnhanceNetFunc.cpp", "EnhanceNetFunc.h"
],
linkopts =
["-Wl,--version-script=tensorflow/tf_version_script.lds",
"/LIBPATH:c:/mylib/lib",
"/LIBPATH:c:/opencv-4.0/stage/x64/vc15/lib",
"/LIBPATH:c:/opencv-4.0/3rdparty/lib/Release",
"/LIBPATH:c:/boost_1_70_0/stage/lib/x64",
"/LIBPATH:c:/Assimp/lib",
"mylib.lib",
"assimp-vc140-mt.lib",
"comdlg32.lib",
"opencv_world401.lib",
],
copts = ["/MD","/I c:/mylib/include",
"/I c:/opencv-4.0/include",
"/I c:/boost_1_70_0/include/boost-1_70",
"/EHsc",
],
deps = [
"//tensorflow/cc:cc_ops",
"//tensorflow/cc:client_session",
"//tensorflow/core:tensorflow",
#"@opencv",
],
)

インクルードディレクトリなどがcoptsに、ライブラリなどリンク情報がlinkoptsに行くようです。/linkを入れるとエラーが出たので要らないようです。追加の注意点として、Eigenを使っている場合はTensorflowのものとバージョンが違っていたのかエラーが出ましたので、Tensorflowの方を使うことにしました。

実行結果

OpenGLで画像を表示するプログラムで、最初にEnhanceNetで4倍拡大するというあまり意味のない処理を追加してみました。
hdr_viewer_tf.png
一応動作しましたので、物体認識用などfrozenしたネットワークをいくつか用意して、用途に応じて切り替えるなどできると汎用性は高まりそうです。
posted by シンドラー at 12:00| Comment(0) | Machine Learning | 更新情報をチェックする

2019年05月18日

C++でTensorflowのテスト その2

前回の続きです。今回は[1]のEnhanceNetをC++で実行するテストです。以前Windowsで環境構築したのですが、Ubuntuの方でも試してみました。Windowsよりはちょっと楽だった気もしますが、バージョンの問題とかはやっぱり色々エラーが出ました。

1. EnhanceNetの準備

[1]からgit cloneします。virtualenvは前回までに構築していますので、python enhancenet.pyで実行します。inputディレクトリに画像を置いて実行すると、outputディレクトリに4倍拡大した画像が保存されます。注意点としては、4倍なのでメモリが不足しやすいのと、outputに既に結果画像があるとスキップされるので実行されない、ぐらいかと思います。

2. ネットワーク構造と重みの出力、フリーズ処理
2.1. ネットワーク構造と重みの出力

[2]を参考にさせていただき、enhancenet.pyに.metaと.pbを出力するコードを追加しました。重みはもともとチェックポイントとして出力するようになっていましたので、追記はしていません。weightsという名前で出力するようになっていました。
  sess = tf.InteractiveSession()
  tf.train.Saver().restore(sess, os.getcwd()+'/weights')

  # https://qiita.com/rxoxixyxd/items/d821a3bc3e7fb1eed47c
  saver = tf.train.Saver()
  saver.export_meta_graph('model.meta')
  with open('graph.pb', 'wb') as f:
    f.write(tf.get_default_graph().as_graph_def().SerializeToString())

気を付ける点として、異なる画像サイズに対応するためだと思いますが、画像を1枚読み込んでその画像のサイズでネットワークへの入力が決まっているようなので、保存したネットワークはその画像サイズ依存になっている気がします。

2.2. ネットワークの入力/出力の確認

次のフリーズ処理に移るためには、ネットワークの出力層の名前?を知っておく必要があります。[3][4]を参考にさせていただきました。summarize_graphというコマンドで確認する方法と、tensorboardやnetronなどグラフ表示で確認する方法があるようです。今回はsummarize_graphを使う方法です。

tensorflowのディレクトリで、以下を実行します。
  $ bazel build -c opt tensorflow/tools/graph_transforms:summarize_graph

ビルドに成功すれば、bazel-bin/tensorflow/tools/graph_transforms/summarize_graphという実行ファイルができます。EnhanceNet-Codeのディレクトリに戻って、2.1.で出力したgraph.pbを引数に指定して実行すると、ネットワーク情報が出力されます。$TF_ROOTはtensorflowのルートディレクトリを設定した環境変数です。
  $ $TF_ROOT/bazel-bin/tensorflow/tools/graph_transforms/summarize_graph \
    --in_graph=graph.pb

Found 1 possible inputs: (name=Placeholder, type=float(1), shape=[1,480,640,3]
(略)
Found 3 possible outputs: (name=add_1, op=Add) (name=save/control_dependency, op=Identity) (name=save_1/control_dependency, op=Identity)

入力は今回640x480の画像で試しましたので、4次元テンソル[サンプル数、高さ、幅、RGB]になっています。名前は"Placeholder"です。出力は3つ(add_1, save/control_dependency, save_1/control_dependency)出てきてしまっています。saveの方はチェックポイント用?output_feature_name?みたいな感じでよくわかりませんでしたので、おそらく"add_1"の方だと思います。

2.3. フリーズ処理

[2]のfreeze_graph.pyを使用させていただいたのでいいと思いますが、一応公式サンプルの中にもfreeze_graphがあるので、そちらを使用してみることにしました。こちらだと.metaファイルは要らないようです。[5]を参考にさせていただきました。

tensorflowのディレクトリで、以下を実行します。
  $ bazel build -c opt tensorflow/python/tools:freeze_graph

ビルドに成功すれば、bazel-bin/tensorflow/python/tools/freeze_graphという実行ファイルができます。戻って次のコマンドを実行してフリーズします。
  $ $TF_ROOT/bazel-bin/tensorflow/python/tools/freeze_graph \
    --input_graph=graph.pb \
    --input_checkpoint=weights \
    --input_binary=true --output_graph=freeze_graph.pb \
    --output_node_names=add_1

--input_binary=trueを入れないと、UTF-8がどうのこうのというエラーが出た気がします。成功すればfreeze_graph.pbというファイルができます。

3. C++での推論の実行

前回作成したコードをEnhanceNet用に修正します。$TF_ROOT/tensorflow/examples/tf-train-cpp/を作業ディレクトリとしています。

3.1. カラー画像の読み込み

common.cppの前回のread_one_fileを修正します。画像の幅、高さの情報が必要なので、引数に保存するようにしました。チャンネル数は3固定ですが一応設定しています。
std::vector<std::vector<float>> read_one_file(const std::string filename, 
int& rows, int& cols, int& ch) {
int number_of_images = 1;

// load color
cv::Mat image = imread(filename, IMREAD_COLOR);
rows = image.rows;
cols = image.cols;
ch = image.channels();
std::cout << "rows:" << rows << " cols:" << cols << " ch:" << ch << std::endl;

vector<vector<float>> images(number_of_images);

// https://stackoverflow.com/questions/8184053/accessing-elements-of-a-cvmat-with-atfloati-j-is-it-x-y-or-row-col
// Read image data
for (int i = 0; i < number_of_images; i++) {
images[i].resize(rows * cols * 3);
int cnt = 0;
for (int row = 0; row < rows; row++) {
for (int col = 0; col < cols; col++) {
images[i][cnt++] = (float)image.at<Vec3b>(row, col)[0]/255.0f - 0.47614917;
images[i][cnt++] = (float)image.at<Vec3b>(row, col)[1]/255.0f - 0.45001204;
images[i][cnt++] = (float)image.at<Vec3b>(row, col)[2]/255.0f - 0.40904046;
}
}
}

return images;
}

cv::Matのat関数は(x, y)なのか(y, x)なのかいつも忘れますね。画像を読み込んでfloat型に変換→flatten処理ですが、enhancenet.pyの方で平均値を引いているのでこういうやり方でやっています。最初この処理を忘れていて、出力画像が白っぽくなってpythonで実行したときと結果が違っていて悩みました。

3.2. Tensor化

こちらはほぼ参考にさせていただいた前のコードそのままです。Tensorが4次元になったので、引数でその情報を渡しています。
  // Create a Tensor(N, rows, cols, ch) from N image data
  tensorflow::Tensor MakeTensor(const std::vector<std::vector<float>>& batch,
   const int rows, const int cols, const int ch) {
  
   tensorflow::Tensor t(tensorflow::DT_FLOAT,
   tensorflow::TensorShape({(int)batch.size(), rows, cols, ch}));
  
   auto dst = t.flat<float>().data();
   for (auto target : batch) {
   std::copy_n(target.begin(), rows*cols*ch, dst);
   dst += rows*cols*ch;
   }
  
   return t;
  }

3.3. 推論処理

void predict(const std::unique_ptr<tensorflow::Session>& session, 
const std::vector<std::vector<float>>& batch,
const int rows, const int cols, const int ch) {

// Create an input data
vector<std::pair<string, tensorflow::Tensor>> inputs = {
{"Placeholder", MakeTensor(batch, rows, cols, ch)}
};

std::vector<tensorflow::Tensor> out_tensors;

// Predict
TF_CHECK_OK(session->Run(inputs, {"add_1"}, {}, &out_tensors));

std::cout << out_tensors[0].DebugString() << std::endl;

// tensor info
std::cout << "batch: " << out_tensors[0].dim_size(0) << std::endl;
std::cout << "rows: " << out_tensors[0].dim_size(1) << std::endl;
std::cout << "cols: " << out_tensors[0].dim_size(2) << std::endl;
std::cout << "ch: " << out_tensors[0].dim_size(3) << std::endl;

#if 1
// https://stackoverflow.com/questions/49295734/in-tensorflow-c-api-how-to-save-a-picture-or-an-array-from-a-tensor
cv::Mat image(out_tensors[0].dim_size(1), out_tensors[0].dim_size(2), CV_32FC3, out_tensors[0].flat<float>().data());
#else
// https://stackoverflow.com/questions/50498561/how-to-access-tensorflowtensor-c
cv::Mat image(out_tensors[0].dim_size(1), out_tensors[0].dim_size(2), CV_32FC3);
auto output = out_tensors[0].tensor<float, 4>();
int cnt=0;
for (int y=0; y<out_tensors[0].dim_size(1); y++)
{
for (int x=0; x<out_tensors[0].dim_size(2); x++)
{
image.at<Vec3f>(y, x)[0] = output(0, y, x, 0);
image.at<Vec3f>(y, x)[1] = output(0, y, x, 1);
image.at<Vec3f>(y, x)[2] = output(0, y, x, 2);
}
}
#endif

// https://stackoverflow.com/questions/14539498/change-type-of-mat-object-from-cv-32f-to-cv-8u
cv::Mat image8U;
image.convertTo(image8U, CV_8U, 255.0);
cv::imwrite("result.png", image8U);
}

入力データの作成→実行の時に"Placeholder"と"add_1"という名前が必要です。dropoutやbatch_normalizationは使っていない?ようでしたので、オプション設定は削除しました。

out_tensorsに画像データが出力されるのですが、これを画像に戻す必要があります。out_tensors[0].DebugString()で構造などを確認できます。この辺りはコメントにも入れていますが[6]を参考にさせていただきました。個別の要素にアクセスする方法の例としてコードに残しています。実際には[7]の方法で一括でTensor→cv::Matに変換できました。

最後はもうOpenCVの範疇ですが、float→ucharに変換して保存しています[8]。

4. 実行結果

[9]の画像を使用させていただきました。普通のバイキュービック補間と比べるとぼやけが少ないと思います。

00001.png
原画像(640x480に変換)

00001-EnhanceNet.png
出力画像(2560x1920)

なかなか大変でしたが一通り手順は確認できたので、次は自前のプログラムとの連携ができるかどうか辺りでしょうか。

[1] https://github.com/msmsajjadi/EnhanceNet-Code
[2] https://qiita.com/rxoxixyxd/items/d821a3bc3e7fb1eed47c
[3] https://blogs.yahoo.co.jp/verification_engineer/71450155.html
[4] https://github.com/tf-coreml/tf-coreml/issues/232
[5] http://laid.delanover.com/how-to-freeze-a-graph-in-tensorflow/
[6] stackoverflow - how-to-access-tensorflowtensor-c
[7] stackoverflow - in-tensorflow-c-api-how-to-save-a-picture-or-an-array-from-a-tensor
[8] stackoverflow - change-type-of-mat-object-from-cv-32f-to-cv-8u
[9] http://www.syaraku-jp.com/020/020.html
posted by シンドラー at 06:20| Comment(0) | Machine Learning | 更新情報をチェックする

2019年05月06日

C++でTensorflowのテスト

GWがあっという間に終わってしまいました。GW前半は画像ビューアの改良などしていたのですが、せっかくなのでDeep Learningを使った画像の拡大などが組み込めるといいなと思い、C++でTensorflowを使う方法について試してみました。Windowsのためかなかなかうまくいきませんでした。

1. Tensorflowのビルド
[1]を参考にさせていただきました。1.13.0の方でも良かったのですが、Ubuntuの環境が1.12.0だった気がしたのでこちらを選びました。

1.1. msys2の問題
pacman -Syuでパッケージのアップデートをした後、他のパッケージの追加などができなくなりました。調べてみると[2]の方に解決方法がまとめられていて助かりました。

1.2. Windowsのロングパス名を有効化の問題
Windows 10 Homeだとgpedit.mscが無いようです。実行しなくても一応問題なかったと思います。

1.3. Tensorflow1.12.0のビルド
bazelでビルドするとエラーで止まりました。[3]でcuda_configure.bzlのgrepを修正したら解決しました。

"grep" -> "C:/msys64/usr/bin/grep"

2. サンプルのテスト
[4]を参考に、サンプルやチュートリアルをbazelを使ってテストしたものは動作しました。ただ、共有ライブラリを使う方法は、ビルドは通るのですがg++でリンクしようとするとリンクエラーがでるので諦めました。

3. Bazelの使い方について
Bazelを使ってコンパイルする方法をメインにしようと思ったのですが、慣れないと分かりづらかったです。[5]などを参考に、とりあえず簡単なプロジェクトを作って色々試してみました。WORKSPACEとBUILDが大事ですね。

4. C++でTensorflowのMNIST
[6][7]を参考に、pythonで作ったネットワークでC++で学習・推論を一通り試してみました。こちらのサイトではclを使ってビルドされていましたが、BazelでビルドするようにBUILDを作成しました。

5. OpenCVライブラリの使用
最終的に自分で作成したライブラリを使用するために、まずはOpenCVを使用してみることにしました。[8]を参考にWORKSPACE/opencv.BUILDを記述しました。BUILDで参照するとき@opencvとすれば良いのですが、その辺もBazelに慣れていないと全然わかりませんでした。

6. サンプルの改造
[7]のソースコードを変更して、OpenCVで1枚の画像を読み込んで推論を行うようにしてみました。

6.1. tensorflowのWORKSPACEへの追記
[8]を参考に、OpenCVについて追記しました。

6.2. 同じフォルダにopencv.BUILDを作成
こちらの環境に合わせて内容を修正したopencv.BUILDを作成しました。

6.3. [7]のコードを配置
tensorflow\examples\tf-train-cppに配置して、新たにBUILDファイルを作成しました。BUILDは下記のような内容にしています。nameが出力ファイル名も兼ねていますので、Windowsの場合は.exeもつけないと実行が面倒です。
  load("//tensorflow:tensorflow.bzl", "tf_cc_binary")

  tf_cc_binary(
    name = "train_and_predict.exe",
    srcs = ["train_and_predict.cpp","common.cpp"],
    linkopts =
      ["-Wl,--version-script=tensorflow/tf_version_script.lds"],
    copts = ["/MD"],
    deps = [
        "//tensorflow/cc:cc_ops",
        "//tensorflow/cc:client_session",
        "//tensorflow/core:tensorflow",
        "@opencv"],
    )

  tf_cc_binary(
    name = "predict.exe",
    srcs = ["predict.cpp","common.cpp"],
    linkopts =
      ["-Wl,--version-script=tensorflow/tf_version_script.lds"],
    copts = ["/MD"],
    deps = [
        "//tensorflow/cc:cc_ops",
        "//tensorflow/cc:client_session",
        "//tensorflow/core:tensorflow",
        "@opencv"],
  )

  tf_cc_binary(
    name = "test.exe",
    srcs = ["test.cpp","common.cpp"],
    linkopts =
      ["-Wl,--version-script=tensorflow/tf_version_script.lds"],
    copts = ["/MD"],
    deps = [
        "//tensorflow/cc:cc_ops",
        "//tensorflow/cc:client_session",
        "//tensorflow/core:tensorflow",
        "@opencv"],
  )
test.exeはこちらで追加したものです。ビルドは下記のように行います。
  $ bazel build -c opt :test.exe
common.cppに下記の2つの関数を追加して、opencvで画像読込みをしています。
  std::vector> read_one_file(std::string filename)
  {
    int number_of_images = 1;
    int rows = 0;
    int cols = 0;

    // load grayscale
    cv::Mat image = imread(filename, IMREAD_GRAYSCALE);
    rows = image.rows;
    cols = image.cols;

    vector> images(number_of_images);

    // Read image data
    for (int i = 0; i < number_of_images; i++) {
      images[i].resize(rows * cols);

      for (int row = 0; row < rows; row++) {
        for (int col = 0; col < cols; col++) {
          images[i][cols*row+col] = (float)image.at(row, col) / 255.0f;
        }
      }
    }
    return images;
  }

  std::vector set_one_label(const int label)
  {
    int number_of_images = 1;

    vector vf_label(number_of_images);

    // Read image data
    for(int i = 0; i < number_of_images; i++){
      vf_label[i] = (float)label;
    }
    return vf_label;
  }
6.4. 実行結果
手書きで28x28の画像を作成しました。エポック数は100に増やして97%程度まで認識率はありますが、単純なネットワークなのであまり精度は良くないようです。
5.png
  $ ..\..\..\bazel-bin\tensorflow\examples\tf-train-cpp\test.exe 5.png 5

  labe[0]=0.000550
  labe[1]=0.001282
  labe[2]=0.000275
  labe[3]=0.000109
  labe[4]=0.000319
  labe[5]=0.785542
  labe[6]=0.207240
  labe[7]=0.000070
  labe[8]=0.004596
  labe[9]=0.000016
  Accuracy: 1


[1] https://dev.infohub.cc/build-tf-1120-gpu/
[2] https://nagayasu-shinya.com/msys2-pacman-db-update-err/
[3] https://github.com/tensorflow/tensorflow/issues/22325
[4] http://memo.saitodev.com/home/tensorflow/build/
[5] http://msyksphinz.hatenablog.com/entry/2016/06/08/022818
[6] https://qiita.com/rxoxixyxd/items/d821a3bc3e7fb1eed47c
[7] https://github.com/ryojiysd/tf-train-cpp
[8] https://stackoverflow.com/questions/34984290/building-opencv-code-using-bazel
posted by シンドラー at 13:49| Comment(0) | Machine Learning | 更新情報をチェックする

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 | 更新情報をチェックする