12

OpenCV と Libfreenect を使用している C++ プロジェクトがあります。OpenNI のように大きくて重いものを含めて、その過程で OpenCV インストールの依存関係を作成したくありません。ここで提供されるキャリブレーション情報を使用して、RGB 画像と深度画像の歪みを解消し、整列させたいと考えています。

カメラ マトリックスと歪み係数に基づいて画像を個別に歪みを補正するのは簡単でした。しかし、今では、整流行列と射影行列を使用して RGB と深度画像を整列させる方法について混乱しているため、基本的に同じ視点から同じものを表示できます。かなり長い間探し回った後、OpenCV でどのように動作するかの流れを確立できません。reprojectImageTo3D( )warpPerspective()が使用される可能性があるという漠然とした見積もりですが、その方法はわかりません。

この問題にどのようにアプローチできますか?古い XBOX360 Kinect を使用しています (生の視差値の範囲は 0 ~ 2047 です)。

アップデート

これまでに書いた部分的なコードは次のとおりです。

// I use callback functions to get RGB (CV_8UC3) and depth (CV_16UC1)
// I undistort them and call the following method
void AlignImages(cv::Mat& pRGB, cv::Mat& pDepth) {

    rotationMat = (cv::Mat_<double_t>(3,3) << 9.9984628826577793e-01, 1.2635359098409581e-03, -1.7487233004436643e-02, -1.4779096108364480e-03, 9.9992385683542895e-01, -1.2251380107679535e-02, 1.7470421412464927e-02, 1.2275341476520762e-02, 9.9977202419716948e-01);
    translationMat = (cv::Mat_<double_t>(3,1) << 1.9985242312092553e-02, -7.4423738761617583e-04, -1.0916736334336222e-02);


    // make a copy in float to convert raw depth data to physical distance
    cv::Mat tempDst;
    pDepth.convertTo(tempDst, CV_32F);

    // create a 3 channel image of precision double for the 3D points
    cv::Mat tempDst3D = cv::Mat(cv::Size(640, 480), CV_64FC3, double(0));

    float_t* tempDstData = (float_t*)tempDst.data;
    double_t* tempDst3DData = (double_t*)tempDst3D.data;

    size_t pixelSize = tempDst.step / sizeof(float_t);
    size_t pixel3DSize = tempDst3D.step / sizeof(double_t);

    for (int row=0; row < tempDst.rows; row++) {
        for (int col=0; col < tempDst.cols; col++) {

            // convert raw depth values to physical distance (in metres)
            float_t& pixel = tempDstData[pixelSize * row + col];
            pixel = 0.1236 * tanf(pixel/2842.5 + 1.1863);

            // reproject physical distance values to 3D space
            double_t& pixel3D_X = tempDst3DData[pixel3DSize * row + col];
            double_t& pixel3D_Y = tempDst3DData[pixel3DSize * row + col +1];
            double_t& pixel3D_Z = tempDst3DData[pixel3DSize * row + col + 2];

            pixel3D_X = (row - 3.3930780975300314e+02) * pixel / 5.9421434211923247e+02;
            pixel3D_Y = (col - 2.4273913761751615e+02) * pixel / 5.9104053696870778e+02;
            pixel3D_Z = pixel;

        }
    }

    tempDst3D = rotationMat * tempDst3D + translationMat;
}

数値を変数に割り当てる代わりに直接使用しましたが、ロジックを理解する上で問題になることはありません。この時点で、次のことを行うことになっています。

P2D_rgb.x = (P3D'.x * fx_rgb / P3D'.z) + cx_rgb
P2D_rgb.y = (P3D'.y * fy_rgb / P3D'.z) + cy_rgb

しかし、私はそれをどのように行うべきか正確にはわかりません。たぶん、私は完全に間違った方向に進んでいます。しかし、これが行われた例は見つかりません。

4

2 に答える 2

2

opencv_contrib (rgbd モジュール) に、外部カメラに深度を登録する RGBD 登録関数が追加されました: https://github.com/Itseez/opencv_contrib/commit/f5ef071c117817b0e98b2bf509407f0c7a60efd7

于 2016-01-11T14:15:23.050 に答える