KURORO BLOGのロゴ

このエントリーをはてなブックマークに追加
OpenCVで使われるinRangeとは?inRangeの定義から活用例を解説

OpenCVで使われるinRangeとは?inRangeの定義から活用例を解説

今回はOpenCVで使われるinRangeに関して、定義から活用例を丁寧に解説いたします。inRangeを始めて聞いた、画像を2値化したいと考える方はおすすめです。ぜひ最後までご一読ください。

目次
  1. OpenCVで使われるinRangeとは?
  2. OpenCVで使われるinRange関数の定義
    1. inRangeの値(第二引数, 第三引数)を調整する
  3. まとめ
  4. 参考文献

OpenCVで使われるinRangeとは?

OpenCVで使われるinRangeとは、2値化(画像を白と黒の2色に変換する)するための関数を意味します。

inRange関数は、画像内に描画される、特定の色を持つ物体の検出を行う際に、よく利用されます。

具体的なイメージとしては、以下の画像のように、白黒の画像を作成(2値化)するイメージを持ってもらうと良いでしょう。

元画像

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

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

inRange関数は、

1# cv2(OpenCV)を利用する宣言を行う。
2import cv2
3
4################################
5# <1チャンネル画像の2値化の場合>
6# 1チャンネル : 0 ~ 255の値のみ(256通り)で画素を表現すること。値の意味合いは形式(RGB(Red, Green, Blue)形式, BGR(Blue, Green, Red)形式, HSV(Hue(色相), Saturation(彩度), Value(明度))形式など)によって異なる。
7# 画素とは? : https://ptl.imagegateway.net/contents/original/glossary/%E7%94%BB%E7%B4%A0.html
8# RGB(Red, Green, Blue)形式とは? : https://ja.wikipedia.org/wiki/RGB
9# HSV(Hue(色相), Saturation(彩度), Value(明度))形式とは? : https://ja.wikipedia.org/wiki/HSV%E8%89%B2%E7%A9%BA%E9%96%93
10# 色相とは? : https://www.webcolordesign.net/color_basic/attribute_color/attribute_hue.html
11# 彩度とは? : https://ja.wikipedia.org/wiki/%E5%BD%A9%E5%BA%A6
12# 明度とは? : https://ja.wikipedia.org/wiki/%E6%98%8E%E5%BA%A6
13
14# 第一引数(必須) : 多次元配列(画像情報)
15
16# 第二引数(必須) : 2値化する条件の下限
17# 第三引数(必須) : 2値化する条件の上限
18# l <= img(画素) < uの時、img(画素)を255(白)にする。
19# l > img(画素) または u - 1 > img(画素)の時、img(画素)を0(黒)にする。
20
21# 戻り値 : 多次元配列(画像情報)
22img = cv2.inRange(img, l, u)
23################################
24
25################################
26# <3チャンネル画像の2値化の場合>
27# 3チャンネル : (0, 0, 0) ~ (255, 255, 255)の値のみ(256x256x256通り)で画素を表現すること。値の意味合いは形式(RGB(Red, Green, Blue)形式, BGR(Blue, Green, Red)形式, HSV(Hue(色相), Saturation(彩度), Value(明度))形式など)によって異なる。
28
29# 第一引数(必須) : 多次元配列(画像情報)
30
31# 第二引数(必須) : 2値化する条件の下限
32# 第三引数(必須) : 2値化する条件の上限
33# (l1, l2, l3) <= img(画素) < (u1, u2, u3)の時、img(画素)を255(白)にする。
34# (l1, l2, l3) > img(画素) または (u1 - 1, u2 - 1, u3 - 1) > img(画素)の時、img(画素)を0(黒)にする。
35
36# 戻り値 : 多次元配列(画像情報)
37img = cv2.inRange(img, (l1, l2, l3), (u1, u2, u3))
38################################

で定義されます。

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

1import cv2
2import sys
3
4# imread : 画像ファイルを読み込んで、多次元配列(numpy.ndarray)にする。
5# imreadについて : https://kuroro.blog/python/wqh9VIEmRXS4ZAA7C4wd/
6# 第一引数 : 画像のファイルパス
7# 戻り値 : 行 x 列 x 色の三次元配列(numpy.ndarray)が返される。
8img = cv2.imread('./xxx.xxx')
9
10# 画像ファイルが正常に読み込めなかった場合、プログラムを終了する。
11if img is None:
12    sys.exit("Could not read the image.")
13
14# cvtColor : 画像の色空間(色)を変更する関数。
15# cvtColorについて : https://kuroro.blog/python/7IFCPLA4DzV8nUTchKsb/
16
17# 第一引数 : 多次元配列(numpy.ndarray)
18
19# 第二引数 : 変更前の画像の色空間(色)と、変更後の画像の色空間(色)を示す定数を設定。
20# cv2.COLOR_BGR2HSV : BGR(Blue, Green, Red)形式の色空間(色)を持つ画像をHSV(Hue(色相), Saturation(彩度), Value(明度))形式へ変更する。
21# ※ なぜHSV形式に変更するのか? : RGB(Red, Green, Blue)形式やBGR(Blue, Green, Red)形式で色を表現し、inRange関数を利用しても構わない。ただinRange関数の第二引数, 第三引数で指定する値の感覚が掴みにくいため、HSV(Hue(色相), Saturation(彩度), Value(明度))形式で色を表現し、inRange関数の第二引数, 第三引数を指定することをおすすめする。
22
23# 戻り値 : 多次元配列(numpy.ndarray)
24img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
25
26# inRange : 2値化(画像を白と黒の2色に変換する)するための関数
27# 第一引数 : 多次元配列(numpy.ndarray)
28# 第二引数 : 2値化する条件の下限
29# 第三引数 : 2値化する条件の上限
30# 戻り値 : 多次元配列(numpy.ndarray)
31img = cv2.inRange(img, (0, 0, 0), (255, 255, 94))
32
33# imwrite : 画像の保存を行う関数
34# 第一引数 : 保存先の画像ファイル名
35# 第二引数 : 多次元配列(numpy.ndarray)
36# <第二引数の例>
37# [
38# [
39# [234 237 228]
40# ...
41# [202 209 194]
42# ]
43# [
44# [10 27 16]
45# ...
46# [36 67 46]
47# ]
48# [
49# [34 51 40]
50# ...
51# [50 81 60]
52# ]
53# ]
54# imwriteについて : https://kuroro.blog/python/i0tNE1Mp8aEz8Z7n6Ggg/
55cv2.imwrite('output.jpg', img)

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

元画像

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

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

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

cvtColorに関しては、OpenCVで使われるcvtcolorとは?cvtcolorの活用例を徹底紹介でまとめていますので、詳しく知りたい方は是非ご確認ください。

inRangeの値(第二引数, 第三引数)を調整する

inRange関数の第二引数, 第三引数へ2値化のための値を定めますが、具体的にどのような値を入れるべきか悩んでいる方も多いかと思います。

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

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

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

1import cv2
2from IPython.display import Image, display
3from ipywidgets import widgets
4import numpy as np
5
6def imshow(img):
7    """画像をJupyter Notebook上に表示する。"""
8    ret, encoded = cv2.imencode(".png", img)
9    display(Image(encoded))
10
11def inRange(**kwargs):
12    """2値化処理を行い、結果を表示する。"""
13    lower = tuple([int(l) for l, h in kwargs.values()])
14    upper = tuple([int(h) for l, h in kwargs.values()])
15    binary = cv2.inRange(img, lowerb=lower, upperb=upper)
16    imshow(binary)
17
18# imread : 画像ファイルを読み込んで、多次元配列(numpy.ndarray)にする。
19# imreadについて : https://kuroro.blog/python/wqh9VIEmRXS4ZAA7C4wd/
20# ※ 2値化したい画像を設定ください。
21img = cv2.imread("xxx.xxx")
22
23# cvtColor : 画像の色空間(色)を変更する関数。
24# cvtColorについて : https://kuroro.blog/python/7IFCPLA4DzV8nUTchKsb/
25# cv2.COLOR_BGR2HSV : BGR(Blue, Green, Red)形式の色空間(色)を持つ画像をHSV(Hue(色相), Saturation(彩度), Value(明度))形式へ変更する。
26img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
27
28# チャンネル数に応じてスライダーの数を設定する。
29num_channels = 1 if img.ndim == 2 else img.shape[2]
30parts = {}
31for i in range(num_channels):
32    slider = widgets.SelectionRangeSlider(
33        options=np.arange(256), index=(0, 255), description=f"channel {i}"
34    )
35    slider.layout.width = "400px"
36
37    parts[f"channel{i}"] = slider
38
39widgets.interactive(inRange, **parts)

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

実際にスライダーを動かすと、チャンネルの値に応じて2値化に対応し、画像が変更されます。

まとめ

  • OpenCVで使われるinRangeとは、2値化(画像を白と黒の2色に変換する)するための関数を意味する。
  • inRange関数を適切に利用するために、ipywidgetsを活用して値調節を行うとよい。

参考文献