【Python】CZPチャートのRAW画像を自作してみよう

ImageSensor

皆さん、CZPチャートというものをご存じでしょうか。CZPチャート Raw画像は、カメラの周波数特性や解像感を確認するために利用される重要なチャートです。ここでは、CZP(Circular Zone Plate) とは何か、そしてどうやってPythonを使いながらRaw画像(特に汎用Raw)を生成するかを解説します。

CZPチャート Raw画像とは?

CZPチャートは、中心から同心円状に異なる周波数の円が描かれており、外側に行くほど周波数が高くなる特徴があります。たとえば下記の図がCZPチャート Raw画像です。このように、カメラの解像感を判定するために使用されるパターンがCircular Zone Plate (CZP) です。

CZP画像

Raw画像をPythonで作る意義

イメージセンサやカメラを扱う際、Raw画像の処理は欠かせません。とはいえ、特に汎用RawについてはWeb上の情報がかなり少ないのが現状です。そこで、Pythonで作成したCZPチャート Raw画像を扱う方法を紹介します。Numpy配列を活用すれば、16ビットのRaw画像を簡単に生成・操作できます。

実装ステップ

1. 必要なライブラリをインポート

import numpy as np
import matplotlib.pyplot as plt
import math

2. 画像パラメータの設定

# CZPチャート Raw画像の幅・高さ
width = 1000
height = 600

# RGB比 (R:G:B = 1:2:1 にしたいとき)
RGB_R = 0.5
RGB_B = 0.5

# ダークオフセット
dark = 200

# 半分の幅・高さ
half_width = int(width / 2)
half_height = int(height / 2)

ここでは、幅を1000ピクセル、高さを600ピクセル、16ビット深度で扱います。RGB比としてR=0.5, B=0.5を設定することで、相対的にGを強め、実際のベイヤー配列に近い形を目指しています。ダークオフセットは200を加算します。

3. 空のNumpy配列をRawとして作成

img_czp = np.empty((height, width), dtype=np.uint16)

この配列が、CZPチャート Raw画像のデータ領域になります。

4. CZPパターンの式を適用

for x in range(width):
    for y in range(height):
        img_czp[y][x] = (
            (2**12) * math.sin(
                math.pi / width * (x - half_width)**2 +
                math.pi / width * (y - half_height)**2
            )
            + (2**12)
        )

  • sin()の中で二乗を加算することで、同心円状のパターンが生成されます。
  • 振幅を2**12(4096)に設定し、さらにオフセットとして+ (2**12)を加えて画素値をシフトしています。

5. ベイヤー配列(RGGB)でのRGB比適用とダークオフセット

for x in range(half_width):
    for y in range(half_height):
        # Rチャネルの画素値を変化させる
        img_czp[2*y][2*x] = img_czp[2*y][2*x] * RGB_R
        
        # Bチャネルの画素値を変化させる
        img_czp[2*y+1][2*x+1] = img_czp[2*y+1][2*x+1] * RGB_B

        # ダークオフセットを加算(R/G/B問わず全画素)
        img_czp[2*y][2*x]     += dark
        img_czp[2*y+1][2*x]   += dark
        img_czp[2*y][2*x+1]   += dark
        img_czp[2*y+1][2*x+1] += dark
  • RGGBベイヤー配列に合わせて、2×2ブロックでR, G, Bを振り分けています。
  • (2y, 2x)がR、(2y+1, 2x+1)がB、残り2ピクセルがGという構造です。

6. 画像の表示と保存

plt.imshow(img_czp, cmap="gray")  # グレースケールで表示
plt.show()

# 生のバイナリデータとして保存 (.raw)
img_czp.tofile("CZP_1000x600.raw")
  • plt.imshow()cmap="gray"を指定すると、Raw画像をグレースケールで可視化できます。
  • tofile()メソッドでファイルに直接書き込むため、汎用Rawとして読み込みが可能です。

完成コード

以下が、CZPチャート Raw画像をPythonで自作するための完全なサンプルコードです。

import numpy as np
import matplotlib.pyplot as plt
import math

#***********************************
# 画像設定
#***********************************
width = 1000
height = 600
RGB_R = 0.5  # RGB比 R:G:B = 1:2:1
RGB_B = 0.5  # RGB比
dark = 200   # ダークオフセット

half_width = int(width / 2)
half_height = int(height / 2)

#***********************************
# raw画像を作る
#***********************************
img_czp = np.empty((height, width), dtype=np.uint16)

for x in range(width):  # CZPの式を用いてパターン生成
    for y in range(height):
        img_czp[y][x] = (
            (2**12) * math.sin(
                math.pi / width * (x - half_width)**2 +
                math.pi / width * (y - half_height)**2
            )
            + (2**12)
        )

for x in range(half_width):
    for y in range(half_height):
        # RGB比適用 (Rチャネル, Bチャネルのみ)
        img_czp[2*y][2*x]     *= RGB_R
        img_czp[2*y+1][2*x+1] *= RGB_B
        
        # ダークオフセット付加 (R/G/B問わず全ピクセル)
        img_czp[2*y][2*x]     += dark
        img_czp[2*y+1][2*x]   += dark
        img_czp[2*y][2*x+1]   += dark
        img_czp[2*y+1][2*x+1] += dark

#***********************************
# raw画像を保存・表示
#***********************************
plt.imshow(img_czp, cmap="gray")
plt.show()
img_czp.tofile("CZP_1000x600.raw")

まとめ

今回は、CZPチャート Raw画像をPythonで自作する方法をご紹介しました。

  • 同心円パターンは、sin⁡(π(x2+y2))\sin(\pi (x^2 + y^2))sin(π(x2+y2))系の式を使うと生成できます。
  • ベイヤー配列を意識して、R/G/B比やダークオフセットを調整することで、実際のセンサに近いRawデータの生成が可能です。
  • Raw画像が正しく扱えるようになると、イメージセンサの評価やカメラの性能確認に非常に役立ちます。

次回以降は、デモザイクなどのコードも紹介できればと考えています。カメラや画像処理の勉強をする方には、ぜひCZPチャート Raw画像の扱い方を知っていただきたいです。Pythonは学習コストも低めなので、気軽に取り組んでみてください。

関連リンク


注意事項: このコードを使用して発生した現象に対しては、一切の責任を負いかねます。

コメント

タイトルとURLをコピーしました