KURORO BLOGのロゴ

このエントリーをはてなブックマークに追加
OpenCVで使われるthresholdとは?threshold活用例を徹底解説

OpenCVで使われるthresholdとは?threshold活用例を徹底解説

今回はOpenCVで使われるthresholdに関して、定義から活用例をわかりやすく解説いたします。thresholdの使い方がわからない、thresholdの活用法をサンプルコードから学びたい方へおすすめです。ぜひ最後までご一読ください。

目次
  1. OpenCVで使われるthresholdとは?
  2. OpenCVで使われるthreshold関数の定義
    1. しきい値のきめ方
  3. OpenCVで使われるadaptiveThreshold関数の定義
  4. まとめ
  5. 参考文献

執筆者 - おすすめの記事3選

OpenCVで使われるthresholdとは?

OpenCVで使われるthresholdとは、2値化(画素の色を示す値を0 or Nのどちらかに変換する)するための関数を意味します。

画素 : 画像は点の集まりで成り立っている。点1つ = 画素と呼ぶ。それぞれの画素には、色を示す値が格納されていて、今回は色を示す値を2値化(0 or Nのどちらかに変換する)する。

画素のイメージ画像

2値化(画素の色を示す値を0 or Nのどちらかに変換する)イメージ

OpenCVで使われるthreshold関数の定義

threshold関数は

1# cv2(OpenCV)を利用する宣言を行う。
2import cv2
3
4# threshold関数 : しきい値を用いて画素の色を示す値を、2値化(0 or N)するための関数。(最終結果を白黒画像にしたい場合は、前処理として画像をグレースケールに変更しておく。)
5# グレースケールとは? : https://www.shinkohsha.co.jp/blog/monochrome-shirokuro-grayscale/
6# しきい値とは? : https://wa3.i-3-i.info/word15002.html
7
8# 第一引数 : 多次元配列(画像情報)
9# 第二引数 : しきい値 float型
10
11# 第三引数 : しきい値を超えた画素に対して、色を示す値を指定。 2値化(0 or N)のNの部分に相当する。float型。(第四引数の定数が、cv2.THRESH_TOZERO, cv2.THRESH_TOZERO_INV, cv2.THRESH_TRUNCの場合、設定する必要はあるが、利用はされない。)
12
13# 第四引数 : 2値化(0 or N)するための条件のタイプを指定する。
14# 2値化するための条件のタイプ一覧情報 : http://opencv.jp/opencv-2svn/cpp/miscellaneous_image_transformations.html#cv-threshold
15
16# 戻り値 #################
17# ret : しきい値を返す。第四引数へ(cv2.THRESH_OTSU or cv2.THRESH_TRIANGLE)を使用した場合、自動的に決まるしきい値が返される。
18# thresh : 多次元配列(画像情報)
19#######################
20ret, thresh = cv2.threshold(img, 数字, 数字, 定数)

で定義されます。

例えば以下のようなコードを作成すると、

1# cv2(OpenCV)を利用する宣言を行う。
2import cv2
3import sys
4
5# imread : 画像ファイルを読み込んで、多次元配列(numpy.ndarray)にする。
6# imreadについて : https://kuroro.blog/python/wqh9VIEmRXS4ZAA7C4wd/
7# 第一引数 : 画像のファイルパス
8# 第二引数 : 画像の形式を指定。0を指定する場合、画像をグレースケールで読み込む。
9# 戻り値 : 多次元配列(numpy.ndarray)が返される。
10img = cv2.imread('./xxx.xxx', 0)
11
12# 画像ファイルが正常に読み込めなかった場合、プログラムを終了する。
13if img is None:
14    sys.exit("Could not read the image.")
15
16# threshold関数 : しきい値を用いて画素の色を示す値を2値化(0 or N)するための関数。
17
18# 第一引数 : 多次元配列(画像情報)
19# 第二引数 : しきい値。float型。127とする。
20
21# 第三引数 : しきい値を超えた画素に対して、色を示す値を指定。 2値化(0 or N)のNの部分に相当する。float型。255とする。
22
23# 第四引数 : 2値化(0 or N)するための条件のタイプを指定する。
24# cv2.THRESH_BINARY : (画素の色を示す値 <= 第二引数)の場合、画素に対して、0の値を与える。(画素の色を示す値 > 第二引数)の場合、画素に対して、第三引数の値を与える。
25
26# 戻り値 #################
27# ret : しきい値を返す。127を返す。
28# thresh : 多次元配列(numpy.ndarray)を返す。
29#########################
30ret, thresh = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
31
32# imwrite : 画像の保存を行う関数
33# 第一引数 : 保存先の画像ファイル名
34# 第二引数 : 多次元配列(numpy.ndarray)
35# <第二引数の例>
36# [
37# [
38# [234 237 228]
39# ...
40# [202 209 194]
41# ]
42# [
43# [10 27 16]
44# ...
45# [36 67 46]
46# ]
47# [
48# [34 51 40]
49# ...
50# [50 81 60]
51# ]
52# ]
53# imwriteについて : https://kuroro.blog/python/i0tNE1Mp8aEz8Z7n6Ggg/
54cv2.imwrite('./output.jpg', thresh)

以下の画像のように、画像が描画されます。

元画像

threshold関数を利用して作成された画像

imreadに関しては、OpenCVで使われるimreadとは?使い方から配列が画像になる仕組みを解説でまとめていますので、詳しく知りたい方は是非ご確認ください。

imwriteに関しては、OpenCVで使われるimwriteとは?imwriteの定義から使用例をご紹介でまとめていますので、詳しく知りたい方は是非ご確認ください。

threshold関数の第四引数(2値化(0 or N)するための条件のタイプを指定する)情報

タイプ名称概要
cv2.THRESH_BINARY                     しきい値以下の色を示す値を0、それ以外の色を示す値をNにして2値化(0 or N)を行います。(参考)
cv2.THRESH_BINARY_INV                     しきい値以下の色を示す値をN、それ以外の色を示す値を0にして2値化(0 or N)を行います。(参考)
cv2.THRESH_TRUNC                     しきい値以下の色を示す値をそのままにして、それ以外の色を示す値をしきい値にして2値化(そのまま or しきい値)を行います。(参考)
cv2.THRESH_TOZERO                     しきい値以下の色を示す値を0、それ以外の色を示す値をそのままにして2値化(0 or そのまま)を行います。(参考)
cv2.THRESH_TOZERO_INV                     しきい値以下の色を示す値をそのまま、それ以外の色を示す値を0にして2値化(0 or そのまま)を行います。(参考)
cv2.THRESH_OTSU                     グレースケール画像でないと動かない大津のアルゴリズムを用いて、しきい値を自動で決める。しきい値(自動で決められたもの)以下の色を示す値を0、それ以外の色を示す値をNにして、2値化(0 or N)を行います。
cv2.THRESH_TRIANGLE                     グレースケール画像でないと動かない。トライアングルアルゴリズムを用いて、しきい値を自動で決める。しきい値(自動で決められたもの)以下の色を示す値を0、それ以外の色を示す値をNにして、2値化(0 or N)を行います。

しきい値のきめ方

threshold関数の第四引数(2値化するための条件のタイプを指定する)へ(cv2.THRESH_OTSU or cv2.THRESH_TRIANGLE)を指定して、自動でしきい値を決める場合は良いのですが、それ以外の定数を指定する場合に、具体的にどのようなしきい値(threshold関数の第二引数)を入れるべきか、悩んでいる方も多いかと思います。

上記の問題を解決するために、筆者の場合ipywidgetsというJupyter Notebookで使える拡張機能を使って、しきい値を調整しています。

【ipywidgetsを利用するために準備したこと】

上記で作成した空のJupyter Notebookへ、以下のコードを貼り付けて、実行(▶️を選択)してみてください。

1import cv2
2from IPython.display import Image, display
3from ipywidgets import widgets
4
5def imshow(img):
6    """画像をJupyter Notebook上に表示する。"""
7    _, encoded = cv2.imencode(".jpg", img)
8    display(Image(encoded))
9
10def execute(thresh, type_list):
11    """2値化(0 or N)を行い、結果画像を表示する。 """
12    # evalについて : https://techacademy.jp/magazine/40662
13    _, binary = cv2.threshold(img, thresh, 255, eval(type_list))
14    imshow(binary)
15
16# imread : 画像ファイルを読み込んで、多次元配列(numpy.ndarray)にする。
17# imreadについて : https://kuroro.blog/python/wqh9VIEmRXS4ZAA7C4wd/
18# 第一引数 : 画像のファイルパス
19# 第二引数 : 画像の形式を指定。0を指定する場合、画像をグレースケールで読み込む。
20# 戻り値 : 多次元配列(numpy.ndarray)が返される。
21# ※ 2値化したい画像を設定ください。
22img = cv2.imread("xxx.xxx", 0)
23
24# 部品情報を格納する。
25parts = {}
26
27# しきい値を調整するスライダー
28# 参考 : https://ipywidgets.readthedocs.io/en/latest/examples/Widget%20List.html?highlight=IntSlider#IntSlider
29# min : しきい値の最小値
30# mix : しきい値の最大値
31# step : しきい値の増減値
32# value : しきい値の初期値
33# description : スライダーの説明文
34parts["thresh"] = widgets.IntSlider(
35    min=0,
36    max=255,
37    step=1,
38    value=0,
39    description="thresh: "
40)
41
42# 2値化(0 or N)するための条件のタイプを選択するドロップダウン
43# ドロップダウンとは? : https://wa3.i-3-i.info/word11625.html
44# 参考 : https://ipywidgets.readthedocs.io/en/latest/examples/Widget%20List.html#Dropdown
45# options : 2値化(0 or N)するための条件のタイプの選択肢
46# description : ドロップダウンの説明文
47parts["type_list"] = widgets.Dropdown(
48    options=[
49        "cv2.THRESH_BINARY",
50        "cv2.THRESH_BINARY_INV",
51        "cv2.THRESH_TRUNC",
52        "cv2.THRESH_TOZERO",
53        "cv2.THRESH_TOZERO_INV",
54        "cv2.THRESH_OTSU",
55        "cv2.THRESH_TRIANGLE",
56    ],
57    description="type_list: "
58)
59
60# 部品の大きさを設定する。
61for part in parts.values():
62    part.layout.width = "400px"
63
64widgets.interactive(execute, **parts)

すると以下の画像のような画面が現れます。

実際に部品(スライダーやドロップダウン)を動かしてみると、それぞれの値に応じて画像を2値化して、画像が変更されます。

OpenCVで使われるadaptiveThreshold関数の定義

先ほどは画素を元に、2値化(画素の色を示す値を0 or Nのどちらかに変換する)する方法をお伝えしました。

今回は画素を元に、2値化(画素の色を示す値を0 or Nのどちらかに変換する)することは変わりませんが、画素の周辺画素の情報も利用して、2値化する方法(adaptiveThreshold関数)を説明いたします。

adaptiveThreshold関数は、画像の各所に色の濃淡がたくさんある場合に、よく利用されます。

adaptiveThreshold関数は

1# cv2(OpenCV)を利用する宣言を行う。
2import cv2
3
4# adaptiveThreshold関数 : ある画素の周辺画素の情報も利用して、しきい値を自動計算し、2値化する関数(前処理として画像をグレースケールに変更しておく必要がある。)
5# グレースケールとは? : https://www.shinkohsha.co.jp/blog/monochrome-shirokuro-grayscale/
6
7# 第一引数 : 多次元配列(画像情報)
8# 第二引数 : しきい値を超えた画素に対して、色を示す値を指定。 2値化(0 or N)のNの部分に相当する。float型。
9
10# 第三引数 : しきい値の計算方法を指定する。
11# 以下、第三引数へ格納される定数。どちらかを選択する。
12###########################
13# cv2.ADAPTIVE_THRESH_GAUSSIAN_C : ガウシアンの重み付き平均値。下記リンクの「【3ステップ】Canny法の理論を徹底解説」章の「ノイズ削減」部分をご確認ください。
14# (https://kuroro.blog/python/wOt3yEohr7oQt1qzif71/)
15# 最後に変換した画素一覧を平均して、しきい値とする。
16# cv2.ADAPTIVE_THRESH_MEAN_C : 近傍画素値の平均値。ガウシアンの重み付き平均値の重み付きがないものと考えるとよい。最後に変換した画素一覧を平均して、しきい値とする。
17###########################
18
19# 第四引数 : 2値化(0 or N)するための条件のタイプを指定する。
20# 以下、第四引数へ格納される定数。どちらかを選択する。
21###########################
22# cv2.THRESH_BINARY : しきい値以下の色を示す値を0、それ以外の色を示す値をNにして2値化(0 or N)を行います。
23# cv2.THRESH_BINARY_INV : しきい値以下の色を示す値をN、それ以外の色を示す値を0にして2値化(0 or N)を行います。
24###########################
25
26# 第五引数 : しきい値計算に利用する近傍領域(ある画素に注目した場合の、(第五引数 x 第五引数)の画素領域)の大きさを指定する。1より大きい奇数の値を指定する。
27# 第六引数 : 第三引数の方法で計算したしきい値から、第六引数で指定する値を引いて、最終的なしきい値とする。
28
29# 戻り値 #################
30# thresh : 多次元配列(画像情報)
31#######################
32thresh = cv2.adaptiveThreshold(img, 数字, 定数, 定数, 数字, offset)

で定義されます。

例えば以下のようなコードを作成すると、

1import cv2
2import sys
3
4# imread : 画像ファイルを読み込んで、多次元配列(numpy.ndarray)にする。
5# imreadについて : https://kuroro.blog/python/wqh9VIEmRXS4ZAA7C4wd/
6# 第一引数 : 画像のファイルパス
7# 第二引数 : 画像の形式を指定。0を指定する場合、画像をグレースケールで読み込む。
8# 戻り値 : 多次元配列(numpy.ndarray)が返される。
9img = cv2.imread('./xxx.xxx', 0)
10
11# 画像ファイルが正常に読み込めなかった場合、プログラムを終了する。
12if img is None:
13    sys.exit("Could not read the image.")
14
15# adaptiveThreshold関数 : ある画素の周辺画素の情報も利用して、しきい値を自動計算し、2値化する関数
16
17# 第一引数 : 多次元配列(画像情報)
18# 第二引数 : しきい値を超えた画素に対して、色を示す値を指定。 2値化(0 or N)のNの部分に相当する。float型。
19
20# 第三引数 : しきい値の計算方法。
21# cv2.ADAPTIVE_THRESH_GAUSSIAN_C : ガウシアンの重み付き平均値。下記リンクの「【3ステップ】Canny法の理論を徹底解説」章の「ノイズ削減」部分をご確認ください。
22# (https://kuroro.blog/python/wOt3yEohr7oQt1qzif71/)
23# 最後に変換した画素一覧を平均して、しきい値とする。
24
25# 第四引数 : 2値化(0 or N)するための条件のタイプを指定する。
26# cv2.THRESH_BINARY : しきい値以下の色を示す値を0、それ以外の色を示す値をNにして、2値化(0 or N)を行います。
27
28# 第五引数 : しきい値計算に利用する近傍領域(ある画素に注目した場合の、(第五引数 x 第五引数)の画素領域)の大きさを指定する。1より大きい奇数の値を指定する。21x21の画素領域とする。
29# 第六引数 : 第三引数の方法で計算したしきい値から、第六引数で指定する値を引いて、最終的なしきい値とする。
30
31# 戻り値 #################
32# thresh : 多次元配列(画像情報)
33#######################
34thresh = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 21, 0)
35
36# imwrite : 画像の保存を行う関数
37# 第一引数 : 保存先の画像ファイル名
38# 第二引数 : 多次元配列(numpy.ndarray)
39# <第二引数の例>
40# [
41# [
42# [234 237 228]
43# ...
44# [202 209 194]
45# ]
46# [
47# [10 27 16]
48# ...
49# [36 67 46]
50# ]
51# [
52# [34 51 40]
53# ...
54# [50 81 60]
55# ]
56# ]
57# imwriteについて : https://kuroro.blog/python/i0tNE1Mp8aEz8Z7n6Ggg/
58cv2.imwrite('./output.jpg', thresh)

以下の画像のように、画像を描画します。

元画像

adaptiveThreshold関数を利用して作成された画像

まとめ

  • OpenCVで使われるthresholdとは、2値化(画素の色を示す値を0 or Nのどちらかに変換する)するための関数を意味する。
  • しきい値を調整する際、ipywidgetsを活用してみると良い。

参考文献

記事に関するお問い合わせ