コンテンツにスキップ
ステージングサーバー
開発サーバー

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

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

情報

このトピックの情報は、すべてのblazeおよびSmart blazeカメラモデルに適用されます。簡潔にするため、すべてのモデルを指して「blaze」を使用しています。

概要#

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 パラメータの値は、選択した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 カメラの座標系の原点は、カメラ筐体内部にあるカメラの光学中心に位置しています。筐体の前面に位置する座標系、つまりz軸に沿って平行移動した座標系での座標を好む場合は、デバイス固有の定数オフセットをz座標から減算する必要があります。必要なオフセットは、

(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ドライバーで取得した深度マップの場合は、次の式を使用する必要があります。

測定距離 [mm] = Pixel_Value x Scan3dCoordinateScale[C]

blaze Viewerで保存された深度マップの場合は、次の式を使用します。

測定距離 [mm] = DepthMin_parameter + (Pixel_Value x (DepthMax_Parameter - DepthMin_parameter)) / 65535

点群の処理#

点群から3D情報を抽出するために、これ以上の処理は必要ありません。点群は、カメラの座標系内のx、y、z座標の3点で構成されるためです。

点群を送信するためのカメラの設定方法およびデータへのアクセス方法については、FirstSample C++サンプルを参照してください。

点群に加えて深度マップが必要な場合は、ConvertPointCloud2DepthMap C++サンプルを参照してください。点群からグレースケールおよびRGB深度マップを計算する方法が説明されています。

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

カメラから取得できます。 ZOffsetOriginToCameraFront parameter:

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( 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 パラメータ、つまりカメラの現在の 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;
}