OMRON SENTECカメラ Python Buildup (5) grab_callback_opencv.py

こちらの資料を読んでください。

https://qiita.com/kotai2003/items/19d840553fc6d69ec17d

### コードの全体説明

このコードは、カメラから取得した画像データをOpenCVを使って表示するサンプルです。主な機能は以下の通りです：

1. StApiの初期化
2. カメラへの接続
3. コールバック関数を用いた画像データの取得
4. 取得した画像データをOpenCVで処理し表示

### クラス `CMyCallback` の定義とメソッド

```python
class CMyCallback:
    """
    Class that contains a callback function.
    """

    def __init__(self):
        self._image = None
        self._lock = threading.Lock()

    @property
    def image(self):
        duplicate = None
        self._lock.acquire()
        if self._image is not None:
            duplicate = self._image.copy()
        self._lock.release()
        return duplicate

    def datastream_callback(self, handle=None, context=None):
        """
        Callback to handle events from DataStream.

        :param handle: handle that trigger the callback.
        :param context: user data passed on during callback registration.
        """
        st_datastream = handle.module
        if st_datastream:
            with st_datastream.retrieve_buffer() as st_buffer:
                if st_buffer.info.is_image_present:
                    st_image = st_buffer.get_image()

                    pixel_format = st_image.pixel_format
                    pixel_format_info = st.get_pixel_format_info(pixel_format)

                    if not(pixel_format_info.is_mono or pixel_format_info.is_bayer):
                        return

                    data = st_image.get_image_data()

                    if pixel_format_info.each_component_total_bit_count > 8:
                        nparr = np.frombuffer(data, np.uint16)
                        division = pow(2, pixel_format_info.each_component_valid_bit_count - 8)
                        nparr = (nparr / division).astype('uint8')
                    else:
                        nparr = np.frombuffer(data, np.uint8)

                    nparr = nparr.reshape(st_image.height, st_image.width, 1)

                    if pixel_format_info.is_bayer:
                        bayer_type = pixel_format_info.get_pixel_color_filter()
                        if bayer_type == st.EStPixelColorFilter.BayerRG:
                            nparr = cv2.cvtColor(nparr, cv2.COLOR_BAYER_RG2RGB)
                        elif bayer_type == st.EStPixelColorFilter.BayerGR:
                            nparr = cv2.cvtColor(nparr, cv2.COLOR_BAYER_GR2RGB)
                        elif bayer_type == st.EStPixelColorFilter.BayerGB:
                            nparr = cv2.cvtColor(nparr, cv2.COLOR_BAYER_GB2RGB)
                        elif bayer_type == st.EStPixelColorFilter.BayerBG:
                            nparr = cv2.cvtColor(nparr, cv2.COLOR_BAYER_BG2RGB)

                    nparr = cv2.resize(nparr, None, fx=DISPLAY_RESIZE_FACTOR, fy=DISPLAY_RESIZE_FACTOR)
                    self._lock.acquire()
                    self._image = nparr
                    self._lock.release()
```

#### クラス `CMyCallback`

- このクラスは、画像データを取得して処理するためのコールバック関数を含みます。
- **属性とメソッド**:
  - `__init__`: インスタンス変数 `_image` とスレッドロック `_lock` を初期化します。
  - `image`: スレッドセーフに `_image` のコピーを返すプロパティ。
  - `datastream_callback`: 画像データを取得して処理するコールバック関数。

### メイン部分

```python
if __name__ == "__main__":
    my_callback = CMyCallback()
    cb_func = my_callback.datastream_callback
    try:
        st.initialize()
        st_system = st.create_system()
        st_device = st_system.create_first_device()
        print('Device=', st_device.info.display_name)
        st_datastream = st_device.create_datastream()

        callback = st_datastream.register_callback(cb_func)

        st_datastream.start_acquisition()
        st_device.acquisition_start()

        print("To terminate, focus on the OpenCV window and press any key.")
        while True:
            output_image = my_callback.image
            if output_image is not None:
                cv2.imshow('image', output_image)
            key_input = cv2.waitKey(1)
            if key_input != -1:
                break

        st_device.acquisition_stop()
        st_datastream.stop_acquisition()

    except Exception as exception:
        print(exception)
```

#### メイン処理

1. **コールバッククラスのインスタンス作成**:

   ```python
   my_callback = CMyCallback()
   cb_func = my_callback.datastream_callback
   ```

2. **StApiの初期化と接続**:

   ```python
   st.initialize()
   st_system = st.create_system()
   st_device = st_system.create_first_device()
   print('Device=', st_device.info.display_name)
   ```

3. **データストリームの作成とコールバック登録**:

   ```python
   st_datastream = st_device.create_datastream()
   callback = st_datastream.register_callback(cb_func)
   ```

4. **画像取得の開始と表示**:

   ```python
   st_datastream.start_acquisition()
   st_device.acquisition_start()
   
   print("To terminate, focus on the OpenCV window and press any key.")
   while True:
       output_image = my_callback.image
       if output_image is not None:
           cv2.imshow('image', output_image)
       key_input = cv2.waitKey(1)
       if key_input != -1:
           break
   ```

5. **画像取得の停止**:

   ```python
   st_device.acquisition_stop()
   st_datastream.stop_acquisition()
   ```

### OpenCVを利用した理由とメリット

#### 理由

1. **画像処理の強力なツール**:
   - OpenCVは画像処理のための豊富な関数を提供しており、画像の変換や表示を簡単に行うことができます。

2. **リアルタイム処理**:
   - 高速な画像処理が可能で、リアルタイムでの画像表示や解析に適しています。

3. **広範なサポート**:
   - OpenCVは多くのプラットフォームとプログラミング言語をサポートしており、他のシステムやライブラリと容易に統合できます。

#### メリット

1. **簡単な実装**:
   - OpenCVの関数を使用することで、複雑な画像処理を簡単に実装できます。

2. **効率的な処理**:
   - OpenCVはC++で実装されており、効率的に画像処理を行うことができます。

3. **豊富な機能**:
   - OpenCVには画像の読み込み、書き込み、表示、変換、フィルタリングなどの豊富な機能があり、開発者はこれらを利用して迅速にアプリケーションを開発できます。

このコードでは、OpenCVを活用することで、カメラから取得した画像データを効率的に処理し、リアルタイムで表示することができます。

## 関連資料

https://qiita.com/kotai2003/items/a20f4ee0ba978e54808e

https://qiita.com/kotai2003/items/c35196f62c8d8eb8a28a

https://qiita.com/kotai2003/items/23a0d0546b0e76a12fff

https://qiita.com/kotai2003/items/a1c9a12baac8311a8790

https://qiita.com/kotai2003/items/f273973df27004ff32a1

https://qiita.com/kotai2003/items/2ac6ae2a6400edcca4b0

https://qiita.com/kotai2003/items/68e9d70fb1270855b16f

https://qiita.com/kotai2003/items/5aa5bc90ddcf8b1f5362