2016年03月04日

libiglについてのメモ その2

前回の続きです。

とりあえずExample 203を参考に、その他のモデルで曲率とベクトルを計算してみました。その際、下記のようなエラーが出ました。

Could not compute curvature of radius 0.827856

エラーで検索してみると、重複する頂点があると失敗するので、igl::remove_duplicate_verticesを使って先に削除するように書かれていました[1]。

使い方ですが、下記のように使用します。
#include <igl/remove_duplicate_vertices>
...
  MatrixXd SV;
  MatrixXi SVI, SVJ;
  // 重複頂点の削除
  igl::remove_duplicate_vertices(V, 0.0000001, SV, SVI, SVJ);
  // SVに削除後の頂点
  V = SV;
  // SVJに元の頂点番号→削除後の頂点番号が格納されているので、
  // インデックスリストを更新
  // ループを回さず一括処理する方法があるはず?
  for (int i = 0; i < F.rows(); i++)
  {
    for (int j = 0; j < F.cols(); j++)
    {
      int temp = F(i, j);
      F(i, j) = SVJ(temp);
    }
  }
関数の引数としては、一つ目が頂点の位置座標行列、2つ目が重複判定のためのパラメータ、3番目が削除後の頂点の位置座標行列、4番目が、削除後の頂点番号→削除前の頂点番号のマップ、5番目が削除前の頂点番号→削除後の頂点番号のマップになります。これを使用して、面のインデックスを更新します。

実行結果

あぴミクさんをOFFに変換してテストしてみました。OFFというのは初めて見ましたが、3D CADなどで使われているファイルフォーマットのようですね[2]。

libigl_015.png

頂点を削除したくない場合は、削除前/削除後のマップは用意されていますので、計算するときだけ一時的に削除して、元の接線ベクトル/従法線ベクトルに割り当てるといった使い方はできるかと思います。

後、結果としては結構統一性がない気がするので、可視化にこれを使うと色々問題があるのかもしれません。頂点単位ではなく、テクスチャ単位で欲しい気もします。

[1] principle_curvature "Could not compute curvature" on STL file
[2] Wikipedia - OFF (fileformat)
web拍手 by FC2
posted by シンドラー at 00:30 | Comment(0) | TrackBack(0) | OpenGL & Metasequoia | このブログの読者になる | 更新情報をチェックする

2016年03月01日

libiglについてのメモ

いつの間にかもう3月ですね。2月は29日があったのにすぐ終わった気がします。

頂点座標に法線ベクトルは一般的に用意されていますが、接線ベクトルは用意されていない場合が多く、外積を使用したりテクスチャ座標から計算したりすることが多いです。頂点座標と法線ベクトルから計算できるのは接平面であり、ベクトルとしては無数に取れるため、どの方向を接線ベクトルとして採用するかが問題となります。

この辺を、例えば近傍頂点から曲面を推定し、勾配などから決める方法はないのかなと考えてみたところ、libigl[1]というライブラリを使えば良さそうな気がしました。ヘッダオンリーのC++ジオメトリ処理ライブラリで、MPLv2.0ライセンスのものです。内部でEigenを使っているようです。

[1]のリンクにもありますが、Tutorial[2]があり、かなり充実しているようですので、そちらを参考にすれば色々できると思います。

0. Mesh representation (Example 101)

libiglでは、Eigenライブラリを使用しており、ベクトルと行列を使用します。三角メッシュの頂点と面情報も行列のペアで表現されます。
    Eigen::MatrixXd V;
    Eigen::MatrixXi F;
Vは、頂点数×3(x,y,z座標)の行列で、Fは面数×3(面のインデックス(左回り))の行列のようです。こうすることで3つぐらいいいことがあるそうです。libiglでは一般的なメッシュフォーマットの読み書きはサポートしていて、read*.hやwrite*.hなどのファイルに記述されています。

libigl_001.png
[1]より引用した説明図

1. Curvature directions (Example 203)

ガウス曲率を計算する時の最大と最小の曲率を持つ主曲率の方向を計算できるようです。この2つのベクトルの片方を接線ベクトル、もう一つを従法線ベクトルにすれば、今回の目的は果たせそうではありますが、その結果がいいものなのかどうかは不明です。

実行結果

libigl_014.png

2. Baking ambient occlusion (Example 606)

レイキャスティングによる頂点ごとの環境遮蔽を計算してくれる関数が提供されています。使用する場合、外部ライブラリとしてEmbree[3]が必要でした。

実行結果

libigl_013.png

この他にも、DualQuaternionSkinningとか面白そうな機能がたくさんあります。

[1] GitHub - libigl
[2] libigl tutorial notes
[3] Embree - High-performance ray tracing kernels
web拍手 by FC2
posted by シンドラー at 22:55 | Comment(0) | TrackBack(0) | OpenGL & Metasequoia | このブログの読者になる | 更新情報をチェックする

2016年02月10日

Extreme Learning Machineのテスト

ニューラルネットワークのような感じでバックプロパゲーションで重みを学習するのではなく、最小二乗法で計算するELM(Extreme Learning Machine)というものがあるみたいなので、試してみました[1][2]。

ネットワーク構成
elm_001.png
最初バイアス入力を入れずにやっていて、近似できないので困っていました。出力の閾値の代わりとして入れているものなので、ELMでも当然必要でした。

elm_002.png

最小二乗法の計算は、[2]にも書かれていますが、データ数>未知数の場合と、データ数<未知数の場合で場合分けするべきですが、今回は片方しか書いていません。

elm_003.png

実行結果

活性化関数にシグモイド関数を使っています。とりあえずsinc関数に一様乱数ノイズを付与した入力データに対して、ELMを使用して関数近似してみました。中間層50,データ数100です。

elm_004.png

[1] Extreme Learning Machine
[2] Extreme Learning Machine
web拍手 by FC2
posted by シンドラー at 20:38 | Comment(0) | TrackBack(0) | Machine Learning | このブログの読者になる | 更新情報をチェックする

2016年01月15日

UnityでQumarionとDK2のテスト

明けましておめでとうございます。といってももう1月も半分終わってますね…。

先月Qumarionが最大55%OFFセールをしていたので、とりあえず買ってみました。Unityと組み合せて使う場合はどうすればいいのか考えていたのですが、ライブラリを公開してくださっている方がいらっしゃいましたので、使わせていただくことにしました[1]。

使い方としては[1]の通りで、Visual Studio Community 2015でコンパイルしたのですが、System.Reactive.Linqのところでエラーがでました。Reactive Extensions (Rx) v2.0がインストールされていないのが原因だったようですので、[2]を参考にインストールするとコンパイルが通りました。

Unity上での使用方法も[1]の通りで問題ないかと思います。今回はMMD4Mecanimを使ったTda式モデルで試させていただきました。注意点としては、RigをHumanoidにする[3]必要があることと、Tポーズ基準にする必要がありますので、適当にTポーズのvmdファイルを作って変換時に指定しました(これはUnity上でTポーズにしたのでいいのだとは思います)。

後はVR Supportを有効化すればDK2で眺めながら人形遊びができるようになります。また、Head Look Controllerなどを有効にしているとそちらも反映されるようです。

実行結果

unity5_qumarion_001.png

操作性としては、Qumarionはポジショントラッキング機能はないようなので、例えばQumarionを手前に動かしてもUnity上では移動しないのと、後ろを見ようとしてY軸中心に回転させても反映されないなどその辺が何とかなるとより人形遊びに近づくかと思いました。

[1] QUMARIONをUnityで使うライブラリを公開しました
[2] 連載:Reactive Extensions(Rx)入門
[3] Unity内でMMDモデルを自由に走らせる手軽な方法

web拍手 by FC2
posted by シンドラー at 02:31 | Comment(0) | TrackBack(0) | Unity 5 | このブログの読者になる | 更新情報をチェックする

2015年12月21日

色の類似度を用いたグレースケール化

いつの間にかあと2週間で今年も終わりとは困ったものです。

OpenCVを使用していると、たまに入力がグレースケール指定のものがあります。単純にグレースケール化しても良いのですが、例えば赤っぽさで明暗にしたグレースケール画像を入力した方が都合が良い場合もあるかと思います。

というわけで、色々な誤差(類似度)[1]を使ってカラー画像をグレースケール化してみました。HSVに関しては、参考サイトの式ではなく、色相は1周するのでその辺を考慮した[2]のと、Hの類似度(0〜1)×彩度(0〜1)という彩度が低いと類似度が低いという適当な式で計算したものです。

実行結果

rainbow.png
                原画像
Paintて適当に作った画像です。

赤との類似画像

red_SSD.png red_ZNCC.png red_HSV1.png
        SSD               ZNCC                HSV

青との類似画像

blue_SSD.png blue_ZNCC.png blue_HSV1.png
        SSD               ZNCC                HSV

緑との類似画像

green_SSD.png green_ZNCC.png green_HSV1.png
        SSD               ZNCC                HSV

HSVやZNCCを使う場合は分母が0に近づく時が困りますね。

[1] 色の類似度
[2] hue値を使った色類似度計算についての試行

web拍手 by FC2
posted by シンドラー at 16:59 | Comment(0) | TrackBack(0) | Image Processing | このブログの読者になる | 更新情報をチェックする

2015年11月24日

PolyVoxの使い方についてのメモ

いつの間にか11月下旬ですね…。もう来月で一年が終わってしまうとは困ったものです。
以前の記事でも使っていましたが、PolyVox[1]をMinecraft風に使う場合のメモです。

PolyVoxでは、表面ポリゴン抽出を、マーチングキューブス法を使ってなるべく滑らかな表面を作成する方法と、Minecraftのように立方体が積み重なったような表面を作成する方法のどちらかを選ぶことができます。

CubicSurfaceExtractorWithNormalsでは、ボリュームデータから表面ポリゴンを立方体ベースで作成してくれます。このとき、ポリゴン情報とボリューム格子番号の対応が取れないっぽいのですが、マテリアル番号は格納されているようです。

まず、Minecraft風のボリュームデータでは、各格子が持つデータ1バイト(0〜255)をマテリアル番号として、0を空気、それ以外を物体とします。今回は例題としてMagicaVoxel[2]のサンプルデータを読み込んで、それをボリュームデータとしてそのまま適用しました。

で、ポリゴンデータはチュートリアル[3]にもあるように、下記3行で抽出できます。


  SurfaceMesh<PositionMaterialNormal> mesh;
  CubicSurfaceExtractorWithNormals< SimpleVolume<uint8_t> >
    surfaceExtractor(&volData, volData.getEnclosingRegion(), &mesh);
  surfaceExtractor.execute();

次に、頂点座標やマテリアル番号の参照方法ですが、こちらもチュートリアルを参考にします。

  //Convienient access to the vertices and indices
  const vector<uint32_t>& vecIndices = surfaceMesh.getIndices();
  const vector<PositionMaterialNormal>& vecVertices = surfaceMesh.getVertices();

  for (int i=0; i<vecVertices.size(); i++)
  {
    float p[3], n[3], materialNo;
    p[0] = vecVertices[i].position.getX();
    p[1] = vecVertices[i].position.getY();
    p[2] = vecVertices[i].position.getZ();
    n[0] = vecVertices[i].normal.getX();
    n[1] = vecVertices[i].normal.getY();
    n[2] = vecVertices[i].normal.getZ();
    // float型
    materialNo = vecVertices[i].getMaterial();
  }

あと、テクスチャ座標は取得できない?ようでしたので、面と頂点座標情報から適当に生成して1面に1枚下記画像を張り付けるようにしてみました。
polyvox_test2_003.png

voxファイルにはマテリアル番号と対応する色パレットがありますので、色×テクスチャ色で適当に色付けしています。

実行結果
biome.voxを使用させていただいております。問題があればお知らせください。

 polyvox_test2_001.png polyvox_test2_002.png

まぁMagicaVoxelでPlyやObjで出力できますので、MagicaVoxel対応データをポリゴン化する意味はないですが、現状ではサイズ制限がありますので、大きめのボリュームデータをとりあえずボクセル化したい場合などには使えるかなとは思います。

[1] http://www.volumesoffun.com/polyvox-about/
[2] https://ephtracy.github.io/
[3] http://www.volumesoffun.com/polyvox/documentation/0.2.1/manual/tutorial1.html
web拍手 by FC2
posted by シンドラー at 00:23 | Comment(0) | TrackBack(0) | OpenGL & Metasequoia | このブログの読者になる | 更新情報をチェックする

2015年10月30日

位相限定相関法(POC)のテスト

以前ちょっと試してそのまま放置していたので何となく整理しました。参考サイトもたくさんありますし、OpenCVでも実装されているようです[1]〜[4]。

2枚の画像のマッチングを行うときに、フーリエ変換して位相情報のみの相関をとって逆変換すると、平行移動量の所にピークが出るみたいです。

で、ピークの様子を確認するのにgnuplot等で表示すればいいのだと思いますが、画像サイズと等しいXY平面ポリゴンを作成して、値を高さZにするディスプレイスメントマッピングみたいなものを作ってみました。

POC_002.png

POC_003.png

上記の計算をしてPLYで出力するサンプルプログラムです。法線計算とか除いています。今回は表示をMeshLab上でやっていますが、法線計算もMeshLabでやればいいかと思います。
plytest.cpp

実行結果
poc_001.png

ついでにLenna画像で試してみました。高さはグレースケール化した時の輝度値です。

POC_006.png
横から見た結果
POC_008.png POC_007.png
       光源なし              光源あり

後は高さマップや法線マップを読み込んでポリゴンで出力するバージョンも作ってみました。画像から読み込んで出力する値を変更しただけですが。
POC_005.png
[5]の画像を使用させていただいております。

話が逸れましたが、まずは平行移動させた画像です。同一画像の場合、ピークが画像の中心に来ますので、平行移動量は画像の中心からどれだけずれているか、になるのではないかと思います。

POC_010.png POC_011.png
原画像

POC_004.png
ピーク画像

結果としては完全に一致していたと思います。ペイントで適当に移動させただけですので、サブピクセル単位のずれはありません。

次に、回転角の計算です。こちらはRIPOCというもので、2枚の画像をフーリエ変換して得られたスペクトル画像をLogPolar変換した画像からPOCで平行移動量を求める、という方法のようです。おそらく。

POC_010.png POC_012.png
原画像

POC_013.png
LogPolar変換した2枚の画像
(平坦な部分に見える線が横(画面奥方向)に平行移動している。今回は横方向がθ)

POC_009.png
ピーク画像

LogPolar変換で、今回は横軸にθ(-PI〜PI)をとっていますので、画像の幅が512ピクセルであれば、512ピクセルで2PIラジアンのずれ、ということになります。端の方が大きい値をとっていますので、変換バグがあるかもしれません。

計算した結果、横方向に48ピクセルずれたところにピークがありましたので、2PI*48/512ラジアン≒33.75度となりました。確かGIMPで33.4度回転させた気がしますので、大体あってそうです。もっと精度がほしい場合はピーク位置をsinc関数か何かで出す必要があるみたいです。

[1] http://d.hatena.ne.jp/suzume_r/20100515
[2] http://authorunknown408.blog.fc2.com/blog-category-1.html#39
[3] http://www.soaristo.jpn.org/blog/archives/2015/02/150214.php
[4] http://cvl-robot.hateblo.jp/entry/2014/02/06/171541
[5] http://www.bencloward.com/shaders_offset.shtml

web拍手 by FC2
posted by シンドラー at 18:28 | Comment(0) | TrackBack(0) | Image Processing | このブログの読者になる | 更新情報をチェックする

2015年10月16日

[Unity 5] FPS移動のためのクラッチ操作のテスト [DK2]

ダンジョン探索系のコンテンツで、視点変更にマウスを使うものがあります。あれはもう駄目ですね。酔います。しかし、後ろを振り向きたい場合、現状のOculus Rift DK2ではトラッキング範囲の限界などもあり何か工夫しないと難しいです。

可動範囲が決まっているマウスの場合、持ち上げている間はマウスカーソルが動かず、領域の端に来たら持ち上げて可動範囲内に戻す、というのを繰り返します。これをクラッチ操作と呼ぶこともあるようです。

今回は、このクラッチ操作を導入してみるテストです。左を向いて、これ以上後ろを向けない場合、キーを押しながら首を前向きに戻す、というのを繰り返す感じです。

仕様
・キーボードを押している間は、Y軸回転を無効化する
 →押した瞬間の向きを保存しておき、押している間はY軸回転の逆回転を親ノードに適用する
 →トラッキングを無効化する操作なので、ユーザが能動的に行わないと酔いそうなため
・キーボードを押している間は、画面を暗くする
 →トラッキング無効化中であることを認識しやすくするためと、酔いを軽減するため

というわけで、カメラに適用するスクリプトは下記のものになります。mainCameraはHMDの位置姿勢で上書きされますので、その親にdummyのGameObjectをつけています。
HMDWalkScript.cs

実行結果

首を限界まで回して、これ以上回らないところでキーを押して前を向く、ということをやっているのですが、動画だとさっぱり伝わりませんね。

感想

慣れると違和感なく操作できました。それ以前に、ただ単に前進しているだけでも体が動いていないのに視点が動くせいで酔ってしまったので、FPSは酔いやすい自分には厳しそうです。以前やったテレポート移動+今回のクラッチ操作が良さそうですかね。適用できるゲームが減ってしまいそうですが。

web拍手 by FC2
posted by シンドラー at 20:40 | Comment(0) | TrackBack(0) | Unity 5 | このブログの読者になる | 更新情報をチェックする

2015年10月15日

Unity 5でG-Bufferのテスト その4

時間が開くと色々忘れて困ったものです。前回のHeadモデルは、1マテリアルの1テクスチャなので問題なかったのですが、一般的なモデルは複数マテリアルで複数テクスチャを使っていて色々大変です。

今回は、マテリアル番号を確認するために、G-Bufferに前回と同様にマテリアル番号を出力して、そのデータを元に特定のマテリアル番号の所だけに特殊な処理をしたり、エッジを表示したりするテストです。

G-Bufferの出力は、前回と同じRenderGBuffer.shaderを使用しています。

手順
1. カメラにDrawEdgeTest.csを割り当てる
DrawEdgeTest.cs
2. ShaderにCustum/DrawEdgeを割り当てたマテリアルを準備する
DrawEdge.shader
3. SSS Matのところに上記マテリアルを割り当てる

後は前の手順なども併せて適当に色々やった気がします。

実行結果


TargetMatNoのところをいじると、マテリアルの境目に赤いエッジが表示されます。これはG-Bufferに出力したマテリアル番号にラプラシアンフィルタを掛けて閾値以上の所を赤色にしていたと思います。

TargetMatListの所に追加したマテリアルは、今回は青色にする処理だけを行っています。このような感じで、処理対象とするマテリアル番号を渡すようにすれば、特定のマテリアルだけに何らかの処理が可能となります。

この辺の処理は重そうで75fpsはきつそうなので、そろそろOculus Rift関係に戻ろうかと思います。

web拍手 by FC2
posted by シンドラー at 01:06 | Comment(0) | TrackBack(0) | Unity 5 | このブログの読者になる | 更新情報をチェックする

2015年10月03日

録音のテスト

いつの間にか10月ですね。困ったものです。

画像や音声の処理をする場合の補助として、切出しやキャプチャツールみたいなものを時間がある時に作っていました。今回は録音のテストです。この辺りはWindows 10になると動かなくなったりするんでしょうかね。

参考サイト[1][2]を見れば特に問題ないかと思います。ステレオミキサーを使うみたいですので、無効になっている場合は[3]等を参考に有効化します。

[1][2]はWindowsアプリケーションで作成していて、コンソールアプリケーションで作成している例が見当たらなかった(ちゃんと探してませんが)ので、そちらで作成してみました。

そのため、なるべくウィンドウプロシージャは使いたくなかったのでコールバック関数[4]を一つ使うようにしてみました。これで合っているのかどうかはわかりません。

基本は[1]のソースコードを[2]を参考に複数バッファ・動的サイズ変更できるようにHeapReAlloc[5]関数を使うように修正した感じです。

以下ソース。エラー処理などもしてません。何か問題があっても責任は取りません。
WaveTestConsole.cpp

WAVEを再生すると音が小さくなってる気がするのですが原因などはよくわかりません。

参考サイト
[1] 入力デバイスによる録音
[2] 音声の入力
[3] パソコンで流れる音を録音する方法(ステレオミキサー)<Windows(R)7>
[4] waveInProc
[5] HeapReAlloc
web拍手 by FC2
posted by シンドラー at 15:20 | Comment(0) | TrackBack(0) | OpenAL | このブログの読者になる | 更新情報をチェックする