OMRON SENTECカメラをPythonとOpenCVで制御する方法(4)

前回記事の続きです。
https://qiita.com/kotai2003/items/13001140c96809ea79c2


### 詳細な解説: カメラ設定編集関数

以下では、カメラ設定を編集するための関数について詳しく解説します。これらの関数は、カメラの各種設定（列挙型設定および数値型設定）をユーザーが対話的に変更できるようにするためのものです。

#### `edit_enumeration` 関数

この関数は、列挙型ノードの値を表示し、ユーザーが変更できるようにします。

```python
def edit_enumeration(nodemap, enum_name):
    """
    Display and allow user to modify the enumeration value.

    :param nodemap: node map.
    :param enum_name: name of the enumeration node.
    """
    node = nodemap.get_node(enum_name)
    if not node.is_writable:
        return

    # Cast to PyIEnumeration from PyNode
    enum_node = st.PyIEnumeration(node)

    while True:
        print(enum_name)
        enum_entries = enum_node.entries
        for index in range(len(enum_entries)):
            enum_entry = enum_entries[index]
            if enum_entry.is_available:
                print("{0} : {1} {2}".format(index,
                      st.PyIEnumEntry(enum_entry).symbolic_value,
                      "(Current)" if enum_node.value == enum_entry.value else ""))
        selection = int(input("Select : "))
        if selection < len(enum_entries):
            enum_entry = enum_entries[selection]
            enum_node.set_int_value(enum_entry.value)
            break
```

- `nodemap`: ノードマップオブジェクト。カメラの設定ノードを含む。
- `enum_name`: 列挙型ノードの名前。
- `node.is_writable`: ノードが書き込み可能かをチェック。書き込み不可能な場合は関数を終了。
- `st.PyIEnumeration(node)`: ノードを列挙型ノードにキャスト。
- `enum_node.entries`: 列挙型のエントリ一覧を取得。
- `enum_node.value`: 現在の値を取得。
- `enum_node.set_int_value`: 選択されたエントリの値を設定。

#### `edit_setting` 関数

この関数は、数値型の設定値を編集するためのものです。

```python
def edit_setting(nodemap, node_name):
    """
    Edit setting which has numeric type.

    :param nodemap:  Node map.
    :param node_name: Node name.
    """
    node = nodemap.get_node(node_name)
    if not node.is_writable:
        return
    if node.principal_interface_type == st.EGCInterfaceType.IFloat:
        node_value = st.PyIFloat(node)
    elif node.principal_interface_type == st.EGCInterfaceType.IInteger:
        node_value = st.PyIInteger(node)
    while True:
        print(node_name)
        print(" Min={0} Max={1} Current={2}{3}".format(
              node_value.min, node_value.max, node_value.value,
              " Inc={0}".format(node_value.inc) if node_value.inc_mode == st.EGCIncMode.FixedIncrement else ""))
        new_value = input("New value : ")
        print()
        if node.principal_interface_type == st.EGCInterfaceType.IFloat:
            new_numeric_value = float(new_value)
        else:
            new_numeric_value = int(new_value)
        if node_value.min <= new_numeric_value <= node_value.max:
            node_value.value = new_numeric_value
            return
```

- `nodemap`: ノードマップオブジェクト。
- `node_name`: 数値型ノードの名前。
- `node.principal_interface_type`: ノードのインターフェースタイプをチェック。
  - `st.EGCInterfaceType.IFloat`: 浮動小数点型。
  - `st.EGCInterfaceType.IInteger`: 整数型。
- `node_value.min` と `node_value.max`: 設定可能な最小値と最大値。
- `node_value.value`: 現在の値。
- `node_value.inc`: インクリメント値（固定増分の場合）。

#### `edit_enum_setting` 関数

この関数は、列挙型ノードと数値型ノードの両方を編集するためのものです。

```python
def edit_enum_setting(nodemap, enum_name, numeric_name):
    """
    Display the contents of the current enumeration node and edit settings.

    :param nodemap: Node map.
    :param enum_name: Enumeration name.
    :param numeric_name: Numeric name.
    """
    node = nodemap.get_node(enum_name)
    if not node.is_writable:
        return

    enum_node = st.PyIEnumeration(node)
    enum_entries = enum_node.entries
    for index in range(len(enum_entries)):
        enum_entry = enum_entries[index]
        if enum_entry.is_available:
            enum_node.value = enum_entry.value
            print("{0} = {1}".format(enum_name, st.PyIEnumEntry(enum_entry).symbolic_value))
            edit_setting(nodemap, numeric_name)
```

- `nodemap`: ノードマップオブジェクト。
- `enum_name`: 列挙型ノードの名前。
- `numeric_name`: 数値型ノードの名前。
- `enum_node.entries`: 列挙型のエントリ一覧。
- `enum_node.value`: 現在の値を設定。
- `st.PyIEnumEntry(enum_entry).symbolic_value`: 列挙型エントリのシンボリック値。

#### 自動設定関数

これらの関数は、特定の自動設定（露出、自動ゲイン、自動ホワイトバランス）を構成するためのものです。

##### `exposure_auto` 関数

```python
def exposure_auto(nodemap):
    """Configure exposure using the given nodemap."""
    edit_enumeration(nodemap, EXPOSURE_MODE)
    edit_enumeration(nodemap, EXPOSURE_AUTO)
    edit_setting(nodemap, AUTO_LIGHT_TARGET)
    if nodemap.get_node(EXPOSURE_TIME):
        edit_setting(nodemap, EXPOSURE_TIME)
    else:
        edit_setting(nodemap, EXPOSURE_TIME_RAW)
```

- `EXPOSURE_MODE`, `EXPOSURE_AUTO`, `AUTO_LIGHT_TARGET`, `EXPOSURE_TIME`, `EXPOSURE_TIME_RAW`: 露出に関連する設定ノード。

##### `gain_auto` 関数

```python
def gain_auto(nodemap):
    """Configure gain using the given nodemap."""
    edit_enumeration(nodemap, GAIN_AUTO)
    edit_setting(nodemap, AUTO_LIGHT_TARGET)
    if nodemap.get_node(GAIN):
        edit_setting(nodemap, GAIN)
    else:
        edit_setting(nodemap, GAIN_RAW)
```

- `GAIN_AUTO`, `AUTO_LIGHT_TARGET`, `GAIN`, `GAIN_RAW`: ゲインに関連する設定ノード。

##### `balance_white_auto` 関数

```python
def balance_white_auto(nodemap):
    """Configure balance ratio/white using the given nodemap."""
    edit_enumeration(nodemap, BALANCE_WHITE_AUTO)
    edit_enum_setting(nodemap, BALANCE_RATIO_SELECTOR, BALANCE_RATIO)
```

- `BALANCE_WHITE_AUTO`, `BALANCE_RATIO_SELECTOR`, `BALANCE_RATIO`: ホワイトバランスに関連する設定ノード。

#### `do_auto_functions` 関数

この関数は、自動設定を構成するために別のスレッドで実行されます。

```python
def do_auto_functions(nodemap):
    """Function running in a separate thread for auto function configuration."""
    feature_list = [EXPOSURE_AUTO, GAIN_AUTO, BALANCE_WHITE_AUTO]
    is_writable_list = [False, False, False]
    for index, feature in enumerate(feature_list):
        with nodemap.get_node(feature) as node:
            is_writable_list[index]=True if node.is_writable else False

    while True:
        print()
        print("Auto Functions")
        for index, feature in enumerate(feature_list):
            if is_writable_list[index]:
                print("{0} : {1}".format(index, feature))
        print("Else : Exit")
        selection = int(input("Select : "))
        if selection == 0 and is_writable_list[selection] == True:
            exposure_auto(nodemap)
        elif selection == 1 and is_writable_list[selection] == True:
            gain_auto(nodemap)
        elif selection == 2 and is_writable_list[selection] == True:
            balance_white_auto(nodemap)
        else:
            print("Focus on the OpenCV window and press any key to terminate.")
            break
```

- `feature_list`: 自動設定機能のリスト。
- `is_writable_list`: 各機能が書き込み可能かどうかを示すリスト。
- 自動設定の選択肢を表示し、ユーザーの入力に基づいて設定を編集します。

これらの関数は連携してカメラの設定を対話的に変更できるようにし、特定の条件下での動作を最適化します。

参考資料
https://qiita.com/kotai2003/items/5c14a3ba58d5f6ccd127