皆さん、CZPチャートというものをご存じでしょうか。CZP(Circular Zone Plate)とは、カメラの周波数特性や解像感の確認などをするためのチャートです。中心から同心円状に異なる周波数の円が描かれており、外側に行くにつれて周波数が高くなります。下の図がCZP画像になります。
今回はCZP画像(汎用Raw)をPythonで自作していきたいと思います。イメージセンサやカメラを扱う上でRaw画像の処理は必要になります。しかし、世の中にRaw画像(特に汎用Raw)の扱い方に関する情報がかなり少ないので、この記事を書いてみようと思いました。
本記事ではNumpy配列を用いてRaw(ただのバイナリの並び)の画素値をいじっていきます。
まずは空のNumpy配列を作成し、この配列をRawの型とします。ここで作っているRawは画像の高さheight、横幅width、符号なし16bitの画像になります。次に、空配列の中にCZPの式を書き込んでいきます。forの2重ループで画像左上の画素を原点として、順次画素値を代入します。
#***********************************
#画像設定
#***********************************
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) #空のNumpy配列
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)
続いて、このままでは全部ホワイト画素になるので、RGBのRaw画像にする場合はRGB比を適用します。同じようにforループで全画素にRGB比を適用しますが、ベイヤー配列のため1ベイヤーのRGGB(2×2画素)を1つの塊として処理をします。そのため、x,yの範囲を画像の高さ、幅の半分にしています。また、ダークのオフセットも付加します。
(*ちなみに、私のオリジナルの方法なので画像処理の慣習などは無視しているかもしれません。)
for x in range(half_width):
for y in range(half_height):
#RGB比適用
img_czp[2*y][2*x] = img_czp[2*y][2*x]*RGB_R
img_czp[2*y+1][2*x+1] = img_czp[2*y+1][2*x+1]*RGB_B
#ダークオフセット付加
img_czp[2*y][2*x] = img_czp[2*y][2*x]+dark
img_czp[2*y+1][2*x] = img_czp[2*y+1][2*x]+dark
img_czp[2*y][2*x+1] = img_czp[2*y][2*x+1]+dark
img_czp[2*y+1][2*x+1] = img_czp[2*y+1][2*x+1]+dark
最後に画像の表示と保存です。『cmap=”gray”』を入力することで、Raw画像はグレースケールで表示されます。
#***********************************
#raw画像を保存,表示
#***********************************
plt.imshow(img_czp, cmap="gray") #画像の表示
plt.show()
img_czp.tofile("CZP_1000x600.raw") #画像の保存
すべてまとめると以下のようなコードになります。
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比適用
img_czp[2*y][2*x] = img_czp[2*y][2*x]*RGB_R
img_czp[2*y+1][2*x+1] = img_czp[2*y+1][2*x+1]*RGB_B
#ダークオフセット付加
img_czp[2*y][2*x] = img_czp[2*y][2*x]+dark
img_czp[2*y+1][2*x] = img_czp[2*y+1][2*x]+dark
img_czp[2*y][2*x+1] = img_czp[2*y][2*x+1]+dark
img_czp[2*y+1][2*x+1] = 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画像の作り方の紹介でした。イメージセンサに関わる人は必ずRaw画像を使います。(汎用)Raw画像の処理方法について、ネット上にあまりにも情報が少ないので記事にしてみました。この記事をきっかけにRaw画像の扱い方について知るきっかけになっていただけたら嬉しいです。Pythonは非常に勉強しやすい言語だと思いますので、苦手意識を持たず勉強してみてください。
次回以降はデモザイクなどのコードを紹介できればと思います。
コメント