0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ROIを活用してバースト撮影を高速化する【Basler pylon SDK / C#】

0
Last updated at Posted at 2025-07-28

ROIを活用してバースト撮影を高速化する【Basler pylon SDK / C#】

Baslerカメラを使って画像処理アプリを開発していると、「視野の一部分だけでいいから、もっと速く撮れないか?」とか、単純に「画像サイズを減らしたい」と感じることはありませんか?

フレームレートを最大限に活かすため、ROI(Region of Interest、撮影範囲の絞り込み) を調整すると高速化できる場合があります。

この記事では、フル画角とROI設定の違いによるフレームレート比較や、実際のサンプル画像とともにC#コードでの設定方法を解説します。


✅ 本記事でわかること

  • BaslerカメラのROI(撮影範囲)を設定する方法
  • ROIを使って画像サイズとフレームレートを改善する
  • ROI設定時の注意点やエラーの対処法

📦 環境

項目 内容
カメラ Basler acA2500-14gm
SDK pylon Camera Software Suite
言語 C# / .NET 8.0 (Windows)
レンズ VS-LD25N(25mm Cマウント)

🔍 ROIとは?

ROI(Region of Interest)は「センサ上で撮影したい領域」だけを選んで読み出す機能です。
Baslerカメラでは、OffsetX, OffsetY, Width, Height の4つのパラメータで定義します。

センサ全体ではなく一部だけを読み出すことで、

  • 画像サイズが小さくなる
  • 読み出し時間が短くなる → フレームレート向上
  • 必要な領域だけ高速処理できる

といったメリットがあります。


🔧 ROIの設定方法(C#)

今回も前回記事(Basler pylon SDKで連続撮影(バーストキャプチャ)をC#で実装する)で紹介したBaslerCameraSampleクラスに、機能を追加していきます。

ROIはカメラ画像の左上を原点として、切り取る四角の位置と大きさを指定します。

public bool SetOffsetX(int offsetX)
    => SetPLCameraParamter(PLCamera.OffsetX, offsetX);

public bool SetOffsetY(int offsetY)
    => SetPLCameraParamter(PLCamera.OffsetY, offsetY);

public bool SetWidth(int width)
    => SetPLCameraParamter(PLCamera.Width, width);

public bool SetHeight(int height)
    => SetPLCameraParamter(PLCamera.Height, height);

毎回個別に指定するのもいいですが、筆者は一度に設定することも多いです。
ROIがセンササイズからはみ出すと例外が発生してしまうため、条件により設定順序を分けておきます。

public bool SetROI(int offsetX, int offsetY, int width, int height)
{
    if (width <= 0 || height <= 0)
        throw new ArgumentException("ROI width and height must be greater than zero.");

    // ROIがカメラのセンサーサイズを超えないように、設定の順番を考慮する。
    if (GetWidth() + offsetX < GetSensorWidth())
    {
        if (!SetOffsetX(offsetX) || !SetWidth(width))
            return false;
    }
    else
    {
        if (!SetWidth(width) || !SetOffsetX(offsetX))
            return false;
    }

    if (GetHeight() + offsetY < GetSensorHeight())
    {
        if (!SetOffsetY(offsetY) || !SetHeight(height))
            return false;
    }
    else
    {
        if (!SetHeight(height) || !SetOffsetY(offsetY))
            return false;
    }
    return true;
}

public int GetWidth()
    => (int)GetPLCameraParamter(PLCamera.Width);

public int GetHeight()
    => (int)GetPLCameraParamter(PLCamera.Height);

public int GetSensorWidth()
    => (int)GetPLCameraParamter(PLCamera.SensorWidth);

public int GetSensorHeight()
    => (int)GetPLCameraParamter(PLCamera.SensorHeight);

あるいはRectを引数に取ります。WPFの場合は以下の通りです。

using Windows;

public bool SetROI(Rect roi)
    => SetROI((int)roi.X, (int)roi.Y, (int)roi.Width, (int)roi.Height);

場合によっては、ROIの大きさをそのままに、int offsetXint offsetYを引数にとって、切り抜く位置を変えることもあります。


📈 ROIでフレームレートが上がる理由

センサからの読み出しは、通常画素数に比例して時間がかかるため、
読み出す画素数を減らすことで露光時間や保存処理の制約にかかわらずフレームレートを上げることができます。


✅ ROI設定時の注意点

パラメータ 注意内容
Width, Height 2・4・8・16などの「特定の倍数」である必要あり
OffsetX, OffsetY ROI位置を指定。センサ端を超えないよう注意

実装の説明でも軽く触れましたが、ROIの設定は、センサの有効範囲を超えないよう Offset → Size の順に注意して行う必要があります。

また、Baslerカメラでは、WidthHeight を設定する際、
カメラ仕様によって 2・4・8・16などの「特定の倍数」である必要があります。

これはセンサーからの読み出し・画像バッファへの配置に関係するもので、GetIncrement()メソッドで確認できます。

public long GetInc(IntegerName parameter)
{
    if (Camera == null || !IsConnected)
        throw new InvalidOperationException("Camera is not connected.");

    if (Camera.Parameters[parameter].IsReadable)
    {
        long inc = Camera.Parameters[parameter].GetIncrement();
        Console.WriteLine($"{parameter} increment: {inc}");
        return inc;
    }
    else
    {
        throw new InvalidOperationException($"{parameter} is not readable.");
    }
}

WidthHeightについて確認してみます。
acA2500-14gmは1ずつ変えられますが、モデルによってはこれが原因で思った通りの画像サイズにできずハマったりすることもあります。

[TestMethod()]
public void GetIncTest()
{
    if (!_baslerCameraSample.IsConnected)
        _baslerCameraSample.Connect();
    
    // Basler acA2500-14gmは1ずつ変えられる。
    var incWidth = _baslerCameraSample.GetInc(PLCamera.Width);
    Assert.AreEqual(1, incWidth, "Width increment should be 1.");
    var incHeight = _baslerCameraSample.GetInc(PLCamera.Height);
    Assert.AreEqual(1, incHeight, "Height increment should be 1.");
}

✅ フレームレートを設定する

ROIを設定後、フレームレートを制御するには以下のようにします。
実際のフレームレートは ResultingFrameRate で確認可能です。

static BaslerCameraSample _baslerCameraSample = new BaslerCameraSample();

[TestMethod()]
public void SetROITest()
{
    if (!_baslerCameraSample.IsConnected)
        _baslerCameraSample.Connect();

    _baslerCameraSample.EnableFrameRate(true);
    _baslerCameraSample.SetFrameRate(30); // 目標値:30fps

    _baslerCameraSample.SetROI(1246, 1200, 640, 480); // ROIを設定
    var fps1 = _baslerCameraSample.GetResultingFrameRate();
    // 5枚バーストキャプチャして撮れる画の変化を比較する。
    _baslerCameraSample.BurstCapture(5, "ROITest_640x480");

    _baslerCameraSample.SetROI(0, 0, 2592, 1944); // フルサイズに戻す
    var fps2 = _baslerCameraSample.GetResultingFrameRate();
    _baslerCameraSample.BurstCapture(5, "ROITest_2592x1944");

    // ROIを設定した後のフレームレートがフルサイズよりも高いことを確認
    Console.WriteLine($"FPS with ROI: {fps1:F2}, FPS without ROI: {fps2:F2}");
    Assert.IsTrue(fps1 > fps2);
}

🧪 ROIとfpsの違いを比較する(実測)

下の表は、同じ対象をフル解像度とROIで撮影した連続画像です。
フル解像度では撮影間隔が長くなってしまっていますが、ROI指定をすると目標フレームレートを達成できているのがわかります。

2592 x 1944

N 0 1 2 3 4
T[ms] 72 140 209 277 346
ROITest_2592x1944_000_72ms.png ROITest_2592x1944_001_140ms.png ROITest_2592x1944_002_209ms.png ROITest_2592x1944_003_277ms.png ROITest_2592x1944_004_346ms.png

640 x 480

N 0 1 2 3 4
T[ms] 23 67 87 120 154
ROITest_640x480_000_23ms.png ROITest_640x480_001_67ms.png ROITest_640x480_002_87ms.png ROITest_640x480_003_120ms.png ROITest_640x480_004_154ms.png

比較

ROI設定 解像度 実際のフレームレート
なし(フル) 2,592 x 1,944 14.59fps
ROIあり 640 x 480 30.00fps

実際の値はカメラモデルにより異なります。


🧭 よくあるエラーと対処法

エラー内容 原因
InvalidParameterException WidthOffsetX が不正(範囲外や偶数違反)
ROI設定後にフレームが取れない 一部機種では ROI 後にカメラ再初期化が必要な場合も

📝 まとめ

  • ROIを使うと、画像サイズを絞って処理を高速化できる
  • フレームレートの上限も向上するため、リアルタイム処理に有効
  • パラメータの制約(偶数・最大値)に注意して使うと安定動作が得られる

筆者:@MilleVision


🛠 サンプルコード完全版のご案内

「ROIでfpsを底上げ:範囲指定と保存の実装一式 →」

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?