OpenCVの使い方29 ~ ヒストグラム平坦化
今回はOpenCVを用いて輝度ヒストグラムの平坦化による画像明るさ補正について紹介する。
1. 画像読み込みと輝度ヒストグラム
霧により全体的に白みがかった画像の明るさを補正してみる。
Google Colabでのサンプル画像読み込み
import cv2 import numpy as np from matplotlib import pyplot as plt from google.colab import files uploaded_file = files.upload() uploaded_file_name = next(iter(uploaded_file)) orig = cv2.imread(uploaded_file_name)
読み込んだ画像は変数gray
に格納する。
gray = cv2.cvtColor(orig, cv2.COLOR_BGR2GRAY) plt.imshow(gray,cmap='gray',vmin=0,vmax=255)
画像の輝度ヒストグラムを調べるためNumpyのnp.histogram(array, bins, range)
を利用する。画像に適用するためgray.flatten()
として1次元配列に変換する。binsは256, 範囲は[0,256]
とする。またhist.cumsum()
として累積度数を取得して、hist.max()/cdf.max()
で正規化する。
hist,bins = np.histogram(gray.flatten(),256,[0,256]) cdf = hist.cumsum() cdf_normalized = cdf * hist.max()/ cdf.max() plt.plot(cdf_normalized, color = 'b') plt.hist(gray.flatten(),256,[0,256], color = 'r') plt.xlim([0,256]) plt.legend(('cdf','histogram'), loc = 'upper left') plt.show()
輝度値が150~225に分布していて比較的白みがかっていることが輝度ヒストグラムからもわかる。
2. ヒストグラム平坦化処理
150~225に集中している輝度値を0~255に分散させることでヒストグラムを平坦化する。
1つづつ計算する場合は累積輝度分布cdf
が0のものをマスク(計算させない)して、マスクした累積輝度分布の最大値と最小値を用いて255で正規化する。
最後にマスクした部分を0で埋める。(以下参照)
累積輝度分布cdf
を0をマスクするにはnp.ma.masked_equal(cdf,0)
とし、マスクした値を0で埋めるにはnp.ma.filled(cdf_m,0)
とする。
平坦化した輝度ヒストグラムを画像に適用するにはcdf[gray]
とし、gray2
に格納する。
cdf_m = np.ma.masked_equal(cdf,0) cdf_m = (cdf_m - cdf_m.min())*255/(cdf_m.max()-cdf_m.min()) cdf = np.ma.filled(cdf_m,0).astype('uint8') gray2=cdf[gray]
似たような処理をOpenCVのcv2.equalize()
で処理することができる。
equ = cv2.equalizeHist(gray)
画像の元の輝度ヒストグラム、累積輝度分布を正規化して平坦化したヒストグラム(Flatten)、OpenCVのcv2.equalize()
で平坦化したヒストグラム(equalizeHist)を比較すると、150~225に集中していた元の輝度ヒストグラムに対して平坦化した輝度ヒストグラムは0~255に広がっていることが確認できる。
3. ヒストグラム平坦化画像比較
最後に元画像、累積輝度分布のヒストグラム平坦化画像、cv2.equalize()
を用いたヒストグラム平坦化画像、imshow()
の輝度範囲をauto(vmin
,vmax
を指定しない)にした場合の表示を比較する。
元画像よりも白みがかって見えにくかった木や枝部分が見やすくなっている。imshow
の輝度範囲を自動とした場合も木や枝がそこそこ見やすいが、ヒストグラム平坦化画像の方がよりはっきりしている。ただし、ヒストグラム平坦化は暗い部分が増えて、輝度が低いエリアは逆に見えにくくなっている。
4. まとめ
OpenCVを用いて輝度ヒストグラムの平坦化による画像明るさ補正について紹介し、白みがかった霧画像の明るさ補正の効果について示した。