Kinect を脇に置かずに、OpenCV を使用して特定のデータセットを操作しています。そして、指定された深度データを対応するRGBにマップしたいと思います(実際の色と深度を取得できるように)
私は OpenCV と C++ を使用しており、Kinect を所有していないため、残念ながら公式の Kinect API から MapDepthFrameToColorFrame メソッドを利用できません。
指定されたカメラの固有値と歪み係数から、深さをワールド座標にマッピングし、ここで提供されているアルゴリズムに基づいて RGB に戻すことができました
Vec3f depthToW( int x, int y, float depth ){
Vec3f result;
result[0] = (float) (x - depthCX) * depth / depthFX;
result[1] = (float) (y - depthCY) * depth / depthFY;
result[2] = (float) depth;
return result;
}
Vec2i wToRGB( const Vec3f & point ) {
Mat p3d( point );
p3d = extRotation * p3d + extTranslation;
float x = p3d.at<float>(0, 0);
float y = p3d.at<float>(1, 0);
float z = p3d.at<float>(2, 0);
Vec2i result;
result[0] = (int) round( (x * rgbFX / z) + rgbCX );
result[1] = (int) round( (y * rgbFY / z) + rgbCY );
return result;
}
void map( Mat& rgb, Mat& depth ) {
/* intrinsics are focal points and centers of camera */
undistort( rgb, rgb, rgbIntrinsic, rgbDistortion );
undistort( depth, depth, depthIntrinsic, depthDistortion );
Mat color = Mat( depth.size(), CV_8UC3, Scalar(0) );
ushort * raw_image_ptr;
for( int y = 0; y < depth.rows; y++ ) {
raw_image_ptr = depth.ptr<ushort>( y );
for( int x = 0; x < depth.cols; x++ ) {
if( raw_image_ptr[x] >= 2047 || raw_image_ptr[x] <= 0 )
continue;
float depth_value = depthMeters[ raw_image_ptr[x] ];
Vec3f depth_coord = depthToW( y, x, depth_value );
Vec2i rgb_coord = wToRGB( depth_coord );
color.at<Vec3b>(y, x) = rgb.at<Vec3b>(rgb_coord[0], rgb_coord[1]);
}
}
しかし、結果はずれているようです。データセットは 3 つの異なる Kinect から取得され、それぞれが異なる方向にずれているため、翻訳を手動で設定することはできません。以下にその 1 つを示します (左: 歪みのない RGB、中央: 歪みのない深さ、右: RGB を深さにマッピング)
私の質問は、この時点で何をすべきかということです。デプスをワールドに、またはワールドを RGB に投影しようとしているときに、手順を間違えましたか? ステレオカメラの経験がある人は、私の失敗を指摘できますか?