測定結果を処理しています#
概要#
Basler blazeカメラは各センサーのピクセルのためにライトが移動する間隔を測定します。
これらの距離を使用して、カメラは各センサーピクセルについて右手座標系でx、y、z座標を計算します。座標系の原点は、カメラハウジング内にあるカメラの光学中心にあります。y軸は下向きで、z軸はカメラとは逆に向いています。
カメラは、選択したピクセル形式に応じて、深度マップまたは点群として3D情報を提供します。深度マップでは、z座標は16ビットのグレー値としてエンコードされます。以下に示すように、すべての3D座標値はグレー値から計算できます。点群には、各センサーピクセルのx、y、zの3D座標が浮動小数点数として含まれています。単位はmmです。
センサーピクセルの有効な深度情報がない場合(例えば、外れ値の除去のため、または不十分な光、つまり、信頼しきい値を超えるほど強くない光のため)、深度マップまたは点群の対応する値は、[Scan3dInvalidDataValue
]パラメーターで定義された値(デフォルト設定は[0])に設定されます。
深度マップの処理#
深度マップは16ビットグレー値で構成されます。各センサーピクセルについては、カメラがz座標値をグレー値に変換し、深度マップに保存します。
[Scan3dCoordinateScale
]、[Scan3dPrincipalPointU
]、[Scan3dPrincipalPointV
]、および[Scan3dFocalLength
]パラメーターによって提供されるカメラのキャリブレーションデータと組み合わせて、深度マップから完全な3D情報を取得できます。
情報
[Scan3dCoordinateScale
]パラメーター値は、選択したピクセル形式によって異なります。blaze Viewerでカメラを操作する場合、ピクセル形式は常にCoord3D_ABC32f
ピクセル形式に設定されます。この設定は変更できません。blaze Viewerによって提供される深度マップは、点群に基づいて作成されます。この場合、[Scan3dCoordinateScale
]パラメーター値は[1]です。pylon Viewerの外側でblazeカメラを操作しているときに、ピクセル形式をCoord3D_C16
に設定すると、[Scan3dCoordinateScale
]パラメーター値は異なります。次の表に、さまざまなピクセル形式の[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レガシーSDK、pylonSDK、またはblazeROSドライバーで取得した深度マップの場合は、次の式を使用する必要があります。
Distance Measured [mm] = Pixel_Value x Scan3dCoordinateScale[C]
blaze Viewerで保存された深度マップの場合は、次の式を使用します。
Distance Measured [mm] = DepthMin_parameter + (Pixel_Value x (DepthMax_Parameter - DepthMin_parameter)) / 65535
点群の処理#
点群から3D情報を抽出するために、これ以上の処理は必要ありません。点群は、カメラの座標系内のx、y、z座標の3点で構成されるためです。
点群を送信するためのカメラの設定方法およびデータへのアクセス方法については、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ビットの深度値では、各範囲の解像度が8ビットの4つのカラー範囲にマッピングされます。
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;
}