1

Kinectセンサーを使用した3Dモデル再構築アプリケーションに取り組んでいます。Microsoft SDKを使用して深度データを取得していますが、実際の各ポイントの位置を計算したいと思います。私はそれについていくつかの記事を読み、いくつかの深度キャリブレーション方法を実装しましたが、それらのすべてが私のアプリケーションでは機能しません。最も近いキャリブレーションはhttp://openkinect.org/wiki/Imaging_Information でしたが、Meshlabでの私の結果は受け入れられませんでした。私はこの方法で深度値を計算します:

    private double GetDistance(byte firstByte, byte secondByte)
    {
        double distance = (double)(firstByte >> 3 | secondByte << 5);
        return distance;
    }

次に、以下の方法を使用して実世界の距離を計算しました

    public static float RawDepthToMeters(int depthValue)
    {
        if (depthValue < 2047)
        {
            return (float)(0.1 / ((double)depthValue * -0.0030711016 + 3.3309495161));
        }
        return 0.0f;
    }

    public static Point3D DepthToWorld(int x, int y, int depthValue)
    {
        const double fx_d = 5.9421434211923247e+02;
        const double fy_d = 5.9104053696870778e+02;
        const double cx_d = 3.3930780975300314e+02;
        const double cy_d = 2.4273913761751615e+02;

        double depth = RawDepthToMeters(depthValue);
        Point3D result = new Point3D((float)((x - cx_d) * depth / fx_d),
                        (float)((y - cy_d) * depth / fy_d), (float)(depth));
                return result;
    }

これらの方法はうまく機能せず、生成されたシーンは正しくありませんでした。次に、以下の方法を使用しました。結果は以前の方法よりも優れていますが、まだ受け入れられません。

    public static Point3D DepthToWorld(int x, int y, int depthValue)
    {
        const int w = 640;
        const int h = 480;
        int minDistance = -10;
        double scaleFactor = 0.0021;
        Point3D result = new Point3D((x - w / 2) * (depthValue + minDistance) *     scaleFactor * (w/h),
(y - h / 2) * (depthValue + minDistance) * scaleFactor,depthValue);    
        return result;
    } 

私の方法で計算した深度ピクセル値に基づいて実際の位置を計算するにはどうすればよいか教えていただけませんか。

4

1 に答える 1

1

実際のgetDistance()深度を計算するために使用している関数は、kinectプレーヤーの検出と呼ばれます。したがって、それに応じてkinectストリームを開いていることを確認してください。そうでない場合は、生の深度データのみを取得する必要があります。

Runtime nui = Runtime.Kinects[0] ;
nui.Initialize(RuntimeOptions.UseDepth);
nui.DepthStream.Open(
   ImageStreamType.Depth, 
   2, 
   ImageResolution.Resolution320x240, 
   ImageType.Depth);

次に、2番目のバイトを8だけビットシフトして深度を計算します。

距離(0,0)=(int)(Bits [0] | Bits [1] << 8);

StéphaneMagnenatによって与えられたより良い近似を使用して少し改善を行うことができたとしても、最初のキャリブレーション方法は問題なく機能するはずです。

距離=0.1236* tan(rawDisparity / 2842.5 + 1.1863)(メートル単位)

より正確なキャリブレーション値が本当に必要な場合は、たとえばmatlabkinectキャリブレーションなどのツールを使用してkinectを実際にキャリブレーションする必要があります。

http://sourceforge.net/projects/kinectcalib/

そして、現在使用しているニコラス・ブッラスが提供する値で、取得した値を再確認します。

編集

もう一度質問を読んで、Microsoft SDKを使用していることに気付きました。そのため、 kinectセンサーから返される値は、すでにmm単位の実際の距離です。この関数を使用する必要はありませんRawDepthToMeters()。非公式のSDKでのみ使用する必要があります。

ハードウェアは、視差値の非線形関数であり、11ビットの精度を持つ深度マップを作成します。kinect sdkドライバーは、箱から出してこの視差値をmmに変換し、整数に丸めます。MS Kinect SDKの深度範囲は800mm〜4000mmです。

于 2012-01-01T15:37:36.187 に答える