Подтвердить что ты не робот

Kinect SDK: выровнять глубину и цветные рамки

Я работаю с датчиком Kinect, и я пытаюсь выровнять рамки глубины и цвета, чтобы я мог сохранять их как изображения, которые "вписываются" друг в друга. Я провел много времени, проходя через форумы msdn и скромную документацию Kinect SDK, и я абсолютно ничего не получаю.

На основе этого ответа: Kinect: Преобразование из координат RGB в координаты глубины

У меня есть следующая функция, где depthData и colorData получены из NUI_LOCKED_RECT.pBits, а mappedData - это вывод, содержащий новый цветной кадр, отображаемый в координаты глубины:

bool mapColorFrameToDepthFrame(unsigned char *depthData, unsigned char* colorData, unsigned char* mappedData)
{
    INuiCoordinateMapper* coordMapper;

    // Get coordinate mapper
    m_pSensor->NuiGetCoordinateMapper(&coordMapper);

    NUI_DEPTH_IMAGE_POINT* depthPoints = new NUI_DEPTH_IMAGE_POINT[640 * 480];

    HRESULT result = coordMapper->MapColorFrameToDepthFrame(NUI_IMAGE_TYPE_COLOR, NUI_IMAGE_RESOLUTION_640x480, NUI_IMAGE_RESOLUTION_640x480, 640 * 480, reinterpret_cast<NUI_DEPTH_IMAGE_PIXEL*>(depthData), 640 * 480, depthPoints);
    if (FAILED(result))
    {
        return false;
    }    

    int pos = 0;
    int* colorRun = reinterpret_cast<int*>(colorData);
    int* mappedRun = reinterpret_cast<int*>(mappedData);

    // For each pixel of new color frame
    for (int i = 0; i < 640 * 480; ++i)
    {
        // Find the corresponding pixel in original color frame from depthPoints
        pos = (depthPoints[i].y * 640) + depthPoints[i].x;

        // Set pixel value if it within frame boundaries
        if (pos < 640 * 480)
        {
            mappedRun[i] = colorRun[pos];
        }
    }

    return true;
}

Все, что я получаю при запуске этого кода, - это неизменный цветной фрейм с удаленным (белым) всеми пикселями, в которых depthFrame не имел информации.

4b9b3361

Ответ 1

С картой OpenNI существует регистрация вызова опций.

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

OpenNI 2.0 и Nite 2.0 отлично работают, чтобы захватывать информацию Kinect и там много учебников.

Вы можете посмотреть на это:

Kinect с OpenNI

И OpenNi имеет пример в SimplerViewer, который объединяет Depth и Color, может быть, вы можете просто посмотреть на это и попробовать.

Ответ 2

Это может быть не быстрый ответ, на который вы надеетесь, но это преобразование успешно выполняется в дополнение к ofxKinectNui для openFrameworks (см. здесь).

Похоже, ofxKinectNui делегирует функции GetColorPixelCoordinatesFromDepthPixel, определенную здесь.

Ответ 3

Я думаю, проблема в том, что вы вызываете MapColorFrameToDepthFrame, когда вы действительно должны называть MapDepthFrameToColorFrame.

Курящий пистолет - это строка кода:

mappedRun[i] = colorRun[pos];

Чтение из pos и запись в i происходит назад, так как pos = depthPoints[i] представляет координаты глубины, соответствующие цветовым координатам в i. Вы действительно хотите перебирать все координаты глубины и читать с входного цветного изображения в соответствующих цветовых координатах.

Ответ 4

Я думаю, что в вашем коде есть разные неправильные строки.

Прежде всего, какую карту глубины вы переходите к своей функции?

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

Второй момент заключается в том, что из того, что я понял, вы хотите отобразить рамку глубины в цветной кадр, поэтому правильная функция, которую вы имеете для вызова из kinect sdk является MapDepthFrameToColorFrame вместо MapColorFrameToDepthFrame.

Наконец, функция вернет карту точки, где для каждой информации о глубине в позиции [i] у вас есть позиция x и позиция y, где эта точка должна быть отображенным.
Для этого вам не нужен указатель colorData​​i > .

Итак, ваша функция должна быть изменена следующим образом:

/** Method used to build a depth map aligned to color frame
    @param [in]  depthData    : pointer to your data;
    @param [out] mappedData   : pointer to your aligned depth map;
    @return true if is all ok : false whene something wrong
*/

bool DeviceManager::mapColorFrameToDepthFrame(unsigned short *depthData,  unsigned short* mappedData){
    INuiCoordinateMapper* coordMapper;
    NUI_COLOR_IMAGE_POINT* colorPoints = new NUI_COLOR_IMAGE_POINT[640 * 480]; //color points
    NUI_DEPTH_IMAGE_PIXEL* depthPoints = new NUI_DEPTH_IMAGE_PIXEL[640 * 480]; // depth pixel

    /** BE sURE THAT YOU ARE WORKING WITH THE RIGHT HEIGHT AND WIDTH*/  
    unsigned long refWidth = 0;
    unsigned long refHeight = 0;
    NuiImageResolutionToSize( NUI_IMAGE_RESOLUTION_640x480, refWidth, refHeight );
    int width  = static_cast<int>( refWidth  ); //get the image width in a right way
    int height = static_cast<int>( refHeight ); //get the image height in a right way

    m_pSensor>NuiGetCoordinateMapper(&coordMapper); // get the coord mapper
    //Map your frame;
    HRESULT result = coordMapper->MapDepthFrameToColorFrame( NUI_IMAGE_RESOLUTION_640x480, width * height, depthPoints, NUI_IMAGE_TYPE_COLOR, NUI_IMAGE_RESOLUTION_640x480, width * height, colorPoints );
    if (FAILED(result))
       return false;

    // apply map in terms of x and y (image coordinates);
    for (int i = 0; i < width * height; i++)
       if (colorPoints[i].x >0 && colorPoints[i].x < width && colorPoints[i].y>0 &&    colorPoints[i].y < height)
            *(mappedData + colorPoints[i].x + colorPoints[i].y*width) = *(depthData + i );

    // free your memory!!!
    delete colorPoints;
    delete depthPoints;
    return true;
}



Убедитесь, что ваш mappedData был инициализирован правильным способом, например, следующим образом.

mappedData = (USHORT*)calloc(width*height, sizeof(ushort));


Помните, что kinect sdk не обеспечивает точную функцию выравнивания между данными о цвете и глубине.

Если вам требуется точное выравнивание между двумя изображениями, вы должны использовать калибровочную модель. В этом случае я предлагаю вам использовать Kinect Calibration Toolbox на основе калибровочной модели Heikkilä.

Вы можете найти его в следующей ссылке:
http://www.ee.oulu.fi/~dherrera/kinect/.

Ответ 5

Прежде всего, вы должны откалибровать свое устройство. Это означает, что вы должны откалибровать RGB и ИК-датчик, а затем найти преобразование между RGB и IR. Как только вы узнаете эту информацию, вы можете применить эту функцию:

RGBPoint = RotationMatrix * DepthPoint + TranslationVector

Проверьте проекты OpenCV или ROS для получения дополнительной информации об этом.

Внешняя калибровка

Внутренняя калибровка