計算點雲的方法
阿新 • • 發佈:2020-12-09
使用 OpenNI 時,點雲的生成也有兩種方法:
方法 1:分別讀取相機的內參和深度幀,對深度幀的每一個畫素點,根據內參來完成點雲的生成。
方法 2:使用 CoordinateConverter 類中的 convertDepthToWorld 方法來將深度座標轉換為點雲。
方法 1 是最常使用的方法,所以一般情況下我們使用這種方法,方法 2 是一種不準確的方法,該方法使用 FOV(Field of View, 視場角)來估計內參中的焦距,使用影象解析度的一半來估計主點的座標。因此該方法一般在無法讀取到相機內參的情況下使用達到模擬生成點雲的目的。
使用方法 1,將深度幀轉換為點雲的程式碼如下:
Step1,獲取內參。
void getCameraParams(openni::Device& Device, xIntrinsic_Params& irParam)
{
OBCameraParams cameraParam;
int dataSize = sizeof(cameraParam);
memset(&cameraParam, 0, sizeof(cameraParam));
openni::Status rc = Device.getProperty(openni::OBEXTENSION_ID_CAM_PARAMS, (uint8_t
*)&cameraParam, &dataSize);
if (rc != openni::STATUS_OK)
{
std::cout << "Error:" << openni::OpenNI::getExtendedError() << std::endl;
return;
}
IRParam.f_x = cameraParam.l_intr_p[0];
IRParam.f_y = cameraParam.l_intr_p[1];
IRParam.c_x = cameraParam.l_intr_p[2];
IRParam.c_y = cameraParam. l_intr_p[3];
std::cout << "IRParam.f_x = " << IRParam.f_x << std::endl;
std::cout << "IRParam.f_y = " << IRParam.f_y << std::endl;
std::cout << "IRParam.c_x = " << IRParam.c_x << std::endl;
std::cout << "IRParam.c_y = " << IRParam.c_y << std::endl;
}
Step2: 轉換點雲
void convertDepthToPointCloud(const uint16_t *pDepth, int width, int height,const char
*ply_filename)
{
float world_x, world_y, world_z;
for (int v = 0; v < height; ++v)
{
for (int u = 0; u < width; ++u)
{
uint16_t Depth = pDepth[v * width + u];
if (Depth <= 0 || Depth < min_Depth || Depth > max_Depth)
continue;
float fdx = g_IntrinsicParam.f_x * ((float)(width) / RESOULTION_X);
float fdy = g_IntrinsicParam.f_y * ((float)(height) / RESOULTION_Y);
float u0 = g_IntrinsicParam.c_x * ((float)(width)/ RESOULTION_X);
float v0 = g_IntrinsicParam.c_y * ((float)(height) / RESOULTION_Y);
float tx = (u - u0) / fdx; float ty = (v - v0) / fdy;
world_x = Depth * tx;
world_y = Depth * ty;
world_z = Depth;
}
}
}
備註:
點選下面連結,進入奧比中光開發者社群,瞭解更多3D視覺技術資訊:
https://developer.orbbec.com.cn/
或掃描下方二維碼,進入奧比中光開發者社群: