處理測量結果#
資訊
本主題中的所有資訊均適用於所有 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 參數
若要計算 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) (以 mm 為單位),該點到相機光學中心的距離可以使用以下公式計算:
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 參數,即相機目前的 depth 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;
}