我已经在这个问题上工作了很长一段时间,并且我的创造力已经结束了,所以希望其他人可以帮助我指出正确的方向。我一直在使用Kinect并尝试将数据捕获到MATLAB。幸运的是,有很多方法可以这样做(我目前正在使用http://www.mathworks.com/matlabcentral/fileexchange/30242-kinect-matlab)。当我试图将捕获的数据投影到3D时,我的传统方法给出了很差的重建结果。
简而言之,我最终为matlab编写了一个Kinect SDK包装器,用于执行重建和对齐。重建就像一场梦,但是......
我在对齐方面遇到了很多麻烦,你可以在这里看到:
请不要过分关注模特:(。
如您所见,对齐方式不正确。我不确定为什么会这样。我已经阅读了很多论坛,其他人使用相同的方法比我更成功。
我目前的管道是使用Kinect Matlab(使用Openni)捕获数据,使用Kinect SDK重建,然后使用Kinect SDK(通过NuiImageGetColorPixelCoordinateFrameFromDepthPixelFrameAtResolution)进行对齐。我怀疑这可能是由于Openni,但我在创建使用Kinect SDK进行捕获的mex函数调用方面收效甚微。
如果有人能指出我应该深入研究的方向,那将非常感激。
编辑:
图我应该发布一些代码。这是我用于对齐的代码:
/* The matlab mex function */
void mexFunction( int nlhs, mxArray *plhs[], int nrhs,
const mxArray *prhs[] ){
if( nrhs < 2 )
{
printf( "No depth input or color image specified!\n" );
mexErrMsgTxt( "Input Error" );
}
int width = 640, height = 480;
// get input depth data
unsigned short *pDepthRow = ( unsigned short* ) mxGetData( prhs[0] );
unsigned char *pColorRow = ( unsigned char* ) mxGetData( prhs[1] );
// compute the warping
INuiSensor *sensor = CreateFirstConnected();
long colorCoords[ 640*480*2 ];
sensor->NuiImageGetColorPixelCoordinateFrameFromDepthPixelFrameAtResolution(
NUI_IMAGE_RESOLUTION_640x480, NUI_IMAGE_RESOLUTION_640x480,
640*480, pDepthRow, 640*480*2, colorCoords );
sensor->NuiShutdown();
sensor->Release();
// create matlab output; it's a column ordered matrix ;_;
int Jdimsc[3];
Jdimsc[0]=height;
Jdimsc[1]=width;
Jdimsc[2]=3;
plhs[0] = mxCreateNumericArray( 3, Jdimsc, mxUINT8_CLASS, mxREAL );
unsigned char *Iout = ( unsigned char* )mxGetData( plhs[0] );
for( int x = 0; x < width; x++ )
for( int y = 0; y < height; y++ ){
int idx = ( y*width + x )*2;
long c_x = colorCoords[ idx + 0 ];
long c_y = colorCoords[ idx + 1 ];
bool correct = ( c_x >= 0 && c_x < width
&& c_y >= 0 && c_y < height );
c_x = correct ? c_x : x;
c_y = correct ? c_y : y;
Iout[ 0*height*width + x*height + y ] =
pColorRow[ 0*height*width + c_x*height + c_y ];
Iout[ 1*height*width + x*height + y ] =
pColorRow[ 1*height*width + c_x*height + c_y ];
Iout[ 2*height*width + x*height + y ] =
pColorRow[ 2*height*width + c_x*height + c_y ];
}
}
答案 0 :(得分:5)
这是立体视觉系统的众所周知的问题。我有一段时间遇到同样的问题。我发布的原始问题可以找到here。我试图做的有点类似于此。然而,经过大量研究,我得出的结论是,捕获的数据集不能轻易对齐。
另一方面,在记录数据集时,您可以轻松使用函数调用来对齐RGB和深度数据。这个方法在OpenNI和Kinect SDK中都可用(功能相同,而函数调用的名称各不相同)
您似乎正在使用Kinect SDK捕获数据集,以便将数据与您可以使用的Kinect SDK对齐MapDepthFrameToColorFrame。
由于您还提到过使用OpenNI,请查看AlternativeViewPointCapability。
我没有使用Kinect SDK的经验,但是在使用OpenNI v1.5时,通过在注册记录器节点之前进行以下函数调用来解决整个问题:
depth.GetAlternativeViewPointCap().SetViewPoint(image);
其中image
是图像生成器节点,depth
是深度生成器节点。这是旧的SDK已被OpenNI 2.0 SDK取代。因此,如果您使用的是最新的SDK,则函数调用可能会有所不同,但整个过程可能类似。
我还添加了一些示例图片:
不使用上述对齐函数调用RGB上的深度边缘未对齐
使用函数调用时,深度边缘完全对齐(有一些红外阴影区域显示一些边缘,但它们只是无效的深度区域)
答案 1 :(得分:1)
depth.GetAlternativeViewPointCap()。SetViewPoint(image);
效果很好,但问题是它缩小了深度图像(通过FOCAL_rgb / FOCAL_kinect)并将深度像素移位差异d =焦点* B / z;根据出厂设置,可能还会有轻微的旋转。
因此,如果不撤消这些转换,就无法恢复所有3个真实世界坐标。这就是说,不依赖于精确的x,y并且仅考虑z(例如分割)的方法即使在移位的移位图中也可以很好地工作。此外,他们可以利用颜色和深度来执行更好的分割。
答案 2 :(得分:1)
通过使用Kinect SDK读取U,V纹理贴图参数,您可以轻松对齐深度框架和颜色框架。对于深度帧D(i,j)的每个像素坐标(i,j),颜色帧的对应像素坐标由(U(i,j),V(i,j))给出,因此给出颜色通过C(U(i,j),V(i,j))。
U,V功能包含在每个Kinect的硬件中,它们从Kinect到Kinect不同,因为Depth相机与摄像机的对齐方式不同,因为在工厂硬件板上粘合时会有微小的差异。但是如果您从Kinect SDK中读取U,V,则不必担心。
下面我将使用带有J4K open source library的Java中的Kinect SDK为您提供一个图像示例和一个实际的源代码示例:
public class Kinect extends J4KSDK{
VideoFrame videoTexture;
public Kinect() {
super();
videoTexture=new VideoFrame();
}
@Override
public void onDepthFrameEvent(short[] packed_depth, int[] U, int V[]) {
DepthMap map=new DepthMap(depthWidth(),depthHeight(),packed_depth);
if(U!=null && V!=null) map.setUV(U,V,videoWidth(),videoHeight());
}
@Override
public void onVideoFrameEvent(byte[] data) {
videoTexture.update(videoWidth(), videoHeight(), data);
} }
图像示例显示了相同Depth-Video对齐帧的3个不同视角:
我希望这对你有帮助!