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 не имел информации.
Ответы
Ответ 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, где эта точка должна
быть отображенным.
Для этого вам не нужен указатель colorDatai > .
Итак, ваша функция должна быть изменена следующим образом:
/** 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 для получения дополнительной информации об этом.
Внешняя калибровка
Внутренняя калибровка