Microsoft Kinect SDK Глубина калибровки - PullRequest
1 голос
/ 29 декабря 2011

Я работаю над приложением реконструкции 3D-модели с датчиком Kinect. Я использую 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;
    } 

Мне было интересно, если вы дадите мне знать, как я могу рассчитать положение в реальном мире, основываясь на моих значениях глубины в пикселях, рассчитанных по моему методу.

1 Ответ

1 голос
/ 01 января 2012

Функция getDistance(), которую вы используете для расчета реальной глубины, относится к обнаружению игрока Kinect. Поэтому убедитесь, что вы соответственно открываете свой поток kinect или, возможно, вам следует получить только необработанные данные о глубине

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

, а затем вычислите глубину простым сдвигом битов второго байта на 8:

Расстояние (0,0) = (int) (биты [0] | биты [1] << 8); </p>

Первые методы калибровки должны работать нормально, даже если вы могли бы сделать небольшое улучшение используя лучшее приближение, данное Стефаном Магненатом:

расстояние = 0,1236 * загар (rawDisparity / 2842,5 + 1,1863) в метрах

Если вам действительно нужны более точные значения калибровки, вы должны действительно откалибровать свой kinect, используя, например, такой инструмент, как калибровка matlab kinect:

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

И дважды проверьте полученные значения с теми, которые вы используете в данный момент, предоставленные Николасом Буррусом.

EDIT

Читая ваш вопрос еще раз, я заметил, что вы используете Microsoft SDK , поэтому значения которые возвращаются с датчика kinect уже реальных расстояний в мм . Вам не нужно использовать функцию RawDepthToMeters(), ее следует использовать только с неофициальными SDK.

Аппаратное обеспечение создает карту глубины, которая является нелинейной функцией значений диспаратности и имеет 11 бит точности. Драйвер kinect sdk преобразует из коробки это значение диспаратности в мм и округляет его до целого числа. MS Kinect SDK имеет диапазон глубины 800 мм до 4000 мм .

...