2016年07月22日

ビットマップフォントに関するメモ

ここのところ月1回しか更新してないですね…。困ったものです。

今日はビットマップフォントに関するメモです。画面や画像に文字を表示する方法は、OpenGLやOpenCVなどにも用意されているので、それを使えば問題ないかと思います。今回のメモはライブラリ等を使わずに無理矢理表示するためのものです。

フォントについては、大きく分けてビットマップフォントとアウトラインフォントがあります。綺麗な文字を描きたいのであればアウトラインフォントだと思いますが、今回は簡単のためビットマップフォントを使用します。

フォントに関しては、ライセンスに気を付ける必要があります。今回は[1]のm+ fontsを使用させていただくことにしました。

こちらのフォントですが、BDFというファイルフォーマットのフォントデータがあります。BDFはBitmap Distribution Formatの略のようで、UNIXで標準的に使用されていたフォーマットのようです。

テキストベースのファイルフォーマットですが、自分で読み込むのも面倒ですので、[2]のbdf2bmpというソフトウェアを使用させていただき、bdfファイルをbmpファイルに変換しました。

後は文字ごとに切り出して拡大/縮小し、白:背景、黒:文字として元の画像にmixしてあげれば画像上に文字を描くことができます。

実行結果

Lenna画像上にHello worldを表示してみました。

chartest.png

[1] m+ fonts
[2] bdf2bmp
web拍手 by FC2
posted by シンドラー at 19:00 | Comment(0) | TrackBack(0) | Image Processing | このブログの読者になる | 更新情報をチェックする

2016年06月02日

平面の方程式に関するメモ

前回のソースコードで自分で追加した部分に関するメモです。間違っていたら教えてください。



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

2016年05月31日

libiglの使い方メモ その4

いつの間にか5月も終わりですね…。来月からはもう少し更新するようにしたいです。今回は前回の続き+αで、展開したテクスチャにAO計算した結果を焼き込んでみました。

1. Camelheadを読み込む
2. 前回と同じ方法でUV展開
3. Example 606を参考にAmbient Oculusionの計算
4. 各ポリゴンのテクスチャ画像上の座標とAO値を3次元ベクトル(tx*texSize, ty*texSize, ao)としてラスタライズ[1]〜[3]
5. テクスチャにラスタライズ結果のAO値を出力
6. UV値やテクスチャ情報を含むモデルとしてCamelheadを出力

ラスタライズに関しては、[3]のものをEigenを使ったものに書き換えたのと、[2][3]を参考にz値を補間するように追加しました。注意点としては、今回参考にしたラスタライザはおそらく右手系、ポリゴンは反時計回り順を想定していますので、テクスチャ座標も左回りになるように外積を使って判定する必要があります(頂点座標が左回りでも、対応するテクスチャ座標が左回りになっているとは限りません)。判定して右回りの場合は、ラスタライザに渡す頂点の順番を入れ替えます。

実行結果

CamelheadのテクスチャとしてAO情報を出力した結果
libigl004_camelhead1.png

MeshLabで出力したテクスチャ付きモデルを表示した結果libigl004_camelhead2.png
光源なし・テクスチャなし
libigl004_camelhead3.png
光源なし・テクスチャあり
libigl004_camelhead4.png
光源あり・テクスチャあり

耳や口のあたりはテクスチャ展開の結果の影響もあってあまりきれいじゃないですね。目の周りあたりはそれなりにうまくいっている気がします。

[1] http://ushiroad.com/rasterizer-refs/
[2] http://memo.render.jp/tekitou-hon-yaku-memo/re
[3] http://forum.devmaster.net/t/advanced-rasterization/6145
続きを読む
web拍手 by FC2
posted by シンドラー at 18:28 | Comment(0) | TrackBack(0) | OpenGL & Metasequoia | このブログの読者になる | 更新情報をチェックする

2016年04月30日

libiglについてのメモ その3

いつの間にか4月が終わって5月ですね。困ったものです。月1回は更新しておきたいので小ネタです。チュートリアルの501〜503ですが、UV展開のようなサンプルがあります。ただ、サンプルのcamelhead以外では、boundary_loopの所でエラー終了してしまうので、凸包など、何か適用できる条件があるのかもしれません。

harmonic関数で、展開したUVの計算ができるようです。その際、5番目の引数で展開方法が選べるようです。
(1: harmonic function, 2: biharmonic, 3: triharmonic, ...)

igl::harmonic(V, F, bnd, bnd_uv, 1, V_uv);

実行結果

数値を変えて画像として出力した結果です。V_uvは各頂点のUV座標ですが、0〜1の範囲ではなく、今回の結果では-1.2〜1.1等中途半端な値になっていましたので、適切に0〜1の間にマッピングする必要がありそうです。


libigl_camelhead1.png libigl_camelhead2.png libigl_camelhead3.png
   1: harmonic      2: biharmonic      3: triharmonic

次はAOを計算してテクスチャに焼き込むテストでもするかもしれません。

[1] http://libigl.github.io/libigl/tutorial/tutorial.html
web拍手 by FC2
posted by シンドラー at 23:20 | Comment(0) | TrackBack(0) | OpenGL & Metasequoia | このブログの読者になる | 更新情報をチェックする

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 | このブログの読者になる | 更新情報をチェックする