我正在使用Kinect创建一个人的3D模型。我得到的是这样的:
我将它导出到Wavefront .obj文件。但我只对脸本身感兴趣,并希望删除它周围的一切。由于Kinect有RGB相机,我可以毫无问题地进行RGB人脸检测。但是这给了我一个包含面部的640x480图像内的矩形,我该如何将其转换为3D网格?
答案 0 :(得分:3)
我前段时间做过类似的事情:
视频here
我所做的很简单:
理想情况下,您可以校准两个(rgb,深度)流。
我使用的是libreenect,但这种技术应该适用于OpenNI,KinectSDK。
我注意到你的应用程序的标题是KinectFusion所以我猜你是从Microsoft Kinect SDK 1.7中的Kinect Fusion示例开始的。应该有一个内置函数来对齐rgb和深度流。关于CV部分,您可以在线找到Kinect to OpenCV Mat转换,例如Dennis Ippel functions。 EgmuCV也有面部检测。并且KinectSDK本身允许您以3D形式跟踪面部,因此我必须在SDK中进行面部检测(甚至不是跟踪)。我自己没有充分使用Kinect SDK,所以目前还不能更具体。
简而言之:
答案 1 :(得分:0)
这是我用来获取Depthstream并使用Fusion处理它的代码:
void processDepth()
{
NUI_IMAGE_FRAME depthFrame = { 0 };
ERROR_CHECK( kinect->NuiImageStreamGetNextFrame( depthStreamHandle, 0, &depthFrame ) );
BOOL nearMode = FALSE;
INuiFrameTexture *frameTexture = 0;
kinect->NuiImageFrameGetDepthImagePixelFrameTexture( depthStreamHandle, &depthFrame, &nearMode, &frameTexture );
NUI_LOCKED_RECT depthData = { 0 };
frameTexture->LockRect( 0, &depthData, 0, 0 );
if ( depthData.Pitch == 0 ) {
std::cout << "zero" << std::endl;
}
processKinectFusion( (NUI_DEPTH_IMAGE_PIXEL*)depthData.pBits, depthData.size);
ERROR_CHECK( kinect->NuiImageStreamReleaseFrame( depthStreamHandle, &depthFrame ) );
}
void processKinectFusion( const NUI_DEPTH_IMAGE_PIXEL* depthPixel, int depthPixelSize)
{
// DepthImagePixel
HRESULT hr = ::NuiFusionDepthToDepthFloatFrame( depthPixel, width, height, m_pDepthFloatImage,
NUI_FUSION_DEFAULT_MINIMUM_DEPTH, NUI_FUSION_DEFAULT_MAXIMUM_DEPTH, TRUE );
if (FAILED(hr)) {
throw std::runtime_error( "::NuiFusionDepthToDepthFloatFrame failed." );
}
Matrix4 worldToBGRTransform = { 0.0f };
worldToBGRTransform.M11 = 256 / 512;
worldToBGRTransform.M22 = 256 / 384;
worldToBGRTransform.M33 = 256 / 512;
worldToBGRTransform.M41 = 0.5f;
worldToBGRTransform.M42 = 0.5f;
worldToBGRTransform.M44 = 1.0f;
Matrix4 worldToCameraTransform;
m_pVolume->GetCurrentWorldToCameraTransform( &worldToCameraTransform );
hr = m_pVolume->ProcessFrame( m_pDepthFloatImage, NUI_FUSION_DEFAULT_ALIGN_ITERATION_COUNT,
NUI_FUSION_DEFAULT_INTEGRATION_WEIGHT, &worldToCameraTransform );
worldToCameraTransform;
if (FAILED(hr)) {
++trackingErrorCount;
if ( trackingErrorCount >= 100 ) {
trackingErrorCount = 0;
m_pVolume->ResetReconstruction( &IdentityMatrix(), nullptr );
}
return;
}
// PointCloud
hr = m_pVolume->CalculatePointCloud( m_pPointCloud, &worldToCameraTransform );
if (FAILED(hr)) {
throw std::runtime_error( "CalculatePointCloud failed." );
}
// PointCloud
hr = ::NuiFusionShadePointCloud( m_pPointCloud, &worldToCameraTransform,
&worldToBGRTransform, m_pShadedSurface, nullptr );
if (FAILED(hr)) {
throw std::runtime_error( "::NuiFusionShadePointCloud failed." );
}
INuiFrameTexture * pShadedImageTexture = m_pShadedSurface->pFrameTexture;
NUI_LOCKED_RECT ShadedLockedRect;
hr = pShadedImageTexture->LockRect(0, &ShadedLockedRect, nullptr, 0);
if (FAILED(hr)) {
throw std::runtime_error( "LockRect failed." );
}
pShadedImageTexture->UnlockRect(0);
}
};
现在我认为最好的方法是编辑/裁剪depthData.pBits。但我不知道该怎么做。