前回記事の続きです。
CMyCallback
クラスの詳細解説
CMyCallback
クラスは、カメラから取得した画像データを処理し、スレッドセーフな方法で画像データを保持するために設計されています。このクラスは、データストリームからのコールバックを処理するためのコールバック関数を含んでいます。
クラスの構造
class CMyCallback:
"""
Class that contains a callback function.
"""
このクラスは、コールバック関数を含むクラスであることを示しています。
初期化 (__init__
)
def __init__(self):
self._image = None
self._lock = threading.Lock()
-
self._image
: 取得した画像データを保持するための変数です。初期値はNone
に設定されています。 -
self._lock
: スレッドセーフなアクセスを保証するためのロックオブジェクトです。これにより、マルチスレッド環境でのデータ競合を防ぎます。
プロパティ (image
)
@property
def image(self):
"""Property: return PyIStImage of the grabbed image."""
duplicate = None
self._lock.acquire()
if self._image is not None:
duplicate = self._image.copy()
self._lock.release()
return duplicate
-
@property
: このデコレータにより、image
メソッドをプロパティとしてアクセスできるようになります。 -
self._lock.acquire()
: ロックを取得し、他のスレッドがself._image
にアクセスするのを防ぎます。 -
self._image.copy()
: 画像データのコピーを作成し、オリジナルデータが他のスレッドによって変更されるのを防ぎます。 -
self._lock.release()
: ロックを解放し、他のスレッドがself._image
にアクセスできるようにします。 -
return duplicate
: コピーした画像データを返します。
コールバック関数 (datastream_callback
)
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.
"""
-
handle
: コールバックをトリガーするハンドル。 -
context
: コールバック登録時に渡されたユーザーデータ。
コールバック処理の流れ
- データストリームの取得
st_datastream = handle.module
handle.module
を使ってデータストリームオブジェクトを取得します。
- バッファの取得
if st_datastream:
with st_datastream.retrieve_buffer() as st_buffer:
データストリームからバッファを取得します。with
文を使うことで、バッファの自動解放を保証します。
- 画像データの確認と取得
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)
各ピクセルコンポーネントが8ビットを超える場合、スケーリングを行います。スケーリングしない場合はそのままのデータを使用します。
- 画像データの整形
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)
ベイヤー形式の画像データをRGB形式に変換します。
- 画像データのリサイズと保存
nparr = cv2.resize(nparr, None, fx=DISPLAY_RESIZE_FACTOR, fy=DISPLAY_RESIZE_FACTOR)
self._lock.acquire()
self._image = nparr
self._lock.release()
画像データをリサイズし、self._image
に保存します。この時、スレッドセーフを保証するためにロックを取得してから画像データを保存し、保存後にロックを解放します。
まとめ
CMyCallback
クラスは、カメラから取得した画像データを安全に処理し保存するための重要なクラスです。スレッドセーフな方法で画像データを保持するためにロック機構を使用し、データストリームからのコールバックを適切に処理します。このクラスの設計により、リアルタイムで画像を処理し表示することが可能になります。
参考資料