IC Imaging Control (.NET C#/Visual Basic)

  • サンプルプログラムトップページ
  • デバイスのオープンとハンドリング
    • C# VB.NET カメラの映像を既存のアプリケーションに組み込む方法
    • C# VB.NET デバイスを開く
    • C# VB.NET デバイスの開閉
    • C# VB.NET ダイアログボックスを使用してデバイスを開く
    • C# VB.NET 複数のデバイスを開く
    • C# VB.NET デバイスのシリアル番号を読み取る
    • C# VB.NET ICImagingControlの標準プロパティダイアログの使用
    • C# VB.NET デバイスプロパティ設定の保存と復元
  • ライブ表示
    • C# VB.NET ライブ表示のリサイズ
    • C# VB.NET フルスクリーン表示
    • C# VB.NET 十字マークのオーバーレイ
    • C# VB.NET WFPでvideoWindowを使ったビデオ表示
  • フレームフィルタ
    • C# VB.NET 低輝度、高輝度ピクセルの強調 その1
    • C# VB.NET 低輝度、高輝度ピクセルの強調 その2
  • ライブ表示とマルチプロセス
    • C# VB.NET ライブ表示のみ
    • C# VB.NET 静止画保存
    • C# VB.NET 任意のタイミングで画像処理と静止画保存を同時に処理
    • C# VB.NET 録画しながら任意のタイミングで静止画保存
    • C# VB.NET 全フレームリアルタイム画像処理しながら
             NG判定を静止画保存
    • C# VB.NET 全フレームリアルタイム画像処理しながら
             NG判定を静止画保存、同時に録画
  • イメージの取得
    • C# VB.NET イメージデータの取得
    • C# VB.NET 静止画ファイル保存(BMP)
    • C# VB.NET 静止画ファイル保存(JPEG)
    • C# VB.NET 静止画ファイルの連番保存
    • C# VB.NET カメラ画像保存&FTPで任意のサーバーに転送する
    • C# VB.NET リングバッファを使用したイメージシーケンスの取得と再生
    • C# VB.NET 静止画とAVI動画保存
    • C# VB.NET メモリーレコーディング
             (高速カメラで撮影した現象をRAMメモリー領域に保存)
    • C# VB.NET ソフトウェアトリガーで画像を表示・保存
    • C# VB.NET 録画時間を指定したAVIファイル保存
    • C# VB.NET 外部トリガーで録画の開始
    • C# VB.NET 取得したイメージの輝度値をCSV形式で出力する
             (16bit対応)
  • 画像処理
    • C# VB.NET イメージデータへのアクセス
    • C# VB.NET コントラストの強調 - Part 1
    • C# VB.NET コントラストの強調 - Part 2
    • C# VB.NET コントラストの強調 - Part 3
    • C# VB.NET レーザーポインタの位置を特定する
    • C# VB.NET OpenCVの画像処理
             (アナログタコメーターのデジタル化)
    • C# VB.NET AIモデルを使ったリアルタイム処理
  • Version 3.5サンプル
    • C# VB.NET 関心領域の画像更新
      Advanced Image Processing
    • C# VB.NET 2値化
      Binarization
    • C# VB.NET 明るさの調整
      BrightnessProperty
    • C# VB.NET 動画保存(MediaStreamSink)
      Capturing a Video File
    • C# VB.NET 動画保存(AviStartCapture)
      Capturing an AVI File
    • C# VB.NET 共通ファイル
      Common
    • C# VB.NET オーバーレイの作成
      Creating an Overlay
    • C# VB.NET デモアプリ
      demoapp
    • C# VB.NET VCDプロパティ:GPIOプロパティ編
      DigitalIO
    • C# VB.NET コールバック関数を使ってバッファを表示させる
      Display Buffer
    • C# VB.NET フィルターの適用
      Filter Inspector
    • C# VB.NET 静止画をキャプチャし保存する
      Grabbing an Image
    • C# VB.NET イメージバッファの輝度値を読み込み、輝度反転処理を施す
      Image Processing
    • C# VB.NET VCDプロパティ:全プロパティ一覧を表示する編
      List VCDProperties
    • C# VB.NET デバイス設定ダイアログの作成
      Making Device Settings
    • C# VB.NET イメージバッファにアクセスする
      Pixelformat
    • C# VB.NET コーデックのプロパティを保存する
      Saving Codec Properties
    • C# VB.NET スクロールとズーム
      croll And Zoom
    • C# VB.NET VCDプロパティ:露光とゲイン編
      StandardProperties
    • C# VB.NET VCDプロパティ:ストロボアウト編
      Strobe
    • C# VB.NET VCDプロパティ:
             プロパティダイアログ画面のカスタマイズ編
      VCD Property Page
    • C# VB.NET VCDプロパティ:明るさとホワイトバランス編
      VCD Simple Property
    • C# VB.NET VCDプロパティ:オートフォーカス編
    • C# VB.NET デバイスの再接続方法とフレーム落ちの確認
  • リンク集

    ICImagingControl WEB APIリファレンスマニュアル/サンプルプログラム

    :日本語対応済み :日本語化準備中
    開発言語 APIリファレンスマニュアル サンプルプログラム
    C 4.0
    ()
    - - 4.0
    ()
    - -
    C++ 4.0
    ()
    3.5
    ()
    3.4
    ()
    4.0
    ()
    3.5 3.4
    ()
    C#/VB.NET 4.0
    ()
    3.5
    ()
    3.4
    ()
    4.0
    ()
    3.5
    ()
    3.4
    ()
    Python 4.0
    ()
    3.5 3.4
    ()
    4.0
    ()
    3.5 3.4
    ()

WFPでvideoWindowを使ったビデオ表示

概要

このプログラムは、WPFアプリケーションでTheImagingSource社のカメラを制御・表示しています。主な処理は、カメラの設定読み込み、映像の取得、画像表示、そして画像の反転や回転処理です。ボタン操作で保存されたカメラ設定ファイルを読み込み、ビデオフォーマットに応じたピクセル形式(RGB24、RGB64、Y16など)を自動で判別し、FrameQueueSinkを通してカメラ映像をリアルタイムで受信・表示します。取得したフレームはWriteableBitmap形式 に変換され、必要に応じてRGB64対応の表示処理も行われます。

サンプルプログラム

Software IC Imaging Control 3.5, Visual Studio™ 2022
サンプル(C#) IC_WPF_cs_3.5.zip

サンプルプログラムの外観

解説

初期化

public MainWindow()
{
    InitializeComponent();
    _rotateFlipFilter = _ic.FrameFilterCreate("Rotate Flip", "");
    _ic.DeviceFrameFilters.Add(_rotateFlipFilter);
    _ic.Sink = new FrameQueueSink(ShowBuffer, MediaSubtypes.RGB32, 5);
}

IこのコードはWPFのMainWindow初期化処理です。InitializeComponent()でUIを初期化し、回転・反転用のフィルターRotate Flipを作成してカメラ映像に適用します。続いて、画像受信用のFrameQueueSinkをRGB32形式で設定し、カメラからのフレームを受け取れるようにします。

画像の受信と表示処理

private FrameQueuedResult ShowBuffer(IFrameQueueBuffer buffer)
{
    videoWindow1.UpdateImage(buffer);
    //画像を保存(64bit対応)
    //TIS.Imaging.FrameExtensions.SaveAsTiff(buffer, "RGB64.tiff");
    return FrameQueuedResult.ReQueue;
}

この関数ShowBufferは、カメラからフレームが届いたときに呼び出されるコールバック処理です。引数bufferは1フレーム分の画像データを表しており、それをvideoWindow1.UpdateImage()を使ってWPFの画面に表示します。処理後、FrameQueuedResult.ReQueueを返すことで、このバッファを再利用し、次のフレームも連続して受け取れるようにします。これにより、リアルタイムなライブ映像表示が可能になります。

デバイス選択時のフォーマット判定とSinkの切り替え

// デバイス選択ボタンがクリックされたときの処理
private void btnSelectDevice_Click(object sender, RoutedEventArgs e)
{
    // カメラのライブ映像を一時停止
    _ic.LiveStop();

    // デバイス設定ダイアログの代わりに、保存された設定ファイルを読み込む
    //_ic.ShowDeviceSettingsDialog();
    _ic.LoadShowSaveDeviceState("lastSelectedDeviceState.xml");

    // 有効なデバイスが選択されていれば処理を継続
    if (_ic.DeviceValid)
    {
        // 現在のビデオフォーマット文字列を取得(例:RGB24(640x480))
        string videoformat = _ic.VideoFormat;

        // "(" の位置を探して、その前の文字列(カラーフォーマットの種類)を抽出
        int index = videoformat.IndexOf('(');
        string beforeParenthesis = "";
        if (index >= 0)
        {
            beforeParenthesis = videoformat.Substring(0, index).Trim(); // 空白除去
        }
        else
        {
            Console.WriteLine("( が見つかりませんでした。");
        }

        // カラーフォーマットに応じて Sink(画像受け取り方式)を切り替える
        if (beforeParenthesis == "RGB24")
        {
            _ic.Sink = new FrameQueueSink(ShowBuffer, MediaSubtypes.RGB24, 5);
        }
        else if (beforeParenthesis == "RGB32")
        {
            _ic.Sink = new FrameQueueSink(ShowBuffer, MediaSubtypes.RGB32, 5);
        }
        else if (beforeParenthesis == "RGB64")
        {
            _ic.Sink = new FrameQueueSink(ShowBuffer, MediaSubtypes.RGB64, 5);
        }
        else if (beforeParenthesis == "Y16")
        {
            _ic.Sink = new FrameQueueSink(ShowBuffer, MediaSubtypes.Y16, 5);
        }
        else if (videoformat == "Y800")
        {
            _ic.Sink = new FrameQueueSink(ShowBuffer, MediaSubtypes.Y800, 5);
        }
        else
        {
            // 未知のフォーマットの場合は RGB24 をデフォルトとして使用
            _ic.Sink = new FrameQueueSink(ShowBuffer, MediaSubtypes.RGB24, 5);
        }

        // カメラのライブ映像を再開
        _ic.LiveStart();
    }
}

このコードは、WPFアプリで[Select Devide...]ボタンが押されたときに実行される処理です。まず、カメラのライブ映像を一時停止し、保存されている設定ファイル(lastSelectedDeviceState.xml)を読み込んで前回使用したカメラ設定を復元します。その後、現在のビデオフォーマット(例:RGB24(640x480))から「RGB24」などのカラーフォーマットを抽出し、使用するMediaSubtypeに応じたFrameQueueSinkを設定します。これにより、カメラからの画像データを適切なカラーフォーマットで取り込めるようになります。最後にLiveStart()を呼び、再びライブ映像の表示を開始します。カラーフォーマットに応じて処理を切り替えることで、RGB24・RGB64・モノクロ8bit・モノクロ16bitなどの様々なカラーフォーマットに対応しています。

チェックボックスとRotate Flipフィルターの連動

private void chkRotateFlipH_Checked(object sender, RoutedEventArgs e)
{
    _rotateFlipFilter.SetBoolParameter("Flip H", chkRotateFlipH.IsChecked.Value);
}
private void chkRotateFlipH_Unchecked(object sender, RoutedEventArgs e)
{
    _rotateFlipFilter.SetBoolParameter("Flip H", chkRotateFlipH.IsChecked.Value);
}
private void chkFlipRotateV_Checked(object sender, RoutedEventArgs e)
{
    _rotateFlipFilter.SetBoolParameter("Flip V", chkRotateFlipV.IsChecked.Value);
}
private void chkFlipRotateV_Unchecked(object sender, RoutedEventArgs e)
{
    _rotateFlipFilter.SetBoolParameter("Flip V", chkRotateFlipV.IsChecked.Value);
}

「水平方向の反転(Flip H)」「垂直方向の反転(Flip V)」を制御するチェックボックスのイベントハンドラです。
例えば、SetBoolParameter("Flip H", true/false)により、回転フィルターの水平反転機能をON/OFFしています。チェックを入れても外しても、現在の値(IsChecked.Value)をそのままフィルターに適用し、チェックボックスとの連動するようにしています。

WPFアプリケーション上に表示するための処理

// カメラから取得した画像フレームを WPF の Image に表示する処理
public void UpdateImage(TIS.Imaging.IFrame buffer)
{
    // 現在のスレッドが UI スレッドか確認
    if (display.Dispatcher.CheckAccess())
    {
        // UI スレッドであれば、直接描画処理を実行
        DoUpdateImage(buffer);
    }
    else
    {
        // UI スレッド以外からの呼び出しの場合

        // すでに非同期描画処理が進行中であれば処理をスキップ(多重更新防止)
        if ((_updateImageOperation != null) && (_updateImageOperation.Status != System.Windows.Threading.DispatcherOperationStatus.Completed))
        {
            return;
        }

        // UI スレッドに非同期で描画処理を依頼
        _updateImageOperation = display.Dispatcher.BeginInvoke(new Action(() => DoUpdateImage(buffer)));
    }
}

// UIスレッド上での非同期更新操作の状態を保持する変数
private System.Windows.Threading.DispatcherOperation _updateImageOperation = null;

// 実際の画像更新処理を行う関数(UIスレッド上で実行される)
private void DoUpdateImage(TIS.Imaging.IFrame buffer)
{
    // フレームのサイズとピクセルフォーマットを取得
    int bufferWidth = buffer.FrameType.Width;
    int bufferHeight = buffer.FrameType.Height;
    PixelFormat bufferFormat = PixelFormatFromFrameType(buffer.FrameType);

    // フレームバッファのポインタを取得
    IntPtr ptr = buffer.GetIntPtr();

    // 現在の WriteableBitmap が null または サイズ・フォーマットが異なる場合は再作成
    if ((_source == null)
        || (_source.PixelWidth != bufferWidth)
        || (_source.PixelHeight != bufferHeight)
        || (_source.Format != bufferFormat))
    {
        if (buffer.FrameType.BitsPerPixel == 64)
        {
            // RGB64(16bit × 4ch)の場合は専用の変換処理で WriteableBitmap を生成
            _source = ConvertRgb64ToWriteableBitmap(ptr, bufferWidth, bufferHeight);
        }
        else
        {
            // 通常フォーマット(例:RGB24)の場合は WriteableBitmap を作成してバッファをコピー
            _source = CreateBackBuffer(bufferWidth, bufferHeight, bufferFormat);
            CopyImageBufferToWritableBitmap(buffer, _source);
        }

        // WPFの Image コントロールに表示
        display.Source = _source;
    }
    else
    {
        // バッファサイズとフォーマットが同じであれば、既存の WriteableBitmap に上書きするだけでOK
        CopyImageBufferToWritableBitmap(buffer, _source);
    }

    // オーバーレイ描画用のアドーナーがある場合は再描画を要求
    if (_overlayAdorner != null)
    {
        _overlayAdorner.InvalidateVisual();
    }

    // 画像が上下逆かどうかの情報を記録(フリップ描画の補正に使用)
    IsSourceBottomUp = buffer.FrameType.IsBottomUp;

    // FlipH / FlipV の状態に基づいて描画の反転を更新
    UpdateFlip();
}

このコードは、The Imaging Controlで取得したカメラ映像フレーム(IFrame)をWPFアプリケーション上に表示するための処理を行います。UpdateImageメソッドは、フレームをWPFのImageコントロールに表示する前処理であり、現在のスレッドがUIスレッドかどうかをDispatcher.CheckAccess()で確認します。UIスレッドでなければ、非同期にDoUpdateImageを呼び出します。重複更新を防ぐため、未完了の更新操作があれば処理をスキップします。

DoUpdateImageは、画像サイズやフォーマットが変わった場合に新たなWriteableBitmapを生成し、RGB64形式の場合は専用の変換処理(ConvertRgb64ToWriteableBitmap)を用いてWPFの表示できる形式(RGB24)に変換します。既存のサイズ・形式と一致する場合は、バッファだけを更新して高速化しています。オーバーレイ表示の再描画を行い、上下反転の補正情報IsSourceBottomUpをUpdateFlip()に反映させることで、映像表示と描画が正しく整合されます。

映像表示のためにRGB64からRGB24に変換

public static WriteableBitmap ConvertRgb64ToWriteableBitmap(IntPtr bufferPtr, int width, int height)
{
    int pixelCount = width * height;
    int srcBytesPerPixel = 8; // R16 G16 B16 A16 = 16bit × 4ch
    int dstBytesPerPixel = 3; // 8bit RGB

    int dstStride = ((width * dstBytesPerPixel + 3) / 4) * 4; // 4バイトアライメント

    byte[] srcBuffer = new byte[pixelCount * srcBytesPerPixel];
    byte[] dstBuffer = new byte[dstStride * height];

    // TISバッファ(RGB64)をコピー
    Marshal.Copy(bufferPtr, srcBuffer, 0, srcBuffer.Length);

    for (int y = 0; y < height; y++)
    {
        for (int x = 0; x < width; x++)
        {
            int i = y * width + x;

            int srcIndex = i * srcBytesPerPixel;
            int dstIndex = y * dstStride + x * dstBytesPerPixel;

            // 各チャンネルの上位8bitを取得(リトルエンディアン)
            ushort r16 = (ushort)(srcBuffer[srcIndex + 0] | (srcBuffer[srcIndex + 1] << 8));
            ushort g16 = (ushort)(srcBuffer[srcIndex + 2] | (srcBuffer[srcIndex + 3] << 8));
            ushort b16 = (ushort)(srcBuffer[srcIndex + 4] | (srcBuffer[srcIndex + 5] << 8));

            dstBuffer[dstIndex + 0] = (byte)(b16 >> 8); // B
            dstBuffer[dstIndex + 1] = (byte)(g16 >> 8); // G
            dstBuffer[dstIndex + 2] = (byte)(r16 >> 8); // R
        }
    }

    // WPFのWriteableBitmapを作成
    WriteableBitmap wb = new WriteableBitmap(
        width,
        height,
        96, 96, // DPI
        PixelFormats.Rgb24,
        null);

    wb.WritePixels(new Int32Rect(0, 0, width, height), dstBuffer, dstStride, 0);

    return wb;
}

この関数は、IC Imaging Controlから得られるRGB64形式(16bit×4チャンネル:R16G16B16A16)の画像バッファを、WPFで扱える8bit×3チャンネル(RGB24)に変換して表示するための WriteableBitmap を作成します。

まず、ネイティブメモリ(IntPtr)の画像バッファをMarshal.CopyでC#のバイト配列にコピーし、各画素ごとにR・G・Bの上位8bit(16bit→8bit)を抽出して新たなバッファに変換します。変換後はWriteableBitmap.WritePixelsを使ってWPFに描画可能な画像オブジェクトを生成して返しています。

この処理によって画像の表示が遅くなることがありますので表示を早くしたい場合にはRGB24やRGB32のカラーフォーマットをあらかじめ設定しておいてください。

画像上で上下・左右反転(Rotateを使用せず)

// 映像の上下反転を制御する依存関係プロパティ(WPFバインディング対応)
// デフォルト値は false(反転なし)
// 値が変更されると再描画が発生し、FlipChanged が呼ばれる
public static readonly DependencyProperty FlipVProperty =
    DependencyProperty.Register("FlipV", typeof(Boolean), typeof(VideoWindow),
        new FrameworkPropertyMetadata(false,
            FrameworkPropertyMetadataOptions.AffectsRender,
            new PropertyChangedCallback(FlipChanged)
        ));

// 映像の左右反転を制御する依存関係プロパティ(WPFバインディング対応)
// デフォルト値は false(反転なし)
// 値が変更されると再描画が発生し、FlipChanged が呼ばれる
public static readonly DependencyProperty FlipHProperty =
    DependencyProperty.Register("FlipH", typeof(Boolean), typeof(VideoWindow),
        new FrameworkPropertyMetadata(false,
            FrameworkPropertyMetadataOptions.AffectsRender,
            new PropertyChangedCallback(FlipChanged)
        ));

// 上下反転状態にアクセスするための CLRプロパティ(XAMLやコードから使用可能)
public bool FlipV
{
    get
    {
        return (bool)GetValue(FlipVProperty); // 現在の値を取得
    }
    set
    {
        SetValue(FlipVProperty, value); // 値を設定(FlipChangedが自動で呼ばれる)
    }
}

// 左右反転状態にアクセスするための CLRプロパティ(XAMLやコードから使用可能)
public bool FlipH
{
    get
    {
        return (bool)GetValue(FlipHProperty); // 現在の値を取得
    }
    set
    {
        SetValue(FlipHProperty, value); // 値を設定(FlipChangedが自動で呼ばれる)
    }
}

// FlipV または FlipH のプロパティ値が変更されたときに呼ばれるコールバック関数
// 実際の反転処理(描画の更新)を行う UpdateFlip を呼び出す
static void FlipChanged(DependencyObject dep, DependencyPropertyChangedEventArgs e)
{
    var vw = dep as VideoWindow;  // プロパティが変更された VideoWindow を取得
    vw.UpdateFlip();              // 反転状態を描画に反映
}

このコードは、WPFで画像の上下・左右反転を切り替えるための仕組みを実装したものです。WPFでは通常のプロパティとは別に「依存関係プロパティ(DependencyProperty)」という特殊な仕組みを使うことで、UIのXAMLとの連携や自動再描画が可能になります。ここでは FlipV(上下反転)と FlipH(左右反転)という2つのプロパティを定義し、どちらも false(反転なし)を初期値としています。値が変更されるとFlipChanged関数が自動で呼ばれ、反転状態を画面に反映するUpdateFlip()が実行されます。これにより、ユーザーがチェックボックスなどを使って反転を切り替えた際、即座に映像が反映される仕組みになっています。

▲ このページの先頭に戻る

Copyright © ARGO Corporation. All Rights Reserved.