読者です 読者をやめる 読者になる 読者になる

プログラミングライダー

プログラミングや趣味のバイクをメモします

openFrameworksでRealSenseSDKを使ったフェイストラッキングをやってみた件

まずは環境の説明から

OS:Win7 x64
IDE:VS2013 ※VS2012推奨
SDK:RSSDK

初期化の方法は以下
カメラのキャプチャイメージも必要なので一緒に取得しています。

// セッションハンドラ
PXCSession* session;
// カメラデバイス
vector<PXCCapture::DeviceInfo> cam_dev;
// マネージャ
PXCSenseManager* pxc_mag;
// フェイスアウトプット
PXCFaceData* mOutput;

// トラッキングポイントのカウンタ
int point_count;
// トラッキングポイント配列
PXCFaceData::LandmarkPoint* landmarkdata;

// 取得するイメージのサイズ
int width, height;
width = 1280;
height = 720;

// センサー取得
session = PXCSession::CreateInstance();

// デバイスの取得
{
	PXCSession::ImplDesc desc;
	memset( &desc, 0, sizeof(desc) ); 
	desc.group = PXCSession::IMPL_GROUP_SENSOR;
	desc.subgroup = PXCSession::IMPL_SUBGROUP_VIDEO_CAPTURE;

	PXCSession::ImplDesc desc1;
	if( session->QueryImpl(&desc, 0, &desc1) < PXC_STATUS_NO_ERROR ) return;

	PXCCapture *capture;
	if( session->CreateImpl<PXCCapture>(&desc1, &capture) < PXC_STATUS_NO_ERROR ) return;

	cam_dev.clear();
	for( int j = 0; ; ++j ) 
	{
		PXCCapture::DeviceInfo deviceInfo;
		if (capture->QueryDeviceInfo(j, &deviceInfo) < PXC_STATUS_NO_ERROR) 
			break;

		cam_dev.push_back( deviceInfo );
	}
	capture->Release();
}

// センサーマネージャのインスタンスを取得
pxc_mag = PXCSenseManager::CreateInstance();

// キャプチャマネージャの取得
PXCCaptureManager* cap = pxc_mag->QueryCaptureManager();

// カメラが複数個存在する場合
// とりあえず0番目を設定
if( cam_dev.size() > 1 )
{
	cap->FilterByDeviceInfo( &cam_dev[0] );
}
	
// フェイストラッキングの有効化
pxc_mag->EnableFace();

// フェイスモジュールの取得
PXCFaceModule* face = pxc_mag->QueryFace();

// フェイスコンフィグパラメータの取得
PXCFaceConfiguration* config = face->CreateActiveConfiguration();

// コンフィグ設定
{
	config->SetTrackingMode( PXCFaceConfiguration::TrackingModeType::FACE_MODE_COLOR );
	config->detection.isEnabled = true;
	config->landmarks.isEnabled = true;
	config->pose.isEnabled = true;
	config->QueryExpressions()->DisableAllExpressions();
	config->QueryExpressions()->Disable();
	config->ApplyChanges();

	point_count = config->landmarks.numLandmarks;
	landmarkdata = new PXCFaceData::LandmarkPoint[point_count];
}

// キャプチャ設定
{
	PXCCapture::Device::StreamProfileSet set;
	memset(&set, 0, sizeof(set));
	set.color.imageInfo.width = width;
	set.color.imageInfo.height = height;
	cap->FilterByStreamProfiles(&set);
}

// カラーストリームの設定
if( !(pxc_mag->EnableStream(PXCCapture::STREAM_TYPE_COLOR, width, height, 30) >= PXC_STATUS_NO_ERROR) ) return;

// マネージャ初期化
pxc_mag->Init();

// フェイスアウトプットを取得
mOutput = face->CreateOutput();

次に更新処理

// ビデオテクスチャ
ofTexture video_tex;
ofPixels video_pix;

// トラッキング情報
bool isTracking;
ofRectangle face_rect;

int landmaerk_err_count;

// 画像の更新
if( pxc_mag->AcquireFrame( true ) >= PXC_STATUS_NO_ERROR )
{
	PXCCapture::Sample *cSample = pxc_mag->QuerySample();

	if (!cSample)
		return;

	PXCImage *cRgbImage = cSample->color;
	if (cRgbImage)
	{
		PXCImage::ImageData cRgbData;
		if( cRgbImage->AcquireAccess(PXCImage::ACCESS_READ, PXCImage::PIXEL_FORMAT_RGB32, &cRgbData) >= PXC_STATUS_NO_ERROR )
		{
			// フェイスの更新
			mOutput->Update();

			uint8_t *cBuffer = cRgbData.planes[0];
			video_pix.setFromPixels(cBuffer, width, height, 4);

			cRgbImage->ReleaseAccess(&cRgbData);
		}
	}

	pxc_mag->ReleaseFrame();
}

// ピクセル情報をテクスチャにコピー
video_tex.loadData( video_pix.getPixels(), width, height, GL_BGRA );

// フェイスデータを取得
isTracking = false;
int numFaces = mOutput->QueryNumberOfDetectedFaces();
if( numFaces > 0 )
{
	PXCFaceData::Face* tracked = mOutput->QueryFaceByIndex( 0 );

	// フェイスの座標を取得
	{
		PXCFaceData::DetectionData* detection = tracked->QueryDetection();
		PXCRectI32 rect;
		detection->QueryBoundingRect( &rect );
		face_rect.x = rect.x; face_rect.y = rect.y; face_rect.width = rect.w; face_rect.height = rect.h;
	}

	// ランドマークポイントの取得
	{
		PXCFaceData::LandmarksData* landmark = tracked->QueryLandmarks();
		pxcI32 numPoints = landmark->QueryNumPoints();
		if( landmark != NULL )
		{
			// トラッキングの有効化
			isTracking = true;
			landmark->QueryPoints( landmarkdata );

			bool err = false;
			for (int i = 0; i < numPoints; ++i) 
			{
				// >>>>ここにランドマーク情報を取得する記述をする<<<<

				if( !err && !landmarkdata[i].confidenceImage )
				{
					err = true;
				}
			}

			if( err ) landmaerk_err_count++;
			else landmaerk_err_count = 0;
		}
	}
}
else
{
	// フェイスを識別できてない場合エラーカウントをリセット
	landmaerk_err_count = 0;
}

// エラーが3秒以上持続する場合
if( landmaerk_err_count > 90 )
{
	// デバイスを閉じる
	pxc_mag->Close();
	pxc_mag->Release();

	// デバイスの再起動
	// 上記の初期化メソッドを呼び出している
	setupdev();

	landmaerk_err_count = 0;
}	

キャプチャしたイメージの更新とトラッキング情報の更新ともう一つ
ラッキング情報が外れた際に再認識ができなくなってしまう時がある
そのためlandmaerk_err_countが一定以上になった時システムを再起動するように
細工をしておいた。

以上の処理でフェイストラッキングを行うことができるはずです。
フェイストラッキングは普段使っているWebカメラでも大丈夫でした!