【Python/OpenCV】単純な二値化処理

Python版OpenCV(cv2.threshold)もしくはNumPyで単純な二値化処理を実装する方法をソースコード付きで解説します。

## 【二値化1】単純二値化処理

まずはじめに、二値画像は「色を0(黒)と1(白)の二階調(1bit)で表した画像」です。
ただし、画像処理プログラムでは、二値化画像の画素値を0(黒)と255(白)の8ビットで表す方が一般的です。

画像を二値画像に変換することを二値化処理といい、ある閾値で画像を二値画像に変換します。画像から物体の輪郭を取り出したりできます。

■二値画像変換の例(左からRGBカラー画像 → グレースケール画像 → 二値画像)

お借りした画像:プロ生ちゃん(暮井 慧)

動画解説版

二値化処理のポイントは、閾値の決め方にあります。
最も単純なのは、人が感覚的に閾値を設定する方法です。

自動的に最適な閾値を求める、より高度な「大津の二値化処理」「適応的二値化処理」については下記ページで紹介しています。

関連記事
二値化処理の原理
【Python/OpenCV】大津の手法で二値化処理
【Python/OpenCV】適応的閾値処理で二値化

今回は、Python言語で以下の2通りの方法で単純な2値化処理を実装してみました。

説明
方法① NumPyでアルゴリズムを書いて実装
方法② cv2.thresholdで簡単に実装(1行で書けちゃうので楽チン)

書式(cv2.threshold)

ret, dst = cv2.threshold(src, threshold, max_value, threshold_type)
パラメータ名 説明
src 入力画像(グレースケール)
threshold 閾値
max_value 二値化したときの最大値(真っ白にするなら255)
threshold_type 使用する二値化手法(単純な二値化ならcv2.THRESH_BINARYを指定)
dst 出力画像

サンプルコード

サンプルプログラムのソースコードです。

方法①

#-*- coding:utf-8 -*-
import cv2
import numpy as np

# 閾値
threshold_value = 127

# 入力画像の読み込み
img = cv2.imread("C:/github/sample/python/opencv/input.png")

# グレースケール変換
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)

# 出力画像用の配列生成
threshold_img = gray.copy()

# 方法1(NumPyで実装)
threshold_img[gray < threshold_value] = 0
threshold_img[gray >= threshold_value] = 255

# 結果を出力
cv2.imwrite("C:/github/sample/python/opencv/th.png", threshold_img)

方法②

#-*- coding:utf-8 -*-
import cv2
import numpy as np


# 閾値
threshold_value = 127

# 入力画像の読み込み
img = cv2.imread("C:/github/sample/python/opencv/input.png")

# グレースケール変換
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)

# 方法2 (OpenCVで実装)
ret, threshold_img = cv2.threshold(gray, threshold_value, 255, cv2.THRESH_BINARY)

# 結果を出力
cv2.imwrite("C:/github/sample/python/opencv/th.png", threshold_img)

※動作には、OpenCVライブラリのインストールが必要です。

####実行結果
サンプルプログラムの実行結果です。

■入力画像(左)と出力画像(右)

## 【二値化2】適応的二値化処理とは

適応的二値化処理(AdaptiveThreshold)は、閾値を固定せず、画素ごとに変化させる二値化処理です。
つまり、画素毎に異なる閾値を算出して設定します。

適応的二値化処理が向いているケース
1 全体的に緩やかに明るさが変化しているようなるような画像(不鮮明な写真や影が写り込んでいる写真など)
【画像処理】適応的二値化処理の原理・特徴・計算式
この記事では、画像処理における適応的二値化処理の原理や計算式についてまとめました。

このアルゴリズムは、NumPyで簡単に実装できます。
また、OpenCVの「cv2.adaptiveThreshold」メソッドを使えば、より簡単に実装できます。

動画解説版

書式

dst = cv2.adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C)
パラメータ名 説明
src 入力画像
maxValue 閾値を満たす画素に与える画素値
adaptiveMethod 閾値の計算方法(cv2.ADAPTIVE_THRESH_MEAN_C なら近傍画素値の平均値、cv2.ADAPTIVE_THRESH_GAUSSIAN_Cならガウシアンの重み付き平均値を閾値にする)
thresholdType 閾値の種類(THRESH_BINARY or THRESH_BINARY_INV)
blockSize 閾値計算に利用する近傍領域サイズ(3なら8近傍)
C 計算した閾値からCを引いた値を最終的な閾値にする
dst 出力画像

今回は、以下の2通りの方法で処理を実装してみました。

説明
方法① NumPyでアルゴリズムを書いて実装(原理の理解を深めるため)
方法② cv2.adaptiveThresholdで実装

ソースコード

サンプルプログラムのソースコードです。

方法①


方法②


実行結果

サンプルプログラムの実行結果です。

■入力画像(左)と出力画像(右)

【Python/OpenCV】適応的閾値処理で二値化
Python版OpenCV(cv2.adaptiveThreshold)で適応的二値化処理を実装する方法をソースコード付きで解説します。

## 【二値化】大津の手法で二値化処理

大津の手法(判別分析法)は、自動的に閾値を決定して二値化処理を行う手法の1つです。
この手法では、分離度が最も大きくなるときの閾値を求めます。(詳細は下記ページ参照)

関連記事
原理はこちら 大津の二値化処理の原理

今回は、Python言語で以下の2通りの方法で処理を実装してみました。

説明
方法① NumPyで大津のアルゴリズムを書いて実装
方法② cv2.thresholdで簡単に実装(1行で書けちゃうので楽チン)

動画解説版

書式

ret, dst = cv2.threshold(src, threshold, max_value, threshold_type)
パラメータ名 説明
src 入力画像(グレースケール)
threshold 閾値(大津の手法を使う場合は自動で設定してくれるので0)
max_value 二値化したときの最大値(真っ白にするなら255)
threshold_type 使用する二値化手法(大津ならcv2.THRESH_OTSUを指定)
dst 出力画像

## 【サンプルコード】Python3 + OpenCV

サンプルプログラムのソースコードです。

方法①


方法②


ポイント

クラス間分散の分子が最大ならば、分離度も最大になります。
よって、計算高速化のためにクラス間分散の分子のみを計算して比較しています。

実行結果

サンプルプログラムの実行結果です。

■入力画像(左)と出力画像(右)

【Python/OpenCV】大津の手法で二値化処理
Python版OpenCV(cv2.threshold)もしくはNumPyで大津の手法(判別分析法)を実装し、画像を二値化する方法をソースコード付きで解説します。
【PythonでOpenCV入門】使い方とサンプル集
OpenCV(Intel Open Source Computer Vision Library)とは、インテル社で開発された画像処理・画像認識用のオープンソースライブラリです。Python/C++/Java/Android/Node.js...

コメント