ヒストグラム平坦化・コントラスト制限付適応ヒストグラム平坦化によるカラー画像のコントラスト補正
明るい画像では明度の分布は明るい方に集中しており、暗い画像では明度は暗い方に集中しています。この明度の分布(ヒストグラム)を広げて明るさをまんべんなくする方法がヒストグラム平坦化で、画像のコントラスト調整ができます。
OpenCVではメソッドcv2.equalizeHist()を使うことで実現可能です。引数となるヒストグラムにはHSV色空間のV(Value)・明度を用い、明度のヒストグラムを平坦化します。
画像が全体的に明るい場合や全体的に暗い場合はヒストグラムが特定の範囲に偏っているため平坦化(ヒストグラムを広げる)が有効ですが、元の画像のヒストグラムが特定の範囲に偏っていないなど、ヒストグラム平坦化があまり有効ではない(広げられない)場合があります。
コントラスト制限付適応ヒストグラム平坦化(CLAHE)は領域ごとにヒストグラム平坦化をする方法で、画像全体のヒストグラム分布に影響されません。
OpenCVではメソッドcv2.createCLAHE()によりCLAHEオブジェクトを生成し、オブジェクト.apply(img)により、画像imgにCLAHEオブジェクトを適用します。
デフォルトのBGR色空間で各チャンネルそれぞれについてヒストグラム平坦化することも可能ですが、元画像と平坦化後画像のBGR比が変わり、色味が維持されないので、HSV色空間に変換し、明度Vにのみヒストグラム平坦化を行うことで、色味を維持したままコントラスト補正を行っています。
使った関数・メソッド
- cv2.equalizeHist() : ヒストグラム平坦化
- cv2.createCLAHE() : CLAHEオブジェクトの生成
関連記事
ルックアップテーブルによる画像コントラストの補正
特定の色を別の色に変換する(赤い服を緑の服に変える)
環境
ヒストグラム平坦化
準備
パブリックドメイン 世界の名画よりドラクロアの「民衆を導く自由の女神」をファイル名'Delacroix.jpg'でjupyter notebookファイル(***.ipynb)と同じディレクトリに保存しました。
Delacroix.jpg
コード
%matplotlib inline import cv2 import numpy as np import matplotlib.pyplot as plt # 画像の読み出し img = cv2.imread('Delacroix.jpg') # BGR->HSV変換 hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # V値のヒストグラム表示 hist = cv2.calcHist([hsv],[2],None,[256],[0,256]) plt.plot(hist,color = "b") plt.show() # V値のヒストグラム平坦化 hsv[:,:,2] = cv2.equalizeHist(hsv[:,:,2]) # 平坦化後のV値のヒストグラム表示 hist = cv2.calcHist([hsv],[2],None,[256],[0,256]) plt.plot(hist,color = "g") plt.show() # HSV->BGR変換 bgr = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR) # 画像の保存 cv2.imwrite('Delacroix_equalizehist.jpg',bgr)
実行結果
元の明度V値のヒストグラムと平坦化後のV値のヒストグラムが表示されます。平坦化により明るい方に明度Vの分布が広がっていることが分かります。
ヒストグラム平坦化後の画像が保存されます。全体的に明るくなり様子がよくわかります。
Delacroix_equalizehist.jpg
準備
フリー写真素材ぱくたそから夕日の写真をファイル名'sunset.jpg'でjupyter notebookファイル(***.ipynb)と同じディレクトリに保存しました。
sunset.jpg
まずはヒストグラム平坦化を試します。
コード
%matplotlib inline import cv2 import numpy as np import matplotlib.pyplot as plt # 画像の読み出し img = cv2.imread('sunset.jpg') # BGR->HSV変換 hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # V値のヒストグラム表示 hist = cv2.calcHist([hsv],[2],None,[256],[0,256]) plt.plot(hist,color = "b") plt.show() # V値のヒストグラム平坦化 hsv[:,:,2] = cv2.equalizeHist(hsv[:,:,2]) # 平坦化後のV値のヒストグラム表示 hist = cv2.calcHist([hsv],[2],None,[256],[0,256]) plt.plot(hist,color = "g") plt.show() # HSV->BGR変換 bgr = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR) # 画像の保存 cv2.imwrite('sunset_equalizehist.jpg',bgr)
実行結果
平坦化により明るい方に明度Vの分布が広がっていることが分かります。
暗い部分が明るくなり、様子が分かるようになります。
続いて、コントラスト制限付適応ヒストグラム平坦化を試します。
コード
%matplotlib inline import cv2 import numpy as np import matplotlib.pyplot as plt # 画像の読み出し img = cv2.imread('sunset.jpg') # BGR->HSV変換 hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # V値のヒストグラム表示 hist = cv2.calcHist([hsv],[2],None,[256],[0,256]) plt.plot(hist,color = "b") plt.show() # CLAHEパラメータの設定 clahe = cv2.createCLAHE(clipLimit=2.0,tileGridSize=(8,8)) # V値のヒストグラム平坦化 hsv[:,:,2] = clahe.apply(hsv[:,:,2]) # 平坦化後のV値のヒストグラム表示 hist = cv2.calcHist([hsv],[2],None,[256],[0,256]) plt.plot(hist,color = "g") plt.show() # HSV->BGR変換 bgr = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR) # 画像の保存 cv2.imwrite('sunset_clahe.jpg',bgr)
実行結果
明度V30程度の画素が最も多かったのが、平坦化により明度V130あたりが最も多い画素となりました。雲の形や岸壁のコントラストが大きくなり、ヒストグラム平坦化よりも、CLAHEの方がよりコントラスト補正がうまくいっていることが分かります。
以下のサイトを参考にさせていただきました
OpenCV-Python Tutorials 1 >> ヒストグラム その2: ヒストグラム平坦化