2020年02月28日

PyTorch3Dのテスト その4

生成したobjの確認などが面倒だったので、objファイルを20視点から表示して保存するだけのプログラムを作ってみました。基本的にはチュートリアルの内容を簡潔にまとめたのと、Phongシェーダのためかどうかわかりませんが、テクスチャ画像やUV座標がないobjをレンダリングしようとするとエラーが出たので、テクスチャが無いモデルについてはダミーの白一色のテクスチャ画像を読み込んで、適当にテクスチャ座標を設定するようにしてみました。

実行結果

形状変形のチュートリアルで生成されたイルカを表示した結果です。

tile_image.jpg

以下コード
pytorch3d_render_obj.html

何か面白い使い道は…やっぱりGAN系ですかね…。
posted by シンドラー at 01:05| Comment(0) | Machine Learning | 更新情報をチェックする

2020年02月21日

PyTorch3Dのテスト その3

前回の続きです。今回は3つ目のチュートリアルであるRender textured meshes[1]です。

・.objの読込み
・光源やカメラ位置の変更
・バッチ処理を使って異なる視点を一度に描画

今後改良されるとは思いますが、objのローダがテクスチャ1枚のモデルにしか対応していないみたいなことが書かれていました。なので、今回はついでにテクスチャを横一列に並べて、テクスチャ座標を更新するプログラムを別途作りました。

もう一点、読み込んだテクスチャがRGB3チャンネルになっていましたので、透過処理は対応していない気がします。

実行結果

opencv_concat_tile.jpg

[2]のモデルを使用させていただきました。透過処理ができていないところがピンク色になってしまっています。

以下改変したコードです。
pytorch3d_rendertexture.html

[1] Render a textured mesh
[2] https://3d.nicovideo.jp/works/td1586
posted by シンドラー at 19:52| Comment(0) | Machine Learning | 更新情報をチェックする

2020年02月20日

PyTorch3Dのテスト その2

前回の続きです。今回は[1]のDeform a source mesh to form a target mesh using 3D loss functionsサンプルです。前回と似ている部分も多かったので、分かりやすかった気がします。

画像を見たところ、ポイントクラウドを使っているようでしたので、メッシュじゃなくてポイントクラウドの変形かと思ったのですが、lossの一つにchamfer_distanceというものがあり、これを使うために、メッシュの表面からポイントクラウドをサンプリングしているだけで、変形元も変形先もポリゴンメッシュでした。

他のポイントとしては下記のような点かと思います。
・変形の方法としては、元の形状の頂点座標に、オフセットとして変位を加算することで行う
・学習するパラメータは上記のオフセット値で、点群間の誤差が小さくなったり、スムーズな形状の誤差などを目的関数として最適化
・最適化手法はSGDを使用

dolphin.png
左:球から変形させたもの 右:元の対象メッシュ

それなりに近づいていますが、ちょっと丸っこい気もします。重みのパラメータを調整すれば改善できるかもしれません。

今回は、変形元の球と対象のイルカの両方とも頂点数が同じでしたが、今回の手法であれば違っていてもできそうなので、別のメッシュで少し試してみようかと思います。後は、LoDのような頂点数が変わるような学習の方法も少し調べてみたいかなとは思います。

前回同様、ちょっと追記したものです。
pytorch3d_test_002.html

[1] Deform a source mesh to form a target mesh using 3D loss functions

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

2020年02月18日

PyTorch3Dのテスト

FacebookのPyTorch3D、NVIDIAのKaolin、GoogleのTensorFlow Graphicsなど、AIをCGに使うライブラリなどが増えてきている気がします。キーワードとしては微分可能レンダラで、CGのレンダリングプロセスも、結局行列計算なので、微分可能なレンダラなら誤差逆伝搬すれば学習できるよね、ということだと思います。多分。

architecture_overview.png
[1]より引用

例えば、目標の視点を獲得したいのであれば、視点座標を学習するパラメータとし、求める出力画像と、現在の視点での出力画像の差を計算し、Adamなどを使ってパラメータ最適化を行っていく、ということが微分可能レンダラであれば可能になるのだと思います。

今回はPyTorch3D[2]のCamera position optimizationサンプル[3]を試してみました。PyTorch3Dを選んだ理由は特にありません。

あまりPythonに慣れていないので、一行ずつ処理を調べて追記した結果が下記になります。次元という言葉の使い方が混乱するのですが、3次元空間というときの次元と、テンソルを3要素から4要素に拡張するときに次元を増やすと言っていいのか分かりません。

pytorch3d_test_001.html

Deform a sphere mesh to dolphinサンプルの方も同じように確認すれば、大体流れはつかめそうな気がします。

[1] Renderer Getting Started
[2] PyTorch3D - GitHub
[3] Camera position optimization with differentiable rendering
posted by シンドラー at 18:06| Comment(0) | Machine Learning | 更新情報をチェックする

2020年01月31日

動画像処理用ソフトウェアの作成

プログラマは罪深い生き物なので、必要なものがあれば自分で実装しがちというようなつぶやきをツイッターで見ましたが、まさにその通りですね。動画のクリッピングとかスケーリングする必要があったので、いいフリーソフトが色々あるみたいですがOpenCVなどを使って自分で作ってみました。

実行結果

時間がかかる処理の部分はカットしています。


右上に原動画の縮小版を表示しています。クリッピング、スケーリングの他、背景差分、FFT、fastNlMeansDenoisingColoredMultiを使ったノイズ除去などもできるようにしてみました。OpenCV様様ですね。後は要らないフレームの削除機能があれば個人的には十分でしょうか。

動画サンプルとして[1]を使用させていただきました。

[1] https://www.kaggle.com/aalborguniversity/brackish-dataset
posted by シンドラー at 00:47| Comment(0) | Image Processing | 更新情報をチェックする

2019年12月31日

プログラミングパラダイムの勉強

今月も全然更新できませんでしたが、忙しかったので仕方がないですね。大晦日ですが月一更新のため本の紹介です。

機械学習のPythonのコードを見ていると、たまにラムダ式が出てきます。あまり印象はないですが、Pythonは関数型スタイルやオブジェクト指向などに対応していますので、その辺りの書き方も理解していないと読み取りにくいことがあります。

[1]でそれぞれの書き方などが勉強できますので、良いのではないかと思います。

[1] 深井 裕二著:「Python人工知能プログラミング-オブジェクト指向と関数型スタイルによるAI開発技法」、三恵社、2019
posted by シンドラー at 19:59| Comment(0) | 関数プログラミング | 更新情報をチェックする

2019年11月30日

CNPYのテスト その2

いつの間にか11月も終わりですね…。月一更新ということで前回の続きですが、大した進展はありません。

cnpyを使ってファイルを読み込んでデータにアクセスする場合、テンプレートを使って型を指定してから参照します。
     //check that the loaded myVar1 matches myVar1
cnpy::NpyArray arr_mv1 = my_npz["myVar1"];
double* mv1 = arr_mv1.data();
この場合、データがdouble型と分かっていればいいのですが、分かっていない場合は何らかの方法で型を調べないといけないので面倒です。ファイルフォーマットとしては、ヘッダの部分でエンディアンの指定、型、バイト数を出力しているようでしたので、ロード時に型の情報も取得してNpyArrayで保持するように変更しました。

npyのヘッダには、リトルエンディアンは'<'、ビッグエンディアンは'>'、型は浮動小数点が'f'、符号付き整数が'i'、符号なし整数が'u'、boolが'b'、複素数が'c'で、その次がバイト数になっているようです。例えば、unsigned shortでリトルエンディアン環境では、"
posted by シンドラー at 19:06| Comment(0) | Machine Learning | 更新情報をチェックする

2019年10月31日

CNPYのテスト

最近はAIでPythonが流行っていますが、長年C/C++で作ったものがあるので、その辺も活用したいと思います。とりあえずはデータ共有ということで、Pythonのnumpyで使われているnpy/npzをC言語で読み書きできるcnpy[1]を試してみました。

CMakeを使ってビルド・インストールします。特に問題はないかと思います。使用方法としては、npy_load, npz_loadなどの関数を使います。いろいろなデータ型を使用できるようにテンプレートを使った構造体になっています。使い方はexample1.cppを見れば大体わかると思います。

注意点というか忘れやすい点として、tensorflow?で画像データを扱う場合はデータの並び順に気を付けます。widthとheightを逆にしていて困りました。[2]にあるように、[n, height, width, channel]の順番に並べる必要があります。

実行結果

何となく3次元畳込み(conv3d)を試してみたかったので、C++で動画像をnpz形式に変換→Google Colaboratoryでnpzを読み込んで動画分類を行ってみました。データセットとしては[3]の一部を使用させていただきました。

512x384のカラー動画72フレームを1つの入力データ[n, 72, 384, 512, 3]として、4つのクラス(head, sa, si, sx)に分類する実験です。動画のフレーム数もまちまちでしたが、とりあえず使ったデータの中で一番短かった72フレームを基準にしました。教師データ8動画、テストデータ5動画と少なすぎですね。

ネットワーク構造は下記のような普通のCNNです。

  Model: "model_1"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
input_1 (InputLayer) (None, 72, 384, 512, 3) 0
_________________________________________________________________
conv3d_1 (Conv3D) (None, 72, 384, 512, 16) 1312
_________________________________________________________________
conv3d_2 (Conv3D) (None, 72, 384, 512, 16) 6928
_________________________________________________________________
max_pooling3d_1 (MaxPooling3 (None, 36, 192, 256, 16) 0
_________________________________________________________________
batch_normalization_1 (Batch (None, 36, 192, 256, 16) 64
_________________________________________________________________
conv3d_3 (Conv3D) (None, 36, 192, 256, 8) 3464
_________________________________________________________________
conv3d_4 (Conv3D) (None, 36, 192, 256, 8) 1736
_________________________________________________________________
max_pooling3d_2 (MaxPooling3 (None, 18, 96, 128, 8) 0
_________________________________________________________________
batch_normalization_2 (Batch (None, 18, 96, 128, 8) 32
_________________________________________________________________
conv3d_5 (Conv3D) (None, 18, 96, 128, 4) 868
_________________________________________________________________
conv3d_6 (Conv3D) (None, 18, 96, 128, 4) 436
_________________________________________________________________
max_pooling3d_3 (MaxPooling3 (None, 9, 48, 64, 4) 0
_________________________________________________________________
batch_normalization_3 (Batch (None, 9, 48, 64, 4) 16
_________________________________________________________________
conv3d_7 (Conv3D) (None, 9, 48, 64, 2) 218
_________________________________________________________________
conv3d_8 (Conv3D) (None, 9, 48, 64, 2) 110
_________________________________________________________________
max_pooling3d_4 (MaxPooling3 (None, 4, 24, 32, 2) 0
_________________________________________________________________
batch_normalization_4 (Batch (None, 4, 24, 32, 2) 8
_________________________________________________________________
flatten_1 (Flatten) (None, 6144) 0
_________________________________________________________________
dense_1 (Dense) (None, 512) 3146240
_________________________________________________________________
dense_2 (Dense) (None, 256) 131328
_________________________________________________________________
dense_3 (Dense) (None, 128) 32896
_________________________________________________________________
dense_4 (Dense) (None, 4) 516
=================================================================
Total params: 3,326,172
Trainable params: 3,326,112
Non-trainable params: 60
_________________________________________________________________
動画なのでやはりメモリ使用量?が多そうなので、バッチサイズは1で逐次学習させました。optimizerはadamで、lossはbinary_crossentropyを使いました。結果としてはval_lossは0.24ぐらいまでしか下がらず、テストに対しても5枚中4枚成功の80%でした。枚数が少なすぎるのでどうしようもありませんが、やってみたいことは一通りできたと思います。

[1] https://github.com/rogersce/cnpy
[2] https://stackoverflow.com/questions/48509419/why-i-must-reshape-one-image-to-n-height-width-channel-in-cnn
[3] http://conradsanderson.id.au/vidtimit/
posted by シンドラー at 20:48| Comment(0) | Machine Learning | 更新情報をチェックする

2019年09月20日

glfwでvulkanのテスト

月一更新を心がけていたのですが、先月は更新できませんでした。特に理由があるわけではないので困ったものです。

vulkanが出て結構時間が経ちますが、使いにくいというか準備が大変というお話を聞いた気がするので、ライブラリ経由で手抜きをすることにします。vulkan関係の情報としては、[1]がまとまっている気がします。こういう情報もgithub上なんですね。今回はもっとvulkan特化のライブラリでも良かったのですが、比較的使い慣れているということでglfw[2]を試すことにしました。

vulkan sdkのインストール
[3]からダウンロード/インストールします。

glfwのcmakeを使ったビルド
特に気を付ける点などはないかと思います。設定にGLFW_VULKAN_STATICというものがありますが、チェックが必要かどうかは分かりませんが、今回はチェックを入れました。

ビルドすると、vulkan関係のリンクエラーがでるので、インストールしたvulkan sdkのinclude/libraryを設定します。vulkan-1.libをリンクすればTestなどのサンプルのビルドも通るはずです。Testにtriangle-vulkanというプロジェクトがあります。簡単なサンプルですが、triangle-vulkan.cだけで2000行を超えているので、やっぱり複雑になりやすいのかもしれません。

その他glfwのvulkan guideが[4]にあります。

実行結果

glfw_vulkan_001.png

[1] https://github.com/vinjn/awesome-vulkan
[2] https://github.com/glfw/glfw
[3] https://vulkan.lunarg.com/
[4] https://www.glfw.org/docs/3.2/vulkan.html
posted by シンドラー at 01:14| Comment(0) | OpenGL & Metasequoia | 更新情報をチェックする

2019年07月31日

Kaggleのテスト

気が付くと一月経っていますね…。機械学習のネタとして、Kaggle[1]を少し試してみることにしました。感想としては、前処理大変だな、という感じです。Getting StartedのDigit Recognizer、Titanic: Machine Learning from Disaster、Facial Keypoints Detectionをやってみましたが、掛けているデータがあるとか、顔画像も逆光で光の当たり方がバラバラなど、実際の問題に近づくほど綺麗なデータが揃わずに前処理などが重要になってくる気がしました。後は深層学習が主流かと思ったのですが、LightGBM[2]などを使った決定木ベースの方がいい問題も多いんですね。

以下はメモです。

csvファイルの読込み
  import pandas as pd

csv_train = pd.read_csv(filepath_or_buffer="training.csv", sep=",")
zipfileの解凍
  import zipfile

with zipfile.ZipFile('test_img.zip') as existing_zip:
existing_zip.extractall('test')
画像をnumpy配列に変換して保存[3]
  from keras.preprocessing.image import load_img, img_to_array
img_size = (96, 96)
temp_img_array_list = []

for img in img_list:
temp_img = load_img(img, grayscale=False, target_size=(img_size))
temp_img_array = img_to_array(temp_img) / 255.0
temp_img_array_list.append(temp_img_array)

temp_img_array_list = np.array(temp_img_array_list)

print(temp_img_array_list.shape)
np.save('train_img.npy', temp_img_array_list)
kerasでデータ拡張[4]

独自損失関数の定義(nan対策)
  def euclidean_distance_loss(y_true, y_pred):
"""
Euclidean distance loss
https://en.wikipedia.org/wiki/Euclidean_distance
:param y_true: TensorFlow/Theano tensor
:param y_pred: TensorFlow/Theano tensor of the same shape as y_true
:return: float
"""
# y_trueがnanであればy_predに、それ以外はy_trueを採用
y_temp = K.tf.where(K.tf.is_nan(y_true), y_pred, y_true)
# y_trueがnanの時括弧の中が0になるはず
sq = K.square(y_pred - y_temp)
return K.sqrt(K.sum(sq, axis=-1))
Kerasサンプルの独自ユークリッド距離損失関数にnan判定を追加したのですが、これが正しいのかどうかは分かりません。

データ拡張なしでCNNで教師データ学習させてみましたが、RMSEが4.1とか全然駄目でした。nanのデータを除いて学習させるとか、データ拡張するとか、データを増やすなど色々しないとなかなか難しいですね。

[1] https://www.kaggle.com/
[2] https://github.com/Microsoft/LightGBM/
[3] https://qiita.com/tom_eng_ltd/items/286a8012527a3dd3c542
[4] https://qiita.com/takurooo/items/c06365dd43914c253240
posted by シンドラー at 20:20| Comment(0) | Neural Network | 更新情報をチェックする