コンテンツにスキップ

測定結果を処理しています#

このトピックでは、Basler blaze-101カメラの測定結果を処理する方法について説明します。

概要#

blaze-101カメラは各センサーのピクセルのためにライトが移動する間隔を測定します。

これらの距離を使用して、カメラは各センサーピクセルの右手座標系でx、y、z座標を計算します。座標系の原点は、カメラハウジング内にあるカメラの光学中心点です。y軸が下を指し、z軸がカメラから遠ざかる方向にあります。

The camera provides 3D information either as a depth map or as a point cloud, depending on the pixel format selected. In a depth map, z coordinates are encoded as 16-bit gray values. As illustrated below, all 3D coordinate values can be calculated from the gray values. A point cloud contains the x,y,z 3D coordinates for each sensor pixel as floating point numbers. The unit is mm.

If there is no valid depth information for a sensor pixel (e.g., due to outlier removal or insufficient light, i.e., light that is not strong enough to pass the confidence threshold), the corresponding values in a depth map or a point cloud are set to the value defined by the Scan3dInvalidDataValue parameter (default setting is 0).

深度マップの処理#

深度マップは16ビットグレー値で構成されます。各センサーピクセルについては、カメラがz座標値をグレー値に変換し、深度マップに保存します。

In combination with the camera's calibration data provided by the Scan3dCoordinateScale, Scan3dPrincipalPointU, Scan3dPrincipalPointV, and Scan3dFocalLength parameters, complete 3D information can be retrieved from a depth map.

情報

The Scan3dCoordinateScale parameter value varies depending on the pixel format selected. When working with the camera in the blaze Viewer, the pixel format is always set to the Coord3D_ABC32f pixel format. You can't change this setting. The depth maps provided by the blaze Viewer are created based on the point clouds. The Scan3dCoordinateScale parameter value is 1 in this case. When you're working with the blaze camera outside the pylon Viewer and set the pixel format to Coord3D_C16, the Scan3dCoordinateScale parameter value is different. The Scan3dCoordinateScale parameter values for the different pixel formats are listed in the following table.

Pixel Format Scan3dCoordinateScale[C] Parameter Value
Coord3D_ABC32f 1
Coord3D_C16 0.152588
Mono16 0.152588

Refer to the GrabDepthMap C++ sample for how to configure a camera to send depth maps and how to access the depth map data.

Calculating 3D Coordinates from the 2D Depth Map#

To convert a depth map's 16-bit gray values to z coordinates in mm, use the following formula:

z [mm] = gray2mm * g

ここで、

g = gray value from the depth map

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;

Dealing with Saved Depth Maps#

For depth maps acquired with the blaze Legacy SDK, the pylon SDK, or the blaze ROS driver, you have to use the following formula:

Distance Measured [mm] = Pixel_Value x Scan3dCoordinateScale[C]

For depth maps saved with the blaze Viewer, use the following formula:

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パラメーターの値を取得することでカメラから取得できます。

const double offset = camera.ZOffsetOriginToCameraFront.GetValue();

(x,y,z)がカメラの座標系にある点の座標である場合、z軸に沿ってカメラのハウジングの前面にシフトされた座標系にある対応する座標(x',y',z')は、次の式を使用して決定できます。

x' = x
y' = y
z' = z - offset

距離の計算#

点の座標(x,y,z)がmmで指定されている場合、その点からカメラの光学中心までの距離は、次の式を使用して計算できます。

d = sqrt( x*x + y*y + z*z )

カメラのハウジングの前面までの距離d'は、次のように計算できます。

z' = z - offset
d' = sqrt( x*x + y*y + 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;
}
トップに戻る