OpenCVのequalizeHist関数を使った画像のヒストグラム均一化
概要
この記事ではequalizeHist関数を使った画像ヒストグラム均一化を紹介します。equalizeHist関数はOpenCVライブラリの一部で、画像のヒストグラム均一化に使用される関数です。ヒストグラム均一化は、画像のコントラストを改善するための手法で、特に暗い画像や明るい画像のコントラストを改善するのに有効で、医療画像処理、衛星画像処理、写真の自動補正など、さまざまなアプリケーションで使用されています。
出力結果
プログラム全体
#解説1
# 必要なライブラリをインポート
import cv2
import numpy as np
from matplotlib import pyplot as plt
from PIL import Image
import requests
from io import BytesIO
#解説2
# Webからサンプル画像をロード
url = 'https://pds.exblog.jp/pds/1/201808/04/07/b0215507_00320968.jpg'
response = requests.get(url)
img = Image.open(BytesIO(response.content)) # 画像をPILのImageオブジェクトとして開く
img = np.array(img) # ImageオブジェクトをNumPy配列に変換
#解説3
# 画像をグレースケールに変換
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# ヒストグラム均一化を適用
equ = cv2.equalizeHist(gray)
# ヒストグラムを計算
hist = cv2.calcHist([gray],[0],None,[256],[0,256])
#解説4
# 元の画像と均一化された画像を表示
plt.figure(figsize=(15, 5)) # 描画領域を作成し、そのサイズを指定
plt.subplot(131), plt.imshow(gray, cmap='gray'), plt.title('元の画像', fontname = 'MS Gothic') # 元の画像を表示
plt.subplot(132), plt.imshow(equ, cmap='gray'), plt.title('均一化された画像', fontname = 'MS Gothic') # 均一化された画像を表示
# ヒストグラムを計算し表示
plt.subplot(133)
plt.hist(gray.ravel(),256,[0,256]) # 元の画像のヒストグラム
plt.title('ヒストグラム', fontname = 'MS Gothic') # タイトルを設定
plt.show() # 描画領域を表示
解説
解説1:ライブラリのインポート
# 必要なライブラリをインポート
import cv2
import numpy as np
from matplotlib import pyplot as plt
from PIL import Image
import requests
from io import BytesIO
ここでは、コードで必要となるライブラリをインポートしています。これらのライブラリは、画像の読み込み、処理、表示などに必要です。使用しているライブラリは下記の通りです。
cv2 |
OpenCVライブラリ。画像処理やコンピュータビジョンのタスクに広く使用されます。 |
---|---|
numpy |
数値計算ライブラリ。画像はピクセルの配列として扱われるため、NumPyは画像処理に必須です。 |
matplotlib.pyplot |
データの視覚化ライブラリ。画像を表示するために使用します。 |
PIL.Image |
Python Imaging Library。画像の読み込みや操作に使用します。 |
requests |
HTTPリクエストを送信するライブラリ。Webから画像をダウンロードするために使用します。 |
io.BytesIO |
バイトストリームを扱うためのライブラリ。画像データをメモリ上で扱うために使用します。 |
補足:numpy
とは?
NumPy(Numerical Python の略)は、Python で数値計算を効率的に行うためのライブラリです。特に多次元配列を操作するための強力な機能と、さまざまな数値計算用の関数が提供されています。画像はピクセルの配列として表現されるため、NumPyの配列として扱うことで、画像データの統計量の計算、フィルタリング、変換など画像処理を効率的に行うことができます。 簡単にまとめると Python での数値計算を効率よく、高速に行うことができるライブラリです。
解説2:画像のロード
# Webからサンプル画像をロード
url = 'https://raw.githubusercontent.com/mdavydov/ComputerVisionCourse/master/images/view.jpg'
response = requests.get(url)
img = Image.open(BytesIO(response.content)) # 画像をPILのImageオブジェクトとして開く
img = np.array(img) # ImageオブジェクトをNumPy配列に変換
ここでは、Webからサンプル画像をダウンロードし、それをNumPy配列として読み込んでいます。requests.get(url)
で画像データを取得し、Image.open(BytesIO(response.content))
で画像データをPILのImageオブジェクトとして開きます。最後に、np.array(img)
でImageオブジェクトをNumPy配列に変換します。これにより、画像をピクセルレベルで操作できるようになります。
解説3:画像の処理
# 画像をグレースケールに変換
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# ヒストグラム均一化を適用
equ = cv2.equalizeHist(gray)
# ヒストグラムを計算
hist = cv2.calcHist([gray],[0],None,[256],[0,256])
ここでは、画像をグレースケールに変換し、ヒストグラム均一化を適用しています。cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
で画像をグレースケールに変換します。これは、ヒストグラム均一化を適用する前の必要なステップです。次に、cv2.equalizeHist(gray)
でヒストグラム均一化を適用します。これにより、画像のコントラストが改善されます。
hist = cv2.calcHist([gray],[0],None,[256],[0,256])
なお、上記のコードではOpenCVのcalcHist
関数を使用して、グレースケール画像(gray)のヒストグラムを計算しています。それぞれの引数は下記の通りです。
第1引数 [gray] |
ヒストグラム表示するための画像を指定します。ここではグレースケールに変換された画像gray 、のヒストグラムを計算しています。 |
---|---|
第2引数 [0] |
ヒストグラムを計算するチャンネルを指定します。グレースケール画像は一つのチャンネルしか持っていませんので、0を指定します。カラー画像の場合、0はB(青)、1はG(緑)、2はR(赤)をそれぞれ指定します。 |
第3引数 None |
この位置にはマスクを指定します。マスクは画像の特定の領域のみを考慮に入れてヒストグラムを計算したい場合に使用します。ここでは全ての領域を対象としていますので、None を指定しています。画像の中の特定の領域だけヒストグラムの計算したい場合はマスク画像を指定します。 |
第4引数:[256] |
ここではヒストグラムのビンの数を指定します。ビンとはデータ分類するための区間を指しています。ここでは256を指定しているので、0(黒色)から255(白色)までの256段階の明るさを考慮したヒストグラムが計算されます。256のビンを用いると、各ビンは特定の輝度値(たとえば、ビン1は輝度が0のピクセル、ビン2は輝度が1のピクセル、といった具体的な一つの輝度値)を表すことになります。仮にビン数を半分の128に設定すると、各ビンは輝度の範囲を2つずつカバーすることになります(たとえば、ビン1は輝度が0または1のピクセル、ビン2は輝度が2または3のピクセル、というように)。つまり、ビンの数はデータをどの程度細かく分類するかを決定します。ビンの数が多すぎるとデータのノイズが強調され、少なすぎるとデータの構造が見えにくくなる可能性があります。ビンの数や範囲は、データの性質と解析の目的により適切に選択する必要があります。 |
第5引数:[0,256] |
ここではヒストグラムを計算する際のピクセル値の範囲を指定します。ここでは0から255までを指定しています。 |
解説4:画像の表示
# 元の画像と均一化された画像を表示
plt.figure(figsize=(15, 5)) # 描画領域を作成し、そのサイズを指定
plt.subplot(131), plt.imshow(gray, cmap='gray'), plt.title('元の画像') # 元の画像を表示
plt.subplot(132), plt.imshow(equ, cmap='gray'), plt.title('均一化された画像') # 均一化された画像を表示
# ヒストグラムを計算し表示
plt.subplot(133)
plt.hist(gray.ravel(),256,[0,256]) # 元の画像のヒストグラム
plt.title('ヒストグラム') # タイトルを設定
plt.show() # 描画領域を表示
ここでは、元の画像とヒストグラム均一化を適用した画像を表示しています。plt.figure(figsize=(15, 5))
で描画領域を作成し、そのサイズを指定します。plt.subplot(131)
とplt.subplot(132)
とplt.subplot(133)
で3つのサブプロットを作成し、それぞれに元の画像と均一化された画像とヒストグラムを表示します。plt.imshow()
で画像を表示し、plt.title()
で各サブプロットにタイトルを付けます。最後に、plt.show()
で描画領域を表示します。これにより、元の画像とヒストグラム均一化を適用した結果とヒストグラムを比較することができます。
エラー:matplotlibの文字化け
matplotlibのデフォルトのフォントでは日本語に対応していません。そのため、フォントを指定していないと下記のようにタイトル等が□□□□に文字化けしてしまいます。
文字化けしてしまうコード
# 元の画像と均一化された画像を表示
plt.figure(figsize=(15, 5)) # 描画領域を作成し、そのサイズを指定
plt.subplot(131), plt.imshow(gray, cmap='gray'), plt.title('元の画像') # 元の画像を表示
plt.subplot(132), plt.imshow(equ, cmap='gray'), plt.title('均一化された画像') # 均一化された画像を表示
# ヒストグラムを計算し表示
plt.subplot(133)
plt.hist(gray.ravel(),256,[0,256]) # 元の画像のヒストグラム
plt.title('ヒストグラム') # タイトルを設定
plt.show() # 描画領域を表示
文字化けを修正
# 元の画像と均一化された画像を表示
plt.figure(figsize=(15, 5)) # 描画領域を作成し、そのサイズを指定
plt.subplot(131), plt.imshow(gray, cmap='gray'), plt.title('元の画像', fontname = 'MS Gothic') # 元の画像を表示
plt.subplot(132), plt.imshow(equ, cmap='gray'), plt.title('均一化された画像', fontname = 'MS Gothic') # 均一化された画像を表示
# ヒストグラムを計算し表示
plt.subplot(133)
plt.hist(gray.ravel(),256,[0,256]) # 元の画像のヒストグラム
plt.title('ヒストグラム', fontname = 'MS Gothic') # タイトルを設定
plt.show() # 描画領域を表示
おまけ
OpenCVではリアルタイムでヒストグラム表示して輝度値の分布を把握したりすることができません。TheImagingSource社のビューワーソフト(IC Capture)ではカメラの映像を映しながらヒストグラムをリアルタイムで確認することができます。これにより、カメラの設定(露出、ゲイン、ホワイトバランスなど)を調整するなど、より適切なパラメータを設定することができます。
IC Captureの機能の詳細は下記に記載しています。
https://www.argocorp.com/software/capture/ICCapture/ICCapture.html