OpenCVのthreshold関数を使った画像の2値化処理

概要

この記事ではOpenCVで画像の2値化を実施する方法について紹介しています。OpenCVのthreshold関数を使った画像の2値化処理は、画像解析や画像処理における重要なステップです。特に、物体検出、顔認識、文字認識などのタスクでは、背景と前景を区別するために2値化が頻繁に使用されます。また、ノイズ除去やエッジ検出などの前処理としても利用されます。threshold関数は、指定した閾値に基づいて画像の各ピクセルを白または黒に変換するので、白と黒を何処で分けるかの閾値を設定する必要が有ります。

出力結果

サンプル画像 二値化画像

プログラム全体

#解説1 import cv2 import urllib import numpy as np #解説2 # サンプル画像をダウンロード url = 'https://upload.wikimedia.org/wikipedia/commons/0/08/Unequalized_Hawkes_Bay_NZ.jpg' with urllib.request.urlopen(url) as url_response: img_array = np.array(bytearray(url_response.read()), dtype=np.uint8) #解説3 # 配列から画像をデコード img = cv2.imdecode(img_array, -1) # 画像をグレースケールに変換 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) #解説4 # 閾値処理を適用 # ここでは、ピクセル値が127より大きい場合は255(白)、それ以外は0(黒)に変換します thresh_value, thresh_img = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY) #解説5 # 元の画像と閾値処理後の画像を表示 cv2.imshow('Original Image', img) cv2.imshow('Thresholded Image', thresh_img) cv2.waitKey(0)

解説

解説1: ライブラリのインポート

import cv2 import urllib import numpy as np

この部分では、後のコードで必要となるライブラリをインポートしています。各ライブラリの機能は以下の通りです:

cv2 OpenCVライブラリ。画像の読み込み、変換、閾値処理など、画像処理に必要な機能を提供します。
urllib URLを扱うためのライブラリ。画像をインターネットからダウンロードするために使用します。
numpy 数値計算を効率的に行うためのライブラリ。画像を配列として扱うために使用します。

補足:urllibとは?

urllib.request は URLs (Uniform Resource Locators) を取得するための Python モジュールで、このモジュールはとても簡単なインターフェースを urlopen 関数の形式で提供しています。 このモジュールはもう少し複雑な状況で利用するためにいくらか複雑なインターフェースも提供しています basic 認証やクッキー、プロキシ等。これらは handler や opener と呼ばれるオブジェクトとして提供されます。

解説2: 画像のダウンロード

# サンプル画像をダウンロード url = 'https://upload.wikimedia.org/wikipedia/commons/0/08/Unequalized_Hawkes_Bay_NZ.jpg' with urllib.request.urlopen(url) as url_response: img_array = np.array(bytearray(url_response.read()), dtype=np.uint8)

この部分では、指定したURLから画像をダウンロードしています。 urllib.request.urlopenを使ってURLを開き、そのレスポンスの内容(ここでは画像データ)を読み込んでいます。 読み込んだデータはバイト列(bytearray)として取得され、それをnumpy.arrayに変換して画像データとして扱えるようにしています。特に、opencvでは画像を数学的に処理するので、画像をバイト配列に変換する必要があります。

解説3: 画像のデコードとグレースケール変換

# 配列から画像をデコード img = cv2.imdecode(img_array, -1) # 画像をグレースケールに変換 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

この部分では、、img_array(これは一般的にNumPy配列形式の生のバイトデータ)から画像をデコードしています。デコードとは、符号化された情報(この場合は画像データ)を元の形式(この場合は画像)に変換することを意味しており、-1は、画像を読み込むときに元の色空間を維持するためのフラグです。その後、デコードされた画像データをグレースケール(RGBを輝度(白黒)に変換したモノクロデータ)に変換しています。各ピクセルのRGB値を一定の比率で合成し、単一の明るさ値(モノクロ)に変換します。cv2.COLOR_BGR2GRAYは、BGR色空間からグレースケールへの変換を指示するためのフラグです。

補足:なぜグレースケールに変換するのか?

グレースケールの必要性については、グレースケール変換は画像処理のタスク(特に画像解析やパターン認識など)で一般的に使用されるプリプロセッシング手法(前処理)であり、計算量を大幅に減らすことができます。カラー画像は各ピクセルごとにRGBの3つの色情報を持っていますが、グレースケール画像は1つの輝度情報しか持っていないため、画像処理等の処理速度が向上します。パターンマッチングや位置調整などの古典的な画像処理では色情報が不要であるため、グレースケールに変換しても問題なく、メリットが勝ります。
ちなみに、画像処理によってカラーカメラからモノクロにすると、カラーフィルタによって若干ぼけた画像になります。よりエッジを強調した画像を取得するために、産業用カメラではモノクロカメラというものがあります。モノクロカメラを使用することによって下記にある通り、エッジが綺麗にとることができます。
https://www.argocorp.com/UVC_camera/UVC_ColorMono.html

解説4: 閾値処理の適用

# 閾値処理を適用 # ここでは、ピクセル値が127より大きい場合は255(白)、それ以外は0(黒)に変換します thresh_value, thresh_img = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)

この部分では、cv2.thresholdを使って画像に閾値処理を適用しています。閾値処理とは、画像の各ピクセルに対して、その値がある閾値より大きければ一定の値(ここでは255、つまり白)に、それ以外なら別の値(ここでは0、つまり黒)に変換する処理です。このプログラムでは"127"を閾値に設定しているのでこれを境に白と黒に別れる事になります。

解説5: 画像の表示

#解説5 # 元の画像と閾値処理後の画像を表示 cv2.imshow('Original Image', img) cv2.imshow('Thresholded Image', thresh_img) cv2.waitKey(0)

この部分では、元の画像と閾値処理後の画像を表示しています。 cv2.imshowはOpenCVライブラリの関数で、画像をウィンドウで表示するために使用します。この関数は2つの引数を取ります。一つ目の引数はウィンドウの名前で、二つ目の引数は表示する画像(numpy配列)です。 cv2.waitKey()はキーボードからの入力をミリ秒単位で待つための関数です。引数が0の場合、ユーザーがキーを押すまで無限に待つことを意味します。この関数は通常、cv2.imshow()と一緒に使用され、ユーザーが画像を閲覧し終えるのを待ち、任意のキーを押すとウィンドウが閉じるようにします。

おまけ

OpenCVは多くの種類のカメラと互換性がありますが、特定のカメラの高度な機能を利用するための専用のインターフェースは提供していません。TheImagingSource社のICImagingControlは、同社のカメラに特化したSDKで、カメラの高度な機能を制御するためのインターフェースを提供しています。これには、露出、ゲイン、ホワイトバランスなどのカメラ設定の調整、ROI(Region of Interest)の設定、トリガーモードの制御などが含まれます。また、ICImagingControlは、カメラから直接取得した生の画像データに対して、下記のようにリアルタイムで上記のOpenCVの二値化処理を実行することができます。
https://www.argocorp.com/software/sdk/ICImagingControl/Sample_program/Python_34/callback.html