1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Basler pylon × WPF:ビニングGUIを最小実装する(1×1 / 2×2 切替、解像度追従)

1
Posted at

Basler pylon × WPF:ビニングGUIを最小実装する(1×1 / 2×2 切替、解像度追従)


導入

前回はビニングの仕組みと効果(S/N・FPS) をコード中心に確認しました。
組み込み装置は画面にカメラのライブビューが映っているだけで、安心感が増すものです。常にフル解像度で使うのではなく、画面表示用に普段はビニングで解像度を落とし処理の負荷を下げ、何かの計測時にフル解像度へ戻すことも、ときにはあるかと思います。

このように、通常はアプリ内部で自動制御する場合でも、現場で即座に切り替えたい動機はあります。例えば、"何か"あったとき にオペレータから解像度を手動で上げたいという要望がきます。逆に、動作確認時に効率化のため、解像度を下げたいときもあるかと思います。
そのような場合に、オペレータがワンクリックで 1×1 / 2×2 のようにビニングを切り替えられるGUIがあれば、評価や開発のスピードも向上します。


ゴール

  • ボタン1クリックで Binning 1×1 / 2×2 を切替
  • 非対応機では自動的にスイッチ無効化
  • 現在の 解像度とBinning値 を常時表示

使用環境 / 前提

  • Basler pylon Camera Software Suite(Basler.Pylon 参照済み)
  • .NET 8 / WPF(Windowsデスクトップ)
  • カメラ:acA2500-14gm(Mono8想定)

コード

これまでの内容に追加で実装していきます。

Baslerカメラ × pylon SDK 制御シリーズまとめ

設計の方針は「停止→設定→ROIフル戻し→再開」といったビニングの設定をカメラクラス側で吸収し、GUIは状態に応じたボタン活性制御サイズ追従のFit呼び出しに専念できるよう分離します。これにより、UIの変更だけでなく、機種差に強い実装となります。

XAML(ツールバー最小)

既存のImageHUDのレイアウトはそのまま。
Gridを1行追加し、上段に切り替えボタンを設けます。

実装が増えてきたので適宜省略します。直近のXAMLの記事はこちらです。(WPF × Basler pylon SDKで背景差分(動体検出)を実装する

<Grid Grid.Row="3" Grid.Column="0">
    <Button x:Name="SetBinning11Button" Content="Binning 1x1" Width="80" Margin="0,5" 
            Command="{Binding SetBinningCommand}"
            CommandParameter="1,1"/>
</Grid>
<Grid Grid.Row="3" Grid.Column="1">
    <Button x:Name="SetBinning22Button" Content="Binning 2x2" Width="80" Margin="0,5" 
            Command="{Binding SetBinningCommand}"
            CommandParameter="2,2"/>
</Grid>
<Grid Grid.Row="3" Grid.Column="2" Grid.ColumnSpan="2">
    <StackPanel Orientation="Horizontal">
        <TextBlock Text="Resolution:" VerticalAlignment="Center"/>
        <TextBlock Text="{Binding ResolutionLabel}" VerticalAlignment="Center"/>
    </StackPanel>
</Grid>
<Grid Grid.Row="3" Grid.Column="4">
    <StackPanel Orientation="Horizontal">
        <TextBlock Text="Binning:" VerticalAlignment="Center"/>
        <TextBlock Text="{Binding BinningLabel}" VerticalAlignment="Center"/>
    </StackPanel>
</Grid>

ついでに現在のステータスを表示させるラベルも画像のGridの下に追加しておきます。

<Grid Grid.Row="5" Grid.Column="0" Grid.ColumnSpan="5" Background="#e9ecef">
    <StackPanel Orientation="Horizontal">
        <TextBlock Text="{Binding StatusMessage}" Margin="6,0,0,0" VerticalAlignment="Center" Opacity="0.8"/>
    </StackPanel>
</Grid>

デザイナのレイアウトは以下のようになります。

BinningGUIXAML.png

ViewModel(最小:コマンドと表示)

MVVMでコマンドを実装していきます。

public sealed class MainViewModel : BindableBase
{
    BaslerCameraSample _cameraService = new BaslerCameraSample();
    private string _statusMessage = "";
    private string _resolutionLabel = "—";
    private string _binningLabel = "—";

    /// <summary>
    /// ビューモデルの初期化を行います。
    /// コマンドの生成や初期表示用の各種状態を設定します。
    /// </summary>
    public MainViewModel()
    {
        // 他のコマンドは省略。

        SetBinningCommand = new DelegateCommand<string>((param) =>
        {
            try
            {
                // "2,2" のような形式で引数を受け取る
                var parts = (param ?? "1,1").Split(',');
                
                if (parts.Length != 2 || !int.TryParse(parts[0], out var h) || !int.TryParse(parts[1], out var v))
                {
                    StatusMessage = "Invalid binning parameter. Use \"H,V\" (e.g., \"2,2\").";
                    return;
                }
                SetBinning(h, v);
            }
            catch (Exception ex)
            {
                StatusMessage = $"Error setting binning: {ex.Message}";
            }
        }, (_) => CanChangeBinning);
    }

    /// <summary>
    /// 操作結果やエラー内容など、状態通知のためのメッセージを表します。
    /// </summary>
    public string StatusMessage
    {
        get => _statusMessage;
        set => SetProperty(ref _statusMessage, value);
    }
    /// <summary>
    /// 現在の解像度(幅×高さ)を表示用の文字列として提供します。
    /// 未接続時は空表示になります。
    /// </summary>
    public string ResolutionLabel
    {
        get => _resolutionLabel;
        private set => SetProperty(ref _resolutionLabel, value);
    }
    /// <summary>
    /// 現在のビニング設定(H×V)を表示用の文字列として提供します。
    /// 取得できない場合は空表示になります。
    /// </summary>
    public string BinningLabel
    {
        get => _binningLabel;
        private set => SetProperty(ref _binningLabel, value);
    }

    /// <summary>
    /// ビニング設定が変更可能かどうかを示します。 
    /// </summary>
    /// <returns></returns>
    public bool CanChangeBinning
        => _cameraService.IsConnected && !_cameraService.IsGrabbing && _cameraService.IsBinningSupported();

    /// <summary>
    /// ビニング設定を変更するコマンドを示します。
    /// </summary>
    /// <value></value>
    public DelegateCommand<string> SetBinningCommand { get; }

    /// <summary>
    /// ビニングを設定します。
    /// </summary>
    /// <param name="h"></param>
    /// <param name="v"></param>
    private void SetBinning(int h, int v)
    {
        if (_cameraService.SetBinning(h, v))
        {

            StatusMessage = $"Binning set: {h}×{v}";
        }
        else
        {
            StatusMessage = $"Failed to set binning: {h}×{v}";
        }
        UpdateResolutionLabel();
        UpdateBinningLabel();
    }
    
    /// <summary>
    /// カメラの現在の解像度を取得して ResolutionLabel を更新します(未接続時は空)。
    /// </summary>
    private void UpdateResolutionLabel()
    {
        if (_cameraService?.IsConnected == true)
            ResolutionLabel = $"{_cameraService.GetWidth()} × {_cameraService.GetHeight()}";
        else
            ResolutionLabel = "—";
    }
    /// <summary>
    /// カメラの現在のビニング値を取得して BinningLabel を更新します(取得不可時は空)。
    /// </summary>
    private void UpdateBinningLabel()
    {
        var b = _cameraService?.GetBinning();
        BinningLabel = (b is { H: > 0, V: > 0 }) ? $"{b.Value.H} × {b.Value.V}" : "—";
    }
}

省略が増えてきて、コードの抜き出しに失敗していないか心配です。


設計メモ

  • 切替は 1×1 / 2×2 のみ:実務ではこの2択で多くの用途をカバーできます。ただし、ComboBoxで実装した方が拡張性は高いです
  • 非対応機のUI無効化CanChangeBinning(接続済・停止中・対応機)で制御しました
  • 安全側の一時停止SetBinning内部で停止→設定→ROIフル戻し→再開を前回記事で実装しました。これはVM側では意識しない“ファサード”となります

実行例

  1. ConnectStart→ライブ表示
  2. StopBinning 2×2Start
    • 解像度ラベルが 2592×1944 → 1296×972 に変わる
  3. StopBinning 1×1 に戻す→サイズ/表示が復帰
  4. 非対応機でボタンが無効化される(IsBinningSupported=false
1x1 2x2
Binning11GUI.png Binning22GUI.png

まとめ

  • 1×1/2×2の簡易切り替えGUIを実装
  • 非対応はボタン無効化

👨‍💻 筆者について

@MilleVision
産業用カメラ・画像処理システムの開発に関する情報を発信中。
pylon SDK × C# の活用シリーズを連載しています。


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

Qiita記事のサンプルをまとめた C#プロジェクト(単体テスト付き) を BOOTH で配布しています。
本記事で省略した BindableBaseDelegateCommand の実装も同梱。

  • 撮影・露光・ゲイン・フレームレート・ROI・イベント駆動撮影など主要機能を網羅
  • WPFへの実装もフォロー
  • 単体テスト同梱で動作確認や学習がスムーズ
  • 記事更新に合わせてアップデート予定
  • 記事投稿後の加筆修正あり

👉 商品ページはこちら

1
1
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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?