處理量測結果#
資訊
本主題中的所有資訊均適用於所有 blaze 和 Smart blaze 相機型號。為求簡潔,文中以「blaze」統稱所有型號。
概覽#
Basler blaze 相機可量測每個感光元件像素的光線行進距離。
利用這些距離,相機會針對每個感光元件像素,在右手座標系中計算 x、y、z 座標。座標系原點位於相機的光學中心(位於相機外殼內部)。y 軸朝下,z 軸背離相機朝外。
根據所選的 pixel format,相機會以深度圖或點雲的形式提供 3D 資訊。在深度圖中,z 座標會編碼為 16 位元灰階值。如下圖所示,所有 3D 座標值皆可從灰階值計算得出。點雲則包含每個感光元件像素的 x、y、z 3D 座標(以浮點數表示)。單位為 mm。
如果感光元件像素沒有有效的深度資訊(例如由於 異常值剔除 或光線不足,即光線強度不足以通過 置信閾值),則深度圖或點雲中的對應值會設為由 Scan3dInvalidDataValue 參數所定義的值(預設設定為 0)。
處理深度圖#
深度圖由 16 位元灰階值組成。對於每個感光元件像素,相機會將 z 座標值轉換為灰階值,並將其儲存在深度圖中。
結合由 Scan3dCoordinateScale, Scan3dPrincipalPointU, Scan3dPrincipalPointV的狀態,以及 Scan3dFocalLength 參數提供的相機校正資料,即可從深度圖中擷取完整的 3D 資訊。
資訊
影像 Scan3dCoordinateScale 參數值會根據所選的 pixel format 而有所不同。在 blaze Viewer 中使用相機時,pixel format 一律設為 Coord3D_ABC32f pixel format。您無法變更此設定。blaze Viewer 提供的深度圖是根據點雲建立的。在此情況下, Scan3dCoordinateScale 參數值為 1。當您在 pylon Viewer 外部使用 blaze 相機並將 pixel format 設為 Coord3D_C16上, Scan3dCoordinateScale 參數值會有所不同。下表列出不同 pixel format 的 Scan3dCoordinateScale 參數值。
| Pixel Format | Scan3dCoordinateScale[C] 參數值 |
|---|---|
| Coord3D_ABC32f | 1 |
| Coord3D_C16 | 0.152588 |
| Mono16 | 0.152588 |
請參閱 GrabDepthMap C++ 範例,了解如何設定相機以傳送深度圖以及如何存取深度圖資料。
從 2D 深度圖計算 3D 座標#
若要將深度圖的 16 位元灰階值轉換為以 mm 為單位的 z 座標,請使用下列公式:
z [mm] = gray2mm * g
其中:
g = 來自深度圖的灰階值
gray2mm = 以下項目的值: Scan3dCoordinateScale Property
若要計算 x 和 y 座標,請使用下列公式:
x [mm] = (u-cx) * z / f
y [mm] = (v-cy) * z / f
其中:
(u,v) = 深度圖中的欄與列
f = 以下項目的值: Scan3dFocalLength 參數,亦即相機鏡頭的焦距
(cx,cy) = 以下項目的值: Scan3dPrincipalPointU 和 Scan3dPrincipalPointV 參數,亦即主點
C++ 範例程式碼#
// Enable depth maps by enabling the Range component and setting the appropriate pixel format.
camera.ComponentSelector.SetValue(ComponentSelector_Range);
camera.ComponentEnable.SetValue(true);
camera.PixelFormat.SetValue(PixelFormat_Coord3D_C16);
// Query the conversion factor required to convert gray values to distances:
// Choose the z axis first...
camera.Scan3dCoordinateSelector.SetValue(Scan3dCoordinateSelector_CoordinateC);
// ... then retrieve the conversion factor.
const auto gray2mm = camera.Scan3dCoordinateScale.GetValue();
// Configure the gray value used for indicating missing depth data.
// Note: Before setting the value, the Scan3dCoordinateSelector parameter must be set to the axis the
// value is to be configured for, in this case the z axis. This means that Scan3dCoordianteSelector must be set
// to "CoordinateC". This has already been done a few lines above.
camera.Scan3dInvalidDataValue.SetValue((double)missingDepth);
// Retrieve calibration data from the camera.
const auto cx = camera.Scan3dPrincipalPointU.GetValue();
const auto cy = camera.Scan3dPrincipalPointV.GetValue();
const auto f = camera.Scan3dFocalLength.GetValue();
// ....
// Access the data.
const auto container = ptrGrabResult->GetDataContainer();
const auto rangeComponent = container.GetDataComponent(0);
const auto width = rangeComponent.GetWidth();
const auto height = rangeComponent.GetHeight();
// Calculate coordinates for pixel (u,v).
const uint16_t g = ((uint16_t*)rangeComponent.GetData())[u + v * width];
const double z = g * gray2mm;
const double x = (u - cx) * z / f;
const double y = (v - cy) * z / f;
處理儲存的深度圖#
對於使用 blaze Legacy SDK、pylon SDK 或 blaze ROS 驅動程式取得的深度圖,您必須使用下列公式:
測量距離 [mm] = Pixel_Value x Scan3dCoordinateScale[C]
對於使用 blaze Viewer 儲存的深度圖,請使用下列公式:
測量距離 [mm] = DepthMin_parameter + (Pixel_Value x (DepthMax_Parameter - DepthMin_parameter)) / 65535
處理點雲#
無需進行額外處理即可從點雲中萃取 3D 資訊,因為點雲由相機座標系內的 x、y、z 座標三元組組成。
請參閱 FirstSample C++ 範例,了解如何設定相機以傳送點雲以及如何存取資料。
如果您除了點雲之外還需要深度圖,請參閱 ConvertPointCloud2DepthMap C++ 範例,該範例說明了如何從點雲計算灰階與 RGB 深度圖。
將座標系原點平移至相機外殼前端#
相機座標系的原點位於相機外殼內側的光學中心。如果您偏好位於相機外殼前端(即沿 z 軸平移)之座標系中的座標,則必須從 z 座標中減去一個恆定的、裝置特有的偏移量。所需的偏移量可以透過取得下列項目的值從相機中擷取: ZOffsetOriginToCameraFront 參數:
如果 (x,y,z) 是相機座標系中某個點的座標,則沿 z 軸平移至相機外殼前端的座標系中對應的座標 (x',y',z') 可以使用下列公式決定:
x' = x
y' = y
z' = z - offset
計算距離#
給定一個點的座標 (x,y,z) (單位為公釐),該點到相機光學中心的距離可以使用以下公式計算:
d = sqrt( xx + yy + z*z )
距離 d' 至相機外殼前部的計算方式如下:
z' = z - offset
d' = sqrt( xx + yy + z'*z')
將深度資訊視覺化為 RGB 影像#
您可以針對彩虹色彩對應使用以下方案,從 z 座標或距離值計算 RGB 值。這對於改善資料視覺化非常有用。
首先,將 [minDepth..maxDepth] 值範圍內的深度值轉換為 10 位元值。此 10 位元深度值會對應至 4 個色彩範圍,每個範圍的解析度為 8 位元。
minDepth 和 maxDepth = 以下項目的值: DepthMin 和 DepthMax 參數,即相機目前的深度 ROI
| 深度值 | 對應至色彩範圍 |
|---|---|
| 0..255 | 紅到黃 (255,0,0) -> (255,255,0) |
| 256..511 | 黃到綠 (255,255,0) -> (0, 255, 0) |
| 512..767 | 綠到青 (0,255,0) -> (0,255,255) |
| 768..1023 | 青到藍 (0,255,255) -> (0, 0, 255) |
在下列程式碼片段中, depth 是 z 值或以 mm 為單位的距離值。
const int minDepth = (int)m_camera.DepthMin.GetValue();
const int maxDepth = (int)m_camera.DepthMax.GetValue();
const double scale = 65536.0 / (maxDepth - minDepth);
for each pixel {
// Set depth either to the corresponding z value or
// a distance value calculated from the z value.
// Clip depth if required.
if (depth < minDepth)
depth = minDepth;
else if (depth > maxDepth)
depth = maxDepth;
// Compute RGB values.
const uint16_t g = (uint16_t)((depth - minDepth) * scale);
const uint16_t val = g >> 6 & 0xff;
const uint16_t sel = g >> 14;
uint32_t res = val << 8 | 0xff;
if (sel & 0x01)
{
res = (~res) >> 8 & 0xffff;
}
if (sel & 0x02)
{
res = res << 8;
}
const uint8_t r = res & 0xff;
res = res >> 8;
const uint8_t g = res & 0xff;
res = res >> 8;
const uint8_t b = res & 0xff;
}