VCDプロパティ:全プロパティ一覧を表示する編
List VCDProperties
概要
カメラデバイスの露光時間やゲイン等の機能を制御するためにVCDプロパティと呼ばれるIC Imaging Controlが用意したインターフェースがあります。VCDプロパティはツリー構造で構成されており、値、範囲、自動設定のような様々な含んでおり、このサンプルでは接続したそれらのVCDプロパティすべてをツリービュー形式で表示しています。
サンプルプログラム
| 利用した開発環境 | Visual Studio™ 2019 | 
|---|---|
| SDK | IC Imaging Control 3.5(Python, C#, VB.NET) | 
| デバイスドライバ | Cam33U_setup,gigecam_setup,usbcam,AFU420_setup,usb2pro_drv | 
| デバイス | TISカメラ全般(MIPI CSI-2&FPD-Link IIIカメラを除く) | 
| サンプル(C#) | list_vcdproperties_cs_3.5.zip | 
| サンプル(VB.NET) | list_vcdproperties_vb_3.5.zip | 
| exeファイル アプリケーション | ー | 
| 別途ファイル | ー | 
| 関連参照URL | ー | 
実行結果

Visual Studioのプログラム上ではすでにボタンの設置や関数は定義済ですので、IC Imaging Contorl3.5をインストールされていれば、実行ボタンだけですぐにデバッグで動作確認することができます。
  画面にあるそれぞれのボタンなどのコントローラの機能は下記の通りです。
| [Select Device]ボタン | デバイスを選択するダイアログ画面を表示 | 
|---|---|
| [Show Property Page]ボタン | デバイスプロパティのダイアログ画面を表示 | 
| Tree Viewer | カメラにある機能の一覧を表示し、選択した機能の設定を変更することができます。 | 
初期設定
private void Form1_Load(object sender, EventArgs e)
{
    if( !icImagingControl1.LoadShowSaveDeviceState("lastSelectedDeviceState.xml") )
    {
        MessageBox.Show("No device was selected.");
        this.Close();
        return;
    }
    // カメラの設定した解像度に合わせて表示画面を変更
    icImagingControl1.LiveDisplayDefault = false;
    icImagingControl1.LiveDisplaySize = icImagingControl1.Size;
    //Tree Viewerの初期化
    UpdateStateAfterDeviceSelect();
}
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    If IcImagingControl1.DeviceValid = False Then
        ' SelectDeviceボタンイベントハンドラの呼び出し(デバイスセッティングダイアログを表示)
        btnSelectDevice_Click(Me, Nothing)
    End If
    If IcImagingControl1.DeviceValid = True Then
        ' ライブストリーミング開始
        IcImagingControl1.LiveStart()
        ' カメラの設定した解像度に合わせて表示画面を変更
        IcImagingControl1.LiveDisplayDefault = False
        IcImagingControl1.LiveDisplaySize = IcImagingControl1.Size
        ' Tree Viewerの初期化
        QueryVCDProperties()
    End If
End Subフォームロードするタイミングの処理内容です。
  LoadShowSaveDeviceStateメソッドにてデバイスを割り当て、LiveDisplaySizeプロパティを使用することで、カメラの設定した解像度に合わせて表示画面を変更しています。
private void UpdateStateAfterDeviceSelect()
{
    //すべてのプロパティ要素(PropertyElement)、およびインターフェイスを列挙
    ListAllPropertyItems();
    //ライブストリーミングを開始
    icImagingControl1.LiveStart();
    // TreeViewを初期化する
    BuildVCDPropertiesTree();
} 初期設定で呼び出す内容として接続したカメラデバイスのプロパティおよびインターフェースを列挙したのちに、ライブストリーミングを開始しTreeViewにセットするところまで行っています。
下記ではListAllPropertyItemsとBuildVCDPropertiesTreeのぞれぞれの関数について説明します。
ListAllPropertyItems関数(すべてのプロパティ要素およびインターフェースを列挙)
private void ListAllPropertyItems()
{
    // すべてのプロパティ アイテムを取得する
    foreach (TIS.Imaging.VCDPropertyItem PropertyItem in icImagingControl1.VCDPropertyItems)
    {
        System.Diagnostics.Debug.WriteLine(PropertyItem.Name);
        // 現在のプロパティ アイテムのすべてのプロパティ要素を取得
        foreach (TIS.Imaging.VCDPropertyElement PropertyElement in PropertyItem.Elements)
        {
            System.Diagnostics.Debug.WriteLine("    Element : " + PropertyElement.Name);
            // 現在のプロパティ要素のすべてのインターフェイスを取得します。
            foreach (TIS.Imaging.VCDPropertyInterface PropertyInterFace in PropertyElement)
            {
                System.Diagnostics.Debug.Write("        Interface ");
                try
                {
                    // 現在のインターフェイスを適切な型にキャストして、
                    // 特別なインターフェイス プロパティにアクセスします。
                    //AbsoluteValue:絶対値型
                    if ( PropertyInterFace.InterfaceGUID == TIS.Imaging.VCDGUIDs.VCDInterface_AbsoluteValue )
                    {
                        var AbsoluteValue = (TIS.Imaging.VCDAbsoluteValueProperty)PropertyInterFace;
                        System.Diagnostics.Debug.Write("Absolute Value : ");
                        System.Diagnostics.Debug.WriteLine(AbsoluteValue.Value.ToString());
                    }
                    //MapStrings:リスト型
                    else if ( PropertyInterFace.InterfaceGUID == TIS.Imaging.VCDGUIDs.VCDInterface_MapStrings )
                    {
                        var MapString = (TIS.Imaging.VCDMapStringsProperty)PropertyInterFace;
                        System.Diagnostics.Debug.Write("Mapstring : ");
                        System.Diagnostics.Debug.WriteLine(MapString.String);
                    }
                    //Switch:切り替え型
                    else if( PropertyInterFace.InterfaceGUID == TIS.Imaging.VCDGUIDs.VCDInterface_Switch )
                    {
                        var Switch = (TIS.Imaging.VCDSwitchProperty)PropertyInterFace;
                        System.Diagnostics.Debug.Write("Switch : ");
                        System.Diagnostics.Debug.WriteLine(Switch.Switch.ToString());
                    }
                    //Button:ボタン型
                    else if( PropertyInterFace.InterfaceGUID == TIS.Imaging.VCDGUIDs.VCDInterface_Button )
                    {
                        var Button = (TIS.Imaging.VCDButtonProperty)PropertyInterFace;
                        System.Diagnostics.Debug.WriteLine("Button");
                    }
                    //Range:閾値(範囲)型
                    else if( PropertyInterFace.InterfaceGUID == TIS.Imaging.VCDGUIDs.VCDInterface_Range )
                    {
                        var Range = (TIS.Imaging.VCDRangeProperty)PropertyInterFace;
                        System.Diagnostics.Debug.Write("Range : ");
                        System.Diagnostics.Debug.WriteLine(Range.Value.ToString());
                    }
                }
                catch( Exception ex )
                {
                    System.Diagnostics.Debug.WriteLine("<error>:" + ex);
                }
            }
        }
    }
}
Private Sub ListAllPropertyItems()
    Dim PropertyItem As TIS.Imaging.VCDPropertyItem
    Dim PropertyElement As TIS.Imaging.VCDPropertyElement
    Dim PropertyInterFace As TIS.Imaging.VCDPropertyInterface ' Default interface type.
    'すべてのインターフェースを定義
    Dim Range As TIS.Imaging.VCDRangeProperty
    Dim Switch As TIS.Imaging.VCDSwitchProperty
    Dim AbsoluteValue As TIS.Imaging.VCDAbsoluteValueProperty
    Dim MapString As TIS.Imaging.VCDMapStringsProperty
    Dim Button As TIS.Imaging.VCDButtonProperty
    'aすべてのプロパティ アイテムを取得する
    For Each PropertyItem In IcImagingControl1.VCDPropertyItems
        System.Diagnostics.Debug.WriteLine(PropertyItem.Name)
        ' 現在のプロパティ アイテム(item)のすべてのプロパティ要素を取得
        For Each PropertyElement In PropertyItem.Elements
            System.Diagnostics.Debug.WriteLine("    Element : " + PropertyElement.Name)
            ' 現在のプロパティ要素(element)のすべてのインターフェイスを取得します。
            For Each PropertyInterFace In PropertyElement
                System.Diagnostics.Debug.Write("        Interface ")
                Try
                    '現在のインターフェイスを適切な型にキャストして、
                    '特別なインターフェイス プロパティにアクセスします。
                    Select Case PropertyInterFace.InterfaceGUID
                        Case VCDGUIDs.VCDInterface_AbsoluteValue
                            AbsoluteValue = PropertyInterFace
                            System.Diagnostics.Debug.WriteLine("Absolut Value : " + AbsoluteValue.Value.ToString)
                        Case VCDGUIDs.VCDInterface_MapStrings
                            MapString = PropertyInterFace
                            System.Diagnostics.Debug.WriteLine("Mapstring : " + MapString.String)
                        Case VCDGUIDs.VCDInterface_Switch
                            Switch = PropertyInterFace
                            System.Diagnostics.Debug.WriteLine("Switch : " + Switch.Switch.ToString)
                        Case VCDGUIDs.VCDInterface_Button
                            Button = PropertyInterFace
                            System.Diagnostics.Debug.WriteLine("Button")
                        Case VCDGUIDs.VCDInterface_Range
                            Range = PropertyInterFace
                            System.Diagnostics.Debug.WriteLine("Range : " + Range.Value.ToString)
                    End Select
                Catch ex As System.Exception
                    System.Diagnostics.Debug.WriteLine("<error>")
                End Try
            Next
        Next
    Next
End Sub
カメラにアクセスし、すべてのプロパティ要素(PropertyElement)、およびインターフェイスを列挙する方法を示しています。
  VCDプロパティのすべてのプロパティにアクセスするためには、プロパティ項目、要素、インターフェースを指定する手段(VCDPropertyItems→PropertyElement→PropertyInterFace)でそれぞれのプロパティオブジェクトに順々にアクセスする必要があります。それぞれのクラスは下記の通りです。
| VCDPropertyItem | カメラがサポートするVCDプロパティにアクセスするための機能(VCDPropertyItemオブジェクトのコレクションやVCDPropertyElementコレクション)を含むクラスです。 | 
|---|---|
| VCDPropertyElement | エレメントを調整する為のインターフェースのセットを含んでおり、プロパティへの様々なアクセスメソッドが用意されています。 | 
| VCDPropertyInterFace | プロパティからデータを読み取り、またデータをプロパティに書き込むものです。下記のプロパティはこのVCDPropertyInterfaceを継承しております。 なお、現在のインターフェイスのプロパティに正しくアクセスするには、インターフェイスを範囲、絶対値などの適切なインターフェイス タイプに「キャスト」する必要があります。 | 
BuildVCDPropertiesTreeItems関数(VCDPropertyItemをTreeViewに追加)
private void BuildVCDPropertiesTreeItems(TreeNode pp, TIS.Imaging.VCDPropertyItems props)
{
    // すべての VCDPropertyItem を反復処理して、ツリーに挿入します
    foreach (TIS.Imaging.VCDPropertyItem item in props)
    {
        // アイテムの新しいツリー ノードを作成します
        TreeNode newNode = new TreeNode(item.Name, 0, 0);
        pp.Nodes.Add(newNode);
        //要素(element)を挿入
        QueryVCDPropertyElements(newNode, item);
    }
}
Private Sub QueryVCDPropertyItems(ByVal ParentNode As TreeNode, ByVal PropertyItems As TIS.Imaging.VCDPropertyItems)
    ' すべての VCDPropertyItem を反復処理して、ツリーに挿入します
    For Each item As TIS.Imaging.VCDPropertyItem In PropertyItems
        ' アイテムの新しいツリー ノードを作成します
        Dim newNode As New TreeNode(item.Name, 0, 0)
        newNode.Tag = Nothing
        ParentNode.Nodes.Add(newNode)
        ' 要素(element)を追加
        QueryVCDPropertyElements(newNode, item)
    Next
End Sub
カメラにあるアイテム(例えば、GainやExposureなど)をすべて、TreeViewに追加をしています。
QueryVCDPropertyElements関数(VCDPropertyElementをTreeViewのノードに追加)
private void QueryVCDPropertyElements(TreeNode pp, TIS.Imaging.VCDPropertyItem item)
{
    foreach (TIS.Imaging.VCDPropertyElement elem in item.Elements)
    {
        TreeNode newNode = null;
        //要素(element)の名前を割り振り
        if( elem.ElementGUID == TIS.Imaging.VCDGUIDs.VCDElement_Value )
            newNode = new TreeNode("VCDElement_Value: '" + elem.Name + "'", 1, 1);
        else if ( elem.ElementGUID == TIS.Imaging.VCDGUIDs.VCDElement_Auto )
            newNode = new TreeNode("VCDElement_Auto: '" + elem.Name + "'", 2, 2);       
        else if ( elem.ElementGUID == TIS.Imaging.VCDGUIDs.VCDElement_OnePush )
            newNode = new TreeNode("VCDElement_OnePush: '" + elem.Name + "'", 3, 3);
        else if ( elem.ElementGUID == TIS.Imaging.VCDGUIDs.VCDElement_WhiteBalanceRed )
            newNode = new TreeNode("VCDElement_WhiteBalanceRed: '" + elem.Name + "'", 4, 4);
        else if ( elem.ElementGUID == TIS.Imaging.VCDGUIDs.VCDElement_WhiteBalanceBlue )
            newNode = new TreeNode("VCDElement_WhiteBalanceBlue: '" + elem.Name + "'", 4, 4);
        else
            newNode = new TreeNode("Other Element ID: '" + elem.Name + "'", 4, 4);
        pp.Nodes.Add(newNode);
        // インターフェースを挿入
        QueryVCDPropertyInterface(newNode, elem);
    }
}Private Sub QueryVCDPropertyElements(ByVal ParentNode As TreeNode, ByVal PropertyItem As TIS.Imaging.VCDPropertyItem)
    ' generate a display name
    Dim name As String
    Dim Image As Integer
    Dim Element As TIS.Imaging.VCDPropertyElement
    For Each Element In PropertyItem.Elements
        '要素(element)の名前を割り振り
        Select Case Element.ElementGUID
            Case VCDGUIDs.VCDElement_Value
                name = "VCDElement_Value"
                Image = 1
            Case VCDGUIDs.VCDElement_Auto
                name = "VCDElement_Auto"
                Image = 2
            Case VCDGUIDs.VCDElement_OnePush
                name = "VCDElement_OnePush"
                Image = 3
            Case VCDGUIDs.VCDElement_WhiteBalanceRed
                name = "VCDElement_WhiteBalanceRed"
                Image = 4
            Case VCDGUIDs.VCDElement_WhiteBalanceBlue
                name = "VCDElement_WhiteBalanceBlue"
                Image = 4
            Case Else
                name = "Other Element ID"
                Image = 4
        End Select
        Dim newNode As New TreeNode(name + ": " + Element.Name, Image, Image)
        newNode.Tag = Nothing
        ParentNode.Nodes.Add(newNode)
        ' インターフェースを挿入
        QueryVCDPropertyInterface(newNode, Element)
    Next
End Subカメラの機能で同様な制御があるのかを判断し、それをVCDPropertyItemのノードの下に追加しています。
例えば、カメラの機能のゲインの場合値を設定するVCDElement_Valueや自動ゲイン機能を設定するVCDElement_Autoなどがあります。
これらの設定できるエレメントをその機能に応じて要素をノードに追加しています。
QueryVCDPropertyInterface関数(すべてのインターフェースを挿入)
private void QueryVCDPropertyInterface(TreeNode pp, TIS.Imaging.VCDPropertyElement elem)
{
    foreach (TIS.Imaging.VCDPropertyInterface itf in elem)
    {
        TreeNode newNode;
        if( itf.InterfaceGUID == TIS.Imaging.VCDGUIDs.VCDInterface_AbsoluteValue )
            newNode = new TreeNode("AbsoluteValue", 4, 4);
        else if( itf.InterfaceGUID == TIS.Imaging.VCDGUIDs.VCDInterface_MapStrings )
            newNode = new TreeNode("MapStrings", 6, 6);
        else if( itf.InterfaceGUID == TIS.Imaging.VCDGUIDs.VCDInterface_Range )
            newNode = new TreeNode("Range", 4, 4);
        else if( itf.InterfaceGUID == TIS.Imaging.VCDGUIDs.VCDInterface_Switch )
            newNode = new TreeNode("Switch", 5, 5);
        else if( itf.InterfaceGUID == TIS.Imaging.VCDGUIDs.VCDInterface_Button )
            newNode = new TreeNode("Button", 3, 3);
        else
        {
            newNode = new TreeNode(itf.InterfaceGUID.ToString(), 4, 4);
        }
        // Tag プロパティがノードでインターフェースを保持
        newNode.Tag = itf;
        pp.Nodes.Add(newNode);
    }
}Private Sub QueryVCDPropertyInterface(ByVal ParentNode As TreeNode, ByVal PropertyElement As TIS.Imaging.VCDPropertyElement)
    Dim Name As String
    Dim image As Integer
    Dim Itf As TIS.Imaging.VCDPropertyInterface
    ' 
    For Each Itf In PropertyElement
        'インターフェース(interface)の名前を割り振り
        Select Case Itf.InterfaceGUID
            Case VCDGUIDs.VCDInterface_AbsoluteValue
                Name = "AbsoluteValue"
                image = 4
            Case VCDGUIDs.VCDInterface_MapStrings
                Name = "MapStrings"
                image = 6
            Case VCDGUIDs.VCDInterface_Range
                Name = "Range"
                image = 4
            Case VCDGUIDs.VCDInterface_Switch
                Name = "Switch"
                image = 5
            Case VCDGUIDs.VCDInterface_Button
                Name = "Button"
                image = 3
            Case Else
                Name = "AbsoluteValue"
                image = 4
        End Select
        'Tag プロパティがノードでインターフェースを保持
        Dim newNode As New TreeNode(Name, image, image)
        newNode.Tag = Itf.Parent.Parent.ItemGUID.ToString() + ":" + Itf.Parent.ElementGUID.ToString() + ":" + Itf.InterfaceGUID.ToString()
        ParentNode.Nodes.Add(newNode)
    Next
End SubVCDPropertyElementsのノードの下に使用できるすべてのインターフェースを追加していきます。
  例えば、カメラのGainの機能ではAbsoluteValueやRangeが設定できるます。
  それらの機能に応じて設定できる下記のインターフェースをノードに追加しています。
| VCDAbsoluteValueProperty | 絶対値型 | 
|---|---|
| VCDButtonProperty | ボタン型 | 
| VCDRangeProperty | 閾値(範囲)型 | 
| VCDMapStringsProperty | リスト型 | 
| VCDSwitchProperty | 切り替え型 | 
これでカメラのすべてのプロパティへアクセスし、TreeViewへの表示・反映をすることができます。
VCDPropertyのコントロール
private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
{
    // Tagプロパティが空の場合
    if (Tree.SelectedNode.Tag == null)
    {
        return;
    }
    // すべてのコントロールを隠す
    foreach( var ctrl in _currentControls )
    {
        ctrl.Dispose();
    }
    _currentControls.Clear();
    TIS.Imaging.VCDPropertyInterface itf = Tree.SelectedNode.Tag as TIS.Imaging.VCDPropertyInterface;
    if (itf != null)
    {
        itf.Update();
        // 選択したインターフェースのタイプに一致するコントロールグループを表示し、初期化します。
        if ( itf.InterfaceGUID == TIS.Imaging.VCDGUIDs.VCDInterface_AbsoluteValue )
             ShowAbsoluteValueControl(itf);
        else if( itf.InterfaceGUID == TIS.Imaging.VCDGUIDs.VCDInterface_MapStrings)
            ShowComboBoxControl(itf);
        else if( itf.InterfaceGUID == TIS.Imaging.VCDGUIDs.VCDInterface_Range)
            ShowRangeControl(itf);
        else if( itf.InterfaceGUID == TIS.Imaging.VCDGUIDs.VCDInterface_Switch)
            ShowSwitchControl(itf);
        else if( itf.InterfaceGUID == TIS.Imaging.VCDGUIDs.VCDInterface_Button)
            ShowButtonControl(itf);
    }
}Private Sub Tree_AfterSelect(ByVal sender As System.Object, ByVal e As System.Windows.Forms.TreeViewEventArgs) Handles Tree.AfterSelect
    ' Tagプロパティが空の場合
    If Tree.SelectedNode.Tag Is Nothing Then Exit Sub
    If Not RangeCtrl Is Nothing Then RangeCtrl.Dispose()
    If Not SwitchCtrl Is Nothing Then SwitchCtrl.Dispose()
    If Not MapStringsCtrl Is Nothing Then MapStringsCtrl.Dispose()
    If Not ButtonCtrl Is Nothing Then ButtonCtrl.Dispose()
    If Not AbsValCtrl Is Nothing Then AbsValCtrl.Dispose()
    Dim itfPath As String = Tree.SelectedNode.Tag
    Dim itf As TIS.Imaging.VCDPropertyInterface = IcImagingControl1.VCDPropertyItems.FindInterface(itfPath)
    If Not itf Is Nothing Then
        itf.Update()
        ' 選択したインターフェースのタイプに一致するコントロールグループを表示し、初期化します。
        Select Case itf.InterfaceGUID
            Case VCDGUIDs.VCDInterface_AbsoluteValue
                ShowAbsoluteValueControl(itf)
            Case VCDGUIDs.VCDInterface_MapStrings
                ShowComboBoxControl(itf)
            Case VCDGUIDs.VCDInterface_Range
                ShowRangeControl(itf)
            Case VCDGUIDs.VCDInterface_Switch
                ShowSwitchControl(itf)
            Case VCDGUIDs.VCDInterface_Button
                ShowButtonControl(itf)
        End Select
    End If
End SubTreeViewに表示されたプロパティを使って制御する方法について説明します。
    上記で作成したインターフェースのノードのタグを使って、それぞれのインターフェースに対応したフォームを表示するようにします。
    TreeViewに表示されたインターフェースノードをクリックすると、フォームに最適なコントロールが現れ、プロパティの設定を調整できます。正確なインターフェースを取得する為にFindInterfaceメソッドを使用し、FindInterfaceはインターフェースパス(もしくはGUID)をパラメータを特定しています。
private void ShowAbsoluteValueControl(TIS.Imaging.VCDPropertyInterface itf)
{
    var newCtrl = new AbsValSlider((TIS.Imaging.VCDAbsoluteValueProperty)itf);
    CtrlFrame.Controls.Add(newCtrl);
    newCtrl.SetBounds(20, 20, 500, 27);
    CtrlFrame.Text = "Absolute Value";
    _currentControls.Add(newCtrl);
}Private Sub ShowAbsoluteValueControl(ByVal itf As TIS.Imaging.VCDPropertyInterface)
    AbsValCtrl = New AbsValSlider()
    CtrlFrame.Controls.Add(AbsValCtrl)
    AbsValCtrl.SetBounds(20, 20, 500, 27)
    AbsValCtrl.AssignItf(itf)
    CtrlFrame.Text = itf.Parent.Parent.Name + ": " + itf.Parent.Name ' Property item name
End Subプロパティ値の設定変更は上記のスライダーやチェックボックスやコンボボックスを実装したユーザーコントロールを使うことで調整することができます。
下記のAPIリファレンスマニュアルにもその他関数などの説明があります。
プログラマーズガイド:VCDプロパティをリストする
    IC Imaging Control3.5(C#/VB.NET) APIリファレンスマニュアル


