最近FaceTrakingをいろいろやっていますが、やっとメインともいえる3Dデータを表示してみます。今回はOpenGLを利用するので、直前のエントリの環境を作っていることを前提としています。
以前までで顔が検出できる状態なっており、ここから3Dの点を取得および、構成する三角形のインデックスを取得します。具体的には次のような手順になります。
- IFTFaceTracker::GetFaceModel()で検出されたモデルをIFTModelに取得する
- 3Dの頂点をIFTModel::Get3DShape()で取得する
- 三角形の構成するための頂点のインデックスをIFTModel::GetTriangles()で取得する
- 取得した三角形の情報をもとにOpenGL上に表示する
検出されたモデルをIFTModelに取得する
最初に検出されたモデルをIFTModelに取得します。IFTModelはIFTFaceTracker::GetFaceModel()で取得できますので、これを呼び出します。
// 顔追跡(公開用)void faceTracking()
{
// 顔追跡(抜粋)
HRESULT hr = faceTracking_p();
// 顔を見つけたので、追跡状態へ遷移
if(SUCCEEDED(hr) && SUCCEEDED(pFTResult->GetStatus())) {
::OutputDebugString( L"FaceTracking Success\n" );
isFaceTracked = true;
pFT->GetFaceModel( &pFTModel );
}
// 顔を見失ったので、未追跡状態のまま
else {
::OutputDebugString( L"FaceTracking failed\n" );
isFaceTracked = false;
}
}
3Dの点を取得する
点の取得は3段階になります。
- IFTModel::Get3DShape()ではIFTResult::Get3DPose()で得られるパラメーター(顔の角度など)が必要になるので、これらを取得する
- 頂点を表すVertex、SU(Shape Unit)、AU(Animation Unit)の配列を作成する
- 上記パラメータを引数にして、IFTModel::Get3DShape()を呼び出す
FLOAT scale = 0.0f;FLOAT rotation[3] = { 0 };
FLOAT transration[3] = { 0 };
kinect.getResult()->Get3DPose( &scale, rotation, transration );
auto model = kinect.getFaceModel();
std::vector vectors(model->GetVertexCount());
std::vector su( model->GetSUCount() );
std::vector au( model->GetAUCount() );
auto hr = model->Get3DShape(&su[0], su.size(), &au[0], au.size(),
scale, rotation, transration, &vectors[0], vectors.size());
三角形を構成するためのインデックスを取得する
続いて三角形の頂点情報を取得します。これは内部のデータ列を利用するので、それらを格納する器を渡します。
UINT triangleCount = 0;FT_TRIANGLE* triangles = 0;
hr = model->GetTriangles( &triangles, &triangleCount );
取得した三角形の情報をもとにOpenGL上に表示する
ここまでで表示するためのデータがそろいました。取得した三角形の頂点データをすべて描画することで、3Dのモデルを表示することができます。
auto vertex = []( FT_VECTOR3D& v ){auto scale = 5;
GLdouble vertex[3] = { v.x * scale, v.y * scale, v.z };
glVertex3dv(vertex);
};
for ( int i = 0; i < triangleCount; ++i ) {
vertex( vectors[triangles[i].i] );
vertex( vectors[triangles[i].j] );
vertex( vectors[triangles[i].k] );
}
ここでは触れなかったパラメーターや、このデータでは方向は取れるのですが、口などの動きが取れていないようなので、それらのパラメータは別途調査という感じですね。
OpenGLの使い方で改善点などあればコメントいただけると嬉しいです。