[Python]OpenCVの使い方入門 閾値(2値化)処理について

画像処理ライブラリ OpenCV 必須技術の閾値処理を実施するやり方

近年,製造業では生産にかかる費用を低減させるために人手作業を自動化させる流れが出てきております。その中でも製品のエラー品チェックや生産工程で流れる製品の個数管理などで画像処理の需要が高まっています。実際に画像処理システムの世界市場(予測)を以下に貼っておきます。

ただ一言で画像処理と言っても色々なライブラリがあり,その選択次第でソフトの開発手法が大きく変わってきます。

今回紹介するのは数ある画像処理ライブラリの中でも特に人気のあるOpenCVを使って,画像処理において必須技術と言える閾値処理を紹介していこうと思います。

※OpenCVと画像処理の基本については  画像処理の基本解説 OpenCVの使い方入門 をご参照願います。また近い内容を紹介しているこちらのサイトもあわせて確認願います。

OpenCVを用いた閾値処理 開発環境と試験用画像の紹介

画像処理の必須技術ともいえる閾値処理をOpenCVで実装します。今回のシステム開発環境は以下の通りです。

  • プログラミング言語:Python3
  • 開発環境: Visual Studio 2019

今回はVisual Studioを使っていますがPythonを使えばメモ帳でも開発できます。

また,閾値処理を解説する上でサンプルとなる画像を紹介します。画像処理の業界ではLennaという女優の写真が良く使われますが私は2020年10月時点で大人気のVTuberの一人,常闇トワ様の画像を使わせていただいています。美しい・・・。

この画像を元に閾値処理を行っていきます。

閾値処理のプログラム紹介 OpenCVのcv2.thresholdを解説

OpenCVの閾値処理であるcv2.thresholdを説明していきます。OpenCVの閾値処理は以下の5パターンを指定でき,それぞれ閾値処理後の出力画像が異なるので場面に応じて使い分けてください。

  1. THRESH_BINARY
  2. THRESH_BINARY_INV
  3. THRESH_TRUNC
  4. THRESH_TOZERO
  5. THRESH_TOZERO_INV

それぞれの項目を順次説明していこうと思います。

※今回の記事は「Pythonで始めるOpenCV4 プログラミング」北山直之様著の画像を一部使用させていただいております。

THRESH_BINARY 純粋な閾値処理

閾値処理の基本形とも言えるTHRESH_BINARYを説明していきます。

閾値処理のイメージ図を示すと以下のような画像の出力になります。

図を見て頂けると分かると思いますが閾値よりも大きい値を指定した最大値に一律で変化させ,閾値よりも低い値は0(黒色)として出力させます。一般的な閾値処理のイメージと合致すると思います。

この処理を行うためのソースコードと出力結果は以下の通りです。ちなみに今回のソースコードでは上図で記載している閾値を100,指定した最大値を200に指定している事になります。

import cv2

img = cv2.imread('C:/Temp/towa.jpg',cv2.IMREAD_GRAYSCALE)   #グレースケールで画像を取得する
ret,dst = cv2.threshold(img,100,200,cv2.THRESH_BINARY)      #閾値処理を行う
cv2.imwrite('C:/Temp/Threshold.jpg',dst)                    #閾値処理した画像を保存する

儚げでかわいいですね・・・。防止の部分が色が黒かったから明暗がくっきり分かれていますね。

THRESH_BINARY_INV 閾値処理の反転

THRESH_BINARY_INVはINVERSEという単語の通り,閾値処理を反転させることができます。

閾値処理の反転というとイメージがわきにくいかも知れませんが下図のような処理を行います。

上図を見てもらえると分かると思いますが閾値よりも低い場合は指定した最大値に反転し,閾値以上の場合は0に反転します。完全にTHRESH_BINARYの反対側の処理ですね。

この処理を行うためのソースコードと出力結果は以下の通りです。先ほどと同様に閾値を100,指定した最大値を200に指定しています。

import cv2

img = cv2.imread('C:/Temp/towa.jpg',cv2.IMREAD_GRAYSCALE)   #グレースケールで画像を取得する
ret,dst = cv2.threshold(img,100,200,cv2.THRESH_BINARY_INV)  #閾値処理を行う
cv2.imwrite('C:/Temp/Threshold_INV.jpg',dst)                #閾値処理した画像を保存する

ホラゲーにでも出て来そうですね。帽子の部分が完全にさっきの画像と反転している事が分かりますね。しかしこれじゃ顔黒ギャルですね~それもいい感じですけど。

THRESH_TRUNC 閾値以上の値を閾値にそろえる

THRESH_TRUNCは閾値を指定すると閾値以上の値が閾値に統一され,他の値はそのまま変わらないという処理です。

文章で書いても分かりにくいとは思いますのでこちらもイメージ図を示します。

上図から閾値以上の値は閾値に丸められ,閾値以下の値はそのままですね。そのため部分的に極端な色をしている対象物を同じ色でまとめるなどの使い方があります。

この処理を行うためのソースコードと出力結果は以下の通りです。先ほどと同様に閾値を100に指定しています。第3引数に200を入力していますが特に処理には関係ありません。

import cv2

img = cv2.imread('C:/Temp/towa.jpg',cv2.IMREAD_GRAYSCALE)   #グレースケールで画像を取得する
ret,dst = cv2.threshold(img,100,200,cv2.THRESH_TRUNC)       #閾値処理を行う
cv2.imwrite('C:/Temp/Threshold_TRUNC.jpg',dst)              #閾値処理した画像を保存する

う~んちょっと見にくいですね。フラッシュをたいてしまったカメラ画像のようですね。少し閾値を低めにしてしまったので明るい(RGB低めの値)画像になっているんですね。

THRESH_TOZERO 閾値以下の値を0にする

THRESH_TOZEROは指定した閾値以上の値は変化させず,閾値以下の値は全て0にする処理です。

THRESH_TOZEROのイメージ図を以下に示します。

かなり思い切りのよい処理ですよね。閾値を高く指定した場合,ほぼ真っ黒な画像になります。

この処理を行うためのソースコードと出力結果は以下の通りです。先ほどと同様に閾値を100に指定しています。第3引数に200を入力していますが特に処理には関係ありません。

import cv2

img = cv2.imread('C:/Temp/towa.jpg',cv2.IMREAD_GRAYSCALE)    #グレースケールで画像を取得する
ret,dst = cv2.threshold(img,100,200,cv2.THRESH_TOZERO)       #閾値処理を行う
cv2.imwrite('C:/Temp/Threshold_TOZERO.jpg',dst)              #閾値処理した画像を保存する

やばいほどの美しさ!昭和のような画像ですがマイルドな感じが出て魅力が3割増しですね。やはり100という低めの閾値を指定したので綺麗に美白したかのような画像になっています。

THRESH_TOZERO_INV 閾値以上の値を0にする

THRESH_TOZERO_INVは上で説明したTHRESH_TOZEROの反転処理になります。これだけ書いても分かりにくいので以下にイメージ図を示します。

図を見てもらえると分かると思いますが閾値よりも高い値は強制的に0(黒色)になっています。また閾値よりも低い値は何も変化しません。かなり変わった処理ですよね。この記事を書いている今もどこで使うのかあまり想像できていません。

この処理を行うためのソースコードと出力結果は以下の通りです。先ほどと同様に閾値を100に指定しています。第3引数に200を入力していますが特に処理には関係ありません。

import cv2

img = cv2.imread('C:/Temp/towa.jpg',cv2.IMREAD_GRAYSCALE)    #グレースケールで画像を取得する
ret,dst = cv2.threshold(img,100,200,cv2.THRESH_TOZERO_INV)   #閾値処理を行う
cv2.imwrite('C:/Temp/Threshold_TOZERO_INV.jpg',dst)          #閾値処理した画像を保存する

黒すぎますねこれ。閾値を100で指定しているので多くの部分が閾値を超えてしまい,出力が0(黒色)になってしまったようです。この閾値を上げていくとどんどん白色が強い画像になっていきます。

今回は閾値(2値化)処理の5パターンを説明しました。私のような工場勤務で画像処理プログラムを作っているような人間だとほとんどの場合で基本形のTHRESH_BINARYを使う事になると思います。ただ取得している画像次第では他の処理も使う事にはなると思いますので是非5つのパターンでどういった処理をするのかは把握しておいていただきたいです。

Follow me!

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です