OpenCV – inRange で画像を2値化する方法について

目次
概要
OpenCV の inRange を使用した2値化方法について解説します。
Advertisement
inRange による2値化
inRange() は指定した範囲の画素を 255、それ以外の画素を0として2値化を行う関数です。

1チャンネル画像の2値化
dst = cv2.inRange(src, l, u)
$$
\displaystyle
dst(x, y) =
\begin{cases}
255 & l \le src(x, y) \le u \\
0 & その他の場合
\end{cases}
$$
3チャンネル画像の2値化
dst = cv2.inRange(src, (l1, l2, l3), (u1, u2, u3))
$$
\displaystyle
dst(x, y) =
\begin{cases}
255 & (l_1, l_2, l_3) \le src(x, y) \le (u_1, u_2, u_3) \\
0 & その他の場合
\end{cases}
$$
Advertisement
画像から特定の色を抽出する
inRange は画像から特定の色を抽出したい場合に便利です。
In [1]:
import cv2
import numpy as np
from IPython import display
from matplotlib import pyplot as plt
def imshow(img, format=".jpg", **kwargs):
"""ndarray 配列をインラインで Notebook 上に表示する。
"""
img = cv2.imencode(format, img)[1]
img = display.Image(img, **kwargs)
display.display(img)
img = cv2.imread("sample.jpg")
色の選択は RGB 色空間で行うよりも、HSV 色空間に変換して行ったほうが選択しやすくなります。HSV 色空間の場合、S、V は下限0、上限255のままにし、H (色相) で調整するのがおすすめです。
HSV 色空間での範囲選択は下記を参考にしてください。

In [2]:
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
lower = (0, 0, 0)
upper = (20, 255, 255)
bin_img = cv2.inRange(hsv, lower, upper)
imshow(bin_img)

2値画像を使って透過処理する
作成した2値画像を使って、透過処理を行う例を紹介します。
In [3]:
# アルファチャンネルを追加する
bgra = cv2.cvtColor(img, cv2.COLOR_BGR2BGRA)
# 2値画像の値が0の画素のアルファ値は0 (透過) にする
bgra[bin_img == 0, 3] = 0
imshow(bgra, ".png")

ipywidgets を使用したパラメータ調整
ipywidgets のスライダー機能を使って、インタラクティブにパラメータを決めるためのコードを紹介します。
In [4]:
from ipywidgets import widgets, fixed
def inRange(img, c1, c2, c3):
"""2値化処理を行い、結果を表示する。
"""
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
lower = np.array([c1[0], c2[0], c3[0]])
upper = np.array([c1[1], c2[1], c3[1]])
bin_img = cv2.inRange(hsv, lower, upper)
imshow(bin_img)
# パラメータ lower, upper を設定するスライダー
names = ["H", "S", "V"]
parts = {}
for i, name in enumerate(names, 1):
slider = widgets.SelectionRangeSlider(
options=np.arange(256), index=(0, 255), description=name
)
slider.layout.width = "400px"
parts[f"c{i}"] = slider
# 画像を読み込む。
img = cv2.imread("sample.jpg")
# ウィジェットを表示する。
widgets.interactive(inRange, **parts, img=fixed(img))
-
前の記事
OpenCV – float 型の配列を画像化する方法について 2020.06.21
-
次の記事
OpenCV – findContours で画像から輪郭を抽出する方法 2020.08.13