こんにちは、NetVision技術部の木村です。
今回は、PythonとFFmpegで作る画像処理シミュレーション用「RAW映像」生成術について紹介します。

1. はじめに:画像処理開発の「データ足りない」問題

イメージセンサーやISP(画像信号処理)の開発において、本物のRAWデータ(10/12/16bit)を用いたシミュレーションは不可欠です。しかし、いざRAWデータを準備しようとすると気軽に用意できなかったり作成が困難だったりします。

そこで今回は、「現像済みのカラー YUV4:2:2-8bit(UYVY) 映像を RAW10/12/16, Bayre配列が RGGB/GRGB の映像に変換できる」 という Python スクリプトを作成してみましたので、ご紹介します。

本 Python スクリプトで行えること
・現像済みのカラー YUV4:2:2-8bit(UYVY) 映像を RAW10/12/16, Bayre配列が RGGB/GRGB の映像に変換できる
 ※ 簡易逆デモザイクのため Raw10/12/16 とで映像の明るさは同じです

2. 実現したいデータ構造(パッキング規則)

標準的なUYVY(16bit/pixel)のコンテナに対し、以下のようにRAWデータを分割して詰め込みます。

[12bit RAWデータ例] 0000 AAAA BBBB BBBB ↑上位4bit ↑下位8bit UYVYメモリ配置: 偶数バイト (U/V位置) ← 0000 AAAA (上位4bit、上位は0パディング) 奇数バイト (Y位置) ← BBBB BBBB (下位8bit)
バイト位置UVYY上の役割格納する値
偶数バイトU / V成分RAW上位ビット(0パディング込み)
奇数バイトY成分RAW下位ビット

3. 変換ロジックのステップ


※色空間の変換は OpenCV により自動で行われます。

① 階調拡張(Bit Extension)

元動画の8bit値(0〜255)を、目標ビット数に合わせて左シフトします。

shift_map = {10: 2, 12: 4, 16: 8} bayer_raw_val = frame.astype(np.uint16) << shift_val
たとえばRAW12の場合、 8bit値 << 4 により0〜4095の範囲に拡張されます。

② 逆デモザイク処理

OpenCVが読み込んだRGB(BGR)データから、ベイヤー配列(例:RGGB)に従って1画素につき1色成分だけを抽出します。これにより、センサーから出た直後の「RAW状態」を再現します。

# RGGBパターンの例 bayer_raw[0::2, 0::2] = bayer_raw_val[0::2, 0::2, 2] # R bayer_raw[0::2, 1::2] = bayer_raw_val[0::2, 1::2, 1] # G bayer_raw[1::2, 0::2] = bayer_raw_val[1::2, 0::2, 1] # G bayer_raw[1::2, 1::2] = bayer_raw_val[1::2, 1::2, 0] # B
対応しているベイヤーパターンは --pattern オプションで指定します(デフォルト:RGGB)。

③ UYVYパッキング

12bitのRAW値を上位ビットと下位ビットに分割し、UYVYのメモリ配置に収めます。

mask_map = {10: 0x03, 12: 0x0F, 16: 0xFF} fake_uyvy = np.zeros((height, width * 2), dtype=np.uint8) fake_uyvy[:, 1::2] = (bayer_raw & 0xFF).astype(np.uint8) # 下位8bit → Y fake_uyvy[:, 0::2] = ((bayer_raw >> 8) & uv_mask).astype(np.uint8) # 上位ビット → U/V

4. 実行方法

環境構築

pip install opencv-python numpy
FFmpegは ffmpeg.exe をスクリプトと同じフォルダに配置するか、パスを通してください。