OMRON SENTECカメラ Python Buildup (4) grab_opencv.py

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

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

### コード全体の説明

このコードは、カメラから取得した画像データをOpenCVを使って処理し、表示するサンプルです。具体的には、以下の手順を実行します：

1. StApiの初期化
2. カメラへの接続
3. 画像データの取得
4. 画像データをOpenCV形式に変換
5. Bayer画像形式をRGBに変換
6. OpenCVで画像をプレビュー

### コードの詳細分析

#### インポートと設定

```python
import cv2
import numpy as np
import stapipy as st

# Number of images to grab
number_of_images_to_grab = 100

# Image scale when displaying using OpenCV.
DISPLAY_RESIZE_FACTOR = 0.3
```

- `cv2`: OpenCVライブラリをインポートします。
- `numpy`: 画像データの処理に使用するため、NumPyライブラリをインポートします。
- `stapipy`: StApiライブラリをインポートします。

#### メイン部分

```python
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()

    st_datastream.start_acquisition(number_of_images_to_grab)
    st_device.acquisition_start()

    while st_datastream.is_grabbing:
        with st_datastream.retrieve_buffer() as st_buffer:
            if st_buffer.info.is_image_present:
                st_image = st_buffer.get_image()
                print("BlockID={0} Size={1} x {2} First Byte={3}".format(
                      st_buffer.info.frame_id,
                      st_image.width, st_image.height,
                      st_image.get_image_data()[0]))

                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):
                    continue

                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)
                cv2.imshow('image', nparr)
                cv2.waitKey(1)
            else:
                print("Image data does not exist.")

    st_device.acquisition_stop()
    st_datastream.stop_acquisition()

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

1. **初期化と接続**:
   - `st.initialize()`でStApiを初期化し、`st.create_system()`でシステムオブジェクトを作成、`st_system.create_first_device()`で最初に検出されたデバイスに接続します。

2. **データストリームの作成と画像取得の開始**:
   - `st_device.create_datastream()`でデータストリームオブジェクトを作成し、`st_datastream.start_acquisition(number_of_images_to_grab)`で画像取得を開始します。

3. **画像データの取得と処理**:
   - `st_datastream.retrieve_buffer()`でバッファを取得し、`st_buffer.get_image()`で画像データを取得します。
   - `pixel_format_info`を使用してピクセルフォーマット情報を確認し、Bayer画像の場合は`cv2.cvtColor()`を使用してRGB形式に変換します。

4. **画像の表示**:
   - `cv2.resize()`で画像をリサイズし、`cv2.imshow()`で画像を表示します。

5. **画像取得の停止**:
   - `st_device.acquisition_stop()`と`st_datastream.stop_acquisition()`で画像取得を停止します。

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

#### 理由

1. **画像処理の強力なツール**:
   - OpenCVは、画像処理のための豊富な関数を提供しており、Bayer画像のRGB変換やフィルタリング、エッジ検出など多岐にわたる処理を簡単に実行できます。

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

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

#### メリット

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

2. **効率的な処理**:
   - OpenCVは内部で最適化されており、効率的に画像処理を行うことができます。

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

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



## カメラが白黒で、mono 8bitの場合のシンプルコード



以下は、白黒カメラ用にシンプル化したコードです。画像データが8ビットのモノクロであることを前提としています。

```python
import cv2
import numpy as np
import stapipy as st

# 取得する画像の枚数
number_of_images_to_grab = 100

# OpenCVを使用して表示する際の画像スケール
DISPLAY_RESIZE_FACTOR = 0.3

try:
    # StApiを初期化
    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()

    # ホスト側の画像取得を開始
    st_datastream.start_acquisition(number_of_images_to_grab)

    # カメラ側の画像取得を開始
    st_device.acquisition_start()

    # データ取得とステータス確認のためのループ
    while st_datastream.is_grabbing:
        # 'with'を使用してローカル変数st_bufferを作成
        with st_datastream.retrieve_buffer() as st_buffer:
            # 取得したデータに画像データが含まれているか確認
            if st_buffer.info.is_image_present:
                # 画像オブジェクトを作成
                st_image = st_buffer.get_image()

                # 取得した画像データの情報を表示
                print("BlockID={0} Size={1} x {2} First Byte={3}".format(
                      st_buffer.info.frame_id,
                      st_image.width, st_image.height,
                      st_image.get_image_data()[0]))

                # 画像データを取得
                data = st_image.get_image_data()

                # データをNumPy配列に変換
                nparr = np.frombuffer(data, np.uint8)

                # 画像を表示用に処理
                nparr = nparr.reshape(st_image.height, st_image.width, 1)

                # 画像をリサイズして表示
                nparr = cv2.resize(nparr, None,
                                   fx=DISPLAY_RESIZE_FACTOR,
                                   fy=DISPLAY_RESIZE_FACTOR)
                cv2.imshow('image', nparr)
                cv2.waitKey(1)
            else:
                # 取得したデータに画像データが含まれていない場合
                print("Image data does not exist.")

    # カメラ側の画像取得を停止
    st_device.acquisition_stop()

    # ホスト側の画像取得を停止
    st_datastream.stop_acquisition()

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

このコードでは、カラー画像の変換や不要な処理を省略し、モノクロ画像の表示に焦点を当てています。`st_image.get_image_data()`で取得したデータをそのまま表示しています。

## 関連資料


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