はじめに
前回の投稿でOpenCVのcv2.equalizeHist関数を使った、ヒストグラム平坦化について解説しました。
今回は、応用編として適用的ヒストグラム平坦化を紹介します。
適用的ヒストグラム平坦化(CLAHE)
適用的ヒストグラム平坦化:CLAHE(Contrast Limited Adaptive Histogram Equalization)は、通常のヒストグラム平坦化の改良版です。CLAHEは、画像全体に対して一律にヒストグラム平坦化を行う代わりに、画像を小さなタイル(ブロック)に分割し、各タイル内で局所的なヒストグラム平坦化を行います。この局所的な処理により、画像全体におけるコントラスト改善を均一に行う事が可能となります。
CLAHEの特徴を下に示します。
- 全体処理 vs 局所処理
通常のヒストグラム平坦化は画像全体に対して一律な処理を行いますが、CLAHEは画像を小領域に分割して、各領域ごとに局所的なヒストグラム平坦化を行います。これにより、CLAHEは画像全体に対して、白飛びや黒つぶれが生じにくくなり、画像の劣化を抑えます。 - コントラスト制限
CLAHEには”Contrast Limit”と呼ばれるパラメータがあります。このパラメータにより、各局所領域において過度なコントラストの調整を制限します。これにより、ノイズの増加や画像の劣化を防ぎます。 - ブロックサイズ
CLAHEでは、画像を小さなタイル(ブロック)に分割します。ブロックのサイズはCLAHEのパラメータとして設定されます。ブロックサイズの選択により、局所的な処理の効果や処理速度が変わることがあります。
CLAHEは特に医療画像や自然画像など、局所的な特徴が重要な場合に有用です。例えば、X線画像やMRI画像では、CLAHEを適用することで骨や臓器の特徴をより鮮明に表示することができます。しかし、一部の画像領域に過剰なコントラスト調整が生じる可能性があるため、パラメータの調整での回避が必要となる場合があります。
OpenCVにおけるCLAHEの適用
OpenCVでは、CLAHEを使用するには、cv2.createCLAHE
関数を用い、CLAHEクラスのオブジェクトを作成後、CLAHEを適用するapply
メソッドを実行します。
cv2.createCLAHE関数
CLAHEクラスのオブジェクトを作成します。
引数
名称 | 説明 |
clipLimit(オプション) | コントラスト制限のしきい値(デフォルト:40.0) |
tileGridSize(オプション) | ヒストグラム平坦化のためのグリッドのサイズ。横方向と縦方向のタイルの数をタプルで指定し、入力画像は同じサイズの長方形のタイルに分割されます。(デフォルト:(8, 8)) |
cv2.CLAHE.applyメソッド
適用的ヒストグラム平坦化の演算を実行します。
引数
名称 | 説明 |
入力画像(必須) | 入力画像データ。対応するデータ型はシングル チャンネルのuint8 または、シングル チャンネルのuint16 |
戻り値
戻り値は入力画像と同じサイズのCLAHEが適用されたグレースケール画像データです。
以下は、clipLimit=4、tileGridSize=(8, 8)の場合のapplyメソッドの出力結果です。
WikipediaでclipLimitの値は3〜4の間が良いと紹介されていたので、clipLimit=4としました。cv2.equalizeHist
関数と比較すると極端に明るい部分が少なく、細部の描写が分かり易い画像になっている事が確認できます。
ヒストグラムにも違いが見られます。cv2.equalizeHist
関数ではヒストグラムに多くの隙間が出来ますが、CLAHEではその様な特徴は見られません。
こちらの結果は、clipLimit=40、tileGridSize=(8, 8)の場合のapplyメソッドの出力結果です。
clipLimitをデフォルトの40にした場合、写真というより絵画の様な雰囲気になりました。
ヒストグラムを見ると、極端に明るい部分と極端に暗い部分の画素数が抑えられていることがわかります。
入力画像として、この画像を使用しました。
引用元
https://www.shopify.com/stock-photos/photos/narrow-cobbled-streets-in-black-and-white
import cv2 import numpy as np from matplotlib import pyplot as plt # 画像の読み込み image = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE) # ヒストグラムの作成(引数の'image'を[ ]で囲うことを忘れないで下さい) histogram = cv2.calcHist([image], [0], None, [256], [0, 256]) # ヒストグラムの可視化 plt.rcParams["figure.figsize"] = [12,7.5] # 表示領域のアスペクト比を設定 plt.subplots_adjust(left=0.01, right=0.95, bottom=0.10, top=0.95) # 余白を設定 plt.subplot(221) # 1行2列の1番目の領域にプロットを設定 plt.imshow(image, cmap='gray') # 画像をグレースケールで表示 plt.axis("off") # 軸目盛、軸ラベルを消す plt.subplot(222) # 1行2列の2番目の領域にプロットを設定 plt.plot(histogram) # ヒストグラムのグラフを表示 plt.xlabel('Brightness') # x軸ラベル(明度) plt.ylabel('Count') # y軸ラベル(画素の数) # CLAHEのパラメータ clip_limit = 4.0 tile_grid_size = (8, 8) # CLAHEオブジェクトを作成 clahe = cv2.createCLAHE(clipLimit=clip_limit, tileGridSize=tile_grid_size) # CLAHEを適用 result = clahe.apply(image) # CLAHE適応後画像のヒストグラムの作成 histogram = cv2.calcHist([result], [0], None, [256], [0, 256]) # ヒストグラムの可視化 plt.subplot(223) # 1行2列の1番目の領域にプロットを設定 plt.imshow(result, cmap='gray') # 画像をグレースケールで表示 plt.axis("off") # 軸目盛、軸ラベルを消す plt.subplot(224) # 1行2列の2番目の領域にプロットを設定 plt.plot(histogram) # ヒストグラムのグラフを表示 plt.xlabel('Brightness') # x軸ラベル(明度) plt.ylabel('Count') # y軸ラベル(画素の数) plt.show()
おわりに
OpenCVの適用的ヒストグラム平坦化(CLAHE)クラスによる適応的ヒストグラム平坦化を解説しました。
clipLimitの値の選定により、画像の雰囲気が異なり興味深い結果でした。
最後までご覧いただきありがとうございました。
■OpenCVの参考書としてどうぞ!■
参考リンク
OpenCV: cv::CLAHE Class Reference
Base class for Contrast Limited Adaptive Histogram Equalization.