つれづれなる備忘録

日々の発見をあるがままに綴る

OpenCVの使い方7 ~ 2値化処理2

 OpenCVの使用方法について、前回の画像の2値化処理の続きで大津の2値化について紹介したい。

1. 大津の2値化

 前回の画像の2値化処理で閾値を自動計算する方法として小区間にわけて閾値を計算する適用的2値化について紹介したが、画像全体閾値の自動計算として画像輝度値のヒストグラムから2つのクラスに分ける閾値を算出する大津の2値化が知られている。(詳細は2値化(大津の2値化) | 画像認識の技術ブログ | マクセルフロンティア株式会社など参照)

以下の画像(gray)を大津の2値化を用いて閾値を自動計算して2値処理する例を示す。

"元画像(グレースケール)"
元画像(グレースケール)

サンプル画像までのコードは下を展開。

サンプル画像読み込み

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 = cv2.cvtColor(orig, cv2.COLOR_BGR2GRAY)
plt.imshow(gray,cmap='gray')

2. 大津の2値化の適用

 大津の2値化を適用して閾値を設定するには、cv2.threshold()のthreshold=0として、method=cv2.THRESH_BINARY+cv2.THRESH_OTSUとする。なお2値化処理方法を別の方法にするにはmethod=cv2.THRESH_TRUNC+cv2.THRESH_OTSUなどすればよい。

ret3,ath3 = cv2.threshold(gray,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)

plt.figure(figsize=(10,20))
plt.subplot(1,2,1)
plt.imshow(thresh1,cmap='gray',,vmin = 0, vmax = 255)
plt.title('THRESH_BINARY')
plt.subplot(1,2,2)
plt.imshow(ath3,cmap='gray',,vmin = 0, vmax = 255)
plt.title('BINARY+THRESH_OTSU')

左の画像はthreshold=127とした場合、右は大津の2値化で閾値を自動計算した画像になる。自動計算された閾値ret3に格納されており、下の画像の場合は102になっている。 閾値を127に設定した場合よりも、大津の2値化で求めた閾値の方が白黒のバランスがよい感じがする。

"大津の2値化"
大津の2値化

2値化処理をBINARY_TRUNCにした場合の比較(左:threshold=127,右:大津の2値化)する。

ret4,ath4 = cv2.threshold(gray,0,255,cv2.THRESH_TRUNC+cv2.THRESH_OTSU)
plt.figure(figsize=(10,20))
plt.subplot(1,2,1)
plt.imshow(thresh3,cmap='gray',,vmin = 0, vmax = 255)
plt.title('THRESH_TRUNC')
plt.subplot(1,2,2)
plt.imshow(ath4,cmap='gray',,vmin = 0, vmax = 255)
plt.title('TRUNC+THRESH_OTSU')

"大津の2値化(BINARY_TRUNC)"
大津の2値化(BINARY_TRUNC)

ここで元画像grayの輝度ヒストグラムと大津の2値化で得られた閾値を赤線で示す。画像の輝度ヒストグラムgray.ravel()として2次元マトリックスを1次元に変換してからplt.hist(gray.ravel(),256)`を適用する。256は値の区切り数で、画像データは0~255のため256とした。元画像は低輝度側に多く分布していて、高い輝度ほど頻度が減っていることがわかる。

a=plt.hist(gray.ravel(),256)
plt.xlabel('Value')
plt.ylabel('Count')
plt.title('Peach')
plt.vlines(102, 0, 3000, "red") 

peach画像の輝度ヒストグラム

3. 他の画像への適用例

 大津の2値化を用いて、代表的な標準画像(例えば標準画像データベース[神奈川工大 信号処理応用研究室])に対して2値化処理と輝度分布の関係を調べてみた。基本的にはカラー画像をグレースケール変換したものを元画像としている。OpenCVのコードは上のコードと同じ  

"マンドリル"
マンドリル

マンドリルの輝度ヒストグラムは120付近に大きなピークと170付近に小さなピークがあり、閾値としては130付近に設定されている。2値化処理した画像としては綺麗に分けられている。

"Mandrill輝度ヒストグラム"
Mandrill輝度ヒストグラム

"オウム"
オウム

"オウム輝度ヒストグラム"
オウム輝度ヒストグラム

オウムの輝度ヒストグラムは90付近の大きなピークと190付近にピークがあり、閾値としては140付近に設定されている。2値化処理した画像は、色合いとしては分けられているが画像としては左側のインコが識別しにくい。

"唐辛子"
唐辛子

"唐辛子輝度ヒストグラム"
唐辛子輝度ヒストグラム

唐辛子の輝度ヒストグラムは90付近のピークと160~180付近のピークに大別でき、閾値としては120付近に設定されている。2つの画像の色(カラーでは緑と赤)がしっかりとわけられている。

4. まとめ

 今回は大津の2値化による閾値の自動計算の方法と、いくつかの画像への適用、輝度ヒストグラム閾値の関係などを調べた。