コンテンツにスキップ

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

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

概要#

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

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

カメラは、選択したピクセル形式に応じて、深度マップまたは点群として3D情報を提供します。深度マップでは、z座標は16ビットのグレー値としてエンコードされます。以下に示すように、すべての3D座標値はグレー値から計算できます。点群には、各センサーピクセルのx、y、zの3D座標が浮動小数点数として含まれています。単位は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]パラメーター値
Coord3D_ABC32f 1
Coord3D_C16 0.152588
Mono16 0.152588

深度マップを送信するようにカメラを設定する方法と深度マップデータにアクセスする方法については、GrabDepthMap C++サンプルを参照してください。

2D深度マップからの3D座標の計算#

深度マップの16ビットグレー値をmm単位のz座標に変換するには、次の式を使用します。

z [mm] = gray2mm * g

ここで、

g = gray value from the depth map

gray2mm = value of the Scan3dCoordinateScale parameter

x座標とy座標を計算するには、次の式を使用します。

x [mm] = (u-cx) * z / f

y [mm] = (v-cy) * z / f

ここで、

(u,v) = column and row in the depth map

f = value of the Scan3dFocalLength parameter, i.e., the focal length of the camera's lens

(cx,cy) = values of the Scan3dPrincipalPointU and Scan3dPrincipalPointV parameters, i.e., the principal point

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深度マップを計算する方法が説明されています。

座標系の原点をカメラハウジングの前面にシフトする#

The camera's coordinate system's origin is located in the camera's optical center which is inside the camera housing. If you prefer coordinates in a coordinate system which is located at the camera's front of the housing, i.e., which is translated along the z axis, a constant, device-specific offset has to be subtracted from the z coordinates. The required offset can be retrieved from the camera by getting the value of the ZOffsetOriginToCameraFront parameter:

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

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

x' = x

y' = y

z' = z - offset

距離の計算#

Given a point's coordinates (x,y,z) in mm, the distance of that point to the camera's optical center can be calculated using the following formula:

d = sqrt( xx + yy + z*z )

The distance d' to the front of the camera's housing can be calculated as follows:

z' = z - offset

d' = sqrt( xx + yy + z'*z')

深度情報をRGB画像として表示#

次の虹色マッピングのスキームを使用して、z座標または距離値からRGB値を計算できます。これは、データの視覚化を改善するために役立ちます。

First, a depth value from the [minDepth..maxDepth] value range is converted into a 10-bit value. This 10-bit depth value is mapped to 4 color ranges where each range has a resolution of 8 bits.

minDepth and maxDepth = values of the DepthMin and DepthMax parameters, i.e., the camera's current 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)

In the following code snippet, depth is either a z value or a distance value in 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;
}