Basler pylon SDKで連続撮影(バーストキャプチャ)をC#で実装する
画像処理や検査用途では、「1枚だけ撮る」だけでなく連続して撮影(バーストキャプチャ) することが求められる場面も多くあります。
本記事では、Baslerのpylon SDKを使ってC#で高速連続撮影を実装する方法を紹介します。
✅ この記事でわかること
- バーストキャプチャの基本実装(Grabループ)
- 撮影間隔の制御方法
- 画像の保存とタイムスタンプ記録
- 処理速度における課題とその解決ヒント
📦 環境
| 項目 | 内容 |
|---|---|
| カメラ | Basler acA2500-14gm |
| SDK | pylon Camera Software Suite |
| 言語 | C# / .NET 8.0 (Windows) |
🔄 基本実装:N枚連続で撮る
今回も前回記事(Basler pylon SDKでフレームレートを制御・確認する)で紹介したBaslerCameraSampleクラスに、以下の機能を追加していきます。
まず、連続撮影の前にトリガー制御モードを設定するサポートメソッドを作っておきます。
public bool SetTriggerMode(string mode)
=> SetPLCameraParameter(PLCamera.TriggerMode, mode);
バースト撮影を行い、指定された枚数の画像を保存します。トリガー制御についてもいずれ記事にしたいですが、今はシンプルなトリガーなしのフリーモードにしておきます。
撮影開始し画像を取得するたび、指定されたベース名に連番と経過時間を付加して画像が保存されます。
経過時間を付加しておくと、後から検証するのに大変参考になります。DateTimeを使うのも有効です。
public void BurstCapture(int count, string baseName = "burst")
{
SetTriggerMode(PLCamera.TriggerMode.Off); // トリガーモードをオフにしてフリーモードで撮影
if (Camera == null || !IsConnected)
throw new InvalidOperationException("Camera is not connected.");
if (Camera.StreamGrabber == null)
throw new InvalidOperationException("Camera StreamGrabber is not available.");
var sw = new Stopwatch();
Camera.StreamGrabber.Start();
sw.Start();
for (int i = 0; i < count; i++)
{
using IGrabResult? result = Camera.StreamGrabber.RetrieveResult(5000, TimeoutHandling.ThrowException);
var elapsed = sw.ElapsedMilliseconds;
if (result?.GrabSucceeded ?? false)
{
// 画像の変換と保存
// 保存処理に時間がかかる場合は、画像をConcurrentQueueなどに一時保存し、別スレッドで非同期保存すると安定します
var bmp = ConvertGrabResultToBitmap(result);
string filename = $"{baseName}_{i:D3}_{elapsed}ms.bmp";
SaveBitmap(bmp, filename);
}
}
sw.Stop();
Camera.StreamGrabber.Stop();
}
🕒 撮影間隔を制御するには?
AcquisitionFrameRateEnable = trueにして、AcquisitionFrameRateを変更してください。(参考:Basler pylon SDKでフレームレートを制御・確認する)
📷 実行例:露出時間を変えて撮影・保存
以下のコードでは、10fpsで画像を連続取得し、保存します。
[TestMethod()]
public void BurstCaptureTest_10times()
{
if (!_baslerCameraSample.IsConnected)
_baslerCameraSample.Connect();
// フレームレートを有効にする。
_baslerCameraSample.EnableFrameRate(true);
_baslerCameraSample.SetFrameRate(10); // 10fps(100ms/frame)
_baslerCameraSample.BurstCapture(10, "BurstCaptureTest");
// 10枚の画像が保存されていることを確認する。
for (int i = 0; i < 10; i++)
{
string filename = $"BurstCaptureTest_{i:D3}_*.bmp";
var files = System.IO.Directory.GetFiles(".", filename);
Assert.IsTrue(files.Length > 0, $"File {filename} not found.");
}
}
実行結果
回転しているサンプルを10fpsで10枚撮影しました。
| 45ms | 143ms | 243ms | 343ms | 443ms |
|---|---|---|---|---|
![]() |
![]() |
![]() |
![]() |
![]() |
| 543ms | 643ms | 743ms | 843ms | 943ms |
![]() |
![]() |
![]() |
![]() |
![]() |
⚠️ よくある問題と対応策
| 問題 | 原因・対策 |
|---|---|
| 撮影枚数が少ない/取りこぼす | 処理が間に合っていない(画像保存に時間がかかる) |
| フル解像度では処理が重すぎる | ROIを設定して高速化(次回解説予定) |
| 1枚目の時刻がずれる | トリガー制御 |
🔁 フル解像度で遅い?それ、ROIで改善できます
今回のバーストキャプチャでは、**フル画角(例:2592x1944)**で撮影しています。
処理が重かったりフレームレートが伸びない場合、ROIを設定して画像サイズを小さくすることで改善できます。
次回の記事では、ROI(撮影範囲の絞り込み)を使って、より高速なバーストキャプチャを実現する方法を紹介します。
📝 まとめ
- バーストキャプチャは
StreamGrabber.Start()+ ループで実装できる - フレームごとの制御には
FrameRate設定を活用 - 保存時間や画像サイズがボトルネックになることもある
- → ROI設定と組み合わせると、連続撮影性能がさらにアップ
筆者:@MilleVision









