Я работаю с OpenNI 1.5.4.0 и OpenCV 2.4.5, плюс Qt для целей визуализации (только изображения RGB).
По сути, я получаю кадры глубины и RGB из Kinect и сохраняю их на жестком диске, используя преобразование:
/* Depth conversion */
cv::Mat depth = cv::Mat(2, sizes, CV_16UC1, (void*) pDepthMap); //XnDepthPixel *pDepthMap
/* RGB conversion */
///image is a QImage* , pImageMap is a XnUInt8*
for(int i = 0; i < height; ++i)
{
for (unsigned y = 0; y < height; ++y)
{
uchar *imagePtr = (*image).scanLine(y);
for (unsigned x=0; x < width; ++x)
{
imagePtr[0] = pImageMap[2];
imagePtr[1] = pImageMap[1];
imagePtr[2] = pImageMap[0];
imagePtr[3] = 0xff;
imagePtr+=4;
pImageMap+=3;
}
}
}
Теперь я хочу загрузить эти изображения с жесткого диска, чтобы вычислить трехмерные облака точек как вычисление после обработки.
Я загружаю карты глубины как:
depth_image = cv::imread(m_rgb_files.at(w).toStdString(), CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR );
но применяя формулы:
depth = depth_image.at<int>(j,i); //depth_image is stored as 16bit
p.z = (float)depth * 0.001f; //converting from millimeters to meters
p.x = (float)(i - m_params.center_x) * depth * m_params.focal_length; //focal_length read using OpenNI function
p.y = (float)(j - m_params.center_y) * depth * m_params.focal_length;
полученное pointcloud — беспорядок.
Если я выполняю онлайн-обработку, используя непосредственно исходные данные XnDepthPixel *, результат будет идеальным, если использовать формулы, написанные ранее.
Кто-нибудь может дать мне «подсказку» о моей вине?
заранее спасибо
РЕДАКТИРОВАТЬ: я следил также за этим ресурс, но это не работает для меня, потому что XnDepthPixel содержит реальные данные в миллиметрах
Я думаю, что здесь есть возможная проблема:
depth = depth_image.at<int>(j,i); //depth_image is stored as 16bit
Если глубина изображения действительно является 16-битный, должен ли он действительно быть:
depth = depth_image.at<short>(j,i); //depth_image is stored as 16bit
Так как int
32-битный, а не 16.
В качестве дополнения, если вы создали OpenCV с поддержкой OpenNI, вы можете получить изображение глубины как cv::Mat
который вы можете легко сохранить с cv::imwrite
Вот минимальный пример:
#include "opencv2/core/core.hpp"#include "opencv2/highgui/highgui.hpp"
#include <iostream>
using namespace cv;
using namespace std;
int main(){
VideoCapture capture;
capture.open(CV_CAP_OPENNI);
if( !capture.isOpened() ){
cout << "Can not open a capture object." << endl;
return -1;
}
cout << "ready" << endl;
for(;;){
Mat depthMap,depthShow;
if( !capture.grab() ){
cout << "Can not grab images." << endl;
return -1;
}else{
if( capture.retrieve( depthMap, CV_CAP_OPENNI_DEPTH_MAP ) ){
const float scaleFactor = 0.05f;
depthMap.convertTo( depthShow, CV_8UC1, scaleFactor );
imshow("depth",depthShow);
if( waitKey( 30 ) == 115) {//s to save
imwrite("your_depth_naming_convention_here.png",depthShow);
}
}
}
if( waitKey( 30 ) == 27 ) break;//esc to exit
}
}