Pythonでいろいろやってみる

Pythonを使った画像処理や機械学習などの簡単なプログラムを載せています。

ヒストグラム平坦化・コントラスト制限付適応ヒストグラム平坦化によるカラー画像のコントラスト補正

明るい画像では明度の分布は明るい方に集中しており、暗い画像では明度は暗い方に集中しています。この明度の分布(ヒストグラム)を広げて明るさをまんべんなくする方法がヒストグラム平坦化で、画像のコントラスト調整ができます。
OpenCVではメソッドcv2.equalizeHist()を使うことで実現可能です。引数となるヒストグラムにはHSV色空間のV(Value)・明度を用い、明度のヒストグラムを平坦化します。
画像が全体的に明るい場合や全体的に暗い場合はヒストグラムが特定の範囲に偏っているため平坦化(ヒストグラムを広げる)が有効ですが、元の画像のヒストグラムが特定の範囲に偏っていないなど、ヒストグラム平坦化があまり有効ではない(広げられない)場合があります。 コントラスト制限付適応ヒストグラム平坦化(CLAHE)は領域ごとにヒストグラム平坦化をする方法で、画像全体のヒストグラム分布に影響されません。
OpenCVではメソッドcv2.createCLAHE()によりCLAHEオブジェクトを生成し、オブジェクト.apply(img)により、画像imgにCLAHEオブジェクトを適用します。
デフォルトのBGR色空間で各チャンネルそれぞれについてヒストグラム平坦化することも可能ですが、元画像と平坦化後画像のBGR比が変わり、色味が維持されないので、HSV色空間に変換し、明度Vにのみヒストグラム平坦化を行うことで、色味を維持したままコントラスト補正を行っています。

使った関数・メソッド
  • cv2.equalizeHist() : ヒストグラム平坦化
  • cv2.createCLAHE() : CLAHEオブジェクトの生成
関連記事

ルックアップテーブルによる画像コントラストの補正
特定の色を別の色に変換する(赤い服を緑の服に変える)

環境
  • windows10 home
  • Anaconda 3/ jupyter notebook 5.6.0
  • Python 3.7.0
  • OpenCV 4.0.0

ヒストグラム平坦化


準備

パブリックドメイン 世界の名画よりドラクロアの「民衆を導く自由の女神」をファイル名'Delacroix.jpg'でjupyter notebookファイル(***.ipynb)と同じディレクトリに保存しました。 f:id:T_A_T:20190629133802j:plain
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の分布が広がっていることが分かります。
f:id:T_A_T:20190629140442p:plain f:id:T_A_T:20190629140449p:plain

ヒストグラム平坦化後の画像が保存されます。全体的に明るくなり様子がよくわかります。 f:id:T_A_T:20190629140148j:plain
Delacroix_equalizehist.jpg


コントラスト制限付適応ヒストグラム平坦化


準備

フリー写真素材ぱくたそから夕日の写真をファイル名'sunset.jpg'でjupyter notebookファイル(***.ipynb)と同じディレクトリに保存しました。 f:id:T_A_T:20190629133558j:plain
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の分布が広がっていることが分かります。 f:id:T_A_T:20190629142404p:plain
f:id:T_A_T:20190629142415p:plain
暗い部分が明るくなり、様子が分かるようになります。
f:id:T_A_T:20190629142153j:plain

続いて、コントラスト制限付適応ヒストグラム平坦化を試します。

コード
%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の方がよりコントラスト補正がうまくいっていることが分かります。 f:id:T_A_T:20190629142519p:plain
f:id:T_A_T:20190629142539p:plain
f:id:T_A_T:20190629142550j:plain

以下のサイトを参考にさせていただきました

OpenCV-Python Tutorials 1 >> ヒストグラム その2: ヒストグラム平坦化

ブログランキングに参加しています

にほんブログ村 IT技術ブログへ
にほんブログ村