OpenCV – inRange で画像を 2 値化する方法

目次

概要

OpenCV の inRange を使用した 2 値化方法について解説します。

inRange による 2 値化

cv2.inRange() は、指定した範囲内の値を持つ画素を 255 で、それ以外の画素を 0 に変換して 2 値化を行う関数です。この関数は、画像中の特定の色範囲を抽出し、2 値画像を生成する際に利用されます。

1 チャンネル画像の 2 値化

255 に変換する輝度値の範囲 $[l, u]$ を指定します。

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 値化

255 に変換する輝度値の範囲の下限 $(l1, l2, l3)$ と上限 $u1, u2, u3$ を指定します。

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} $$

画像から特定の色を抽出する

cv2.inRange() は画像から特定の色を抽出するのに便利な関数です。

sample.jpg

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)

色の選択は RGB 色空間で行うよりも、HSV 色空間に変換して行ったほうが選択しやすくなります。HSV 色空間の場合、S、V は下限 0、上限 255 のままにし、H (色相) で調整するのがおすすめです。

HSV 色空間での範囲選択は下記を参考にしてください。

In [2]:
def binarize(img, c1, c2, c3):
    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]])

    dst = cv2.inRange(hsv, lower, upper)

    return dst


img = cv2.imread("sample.jpg")

dst = binarize(img, c1=(0, 20), c2=(0, 255), c3=(0, 255))
imshow(dst)

2 値画像を使って透過処理する

2 値画像を使って透過処理を行う方法を紹介します。

In [3]:
def binarize(img, c1, c2, c3):
    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]])

    dst = cv2.inRange(hsv, lower, upper)

    return dst


img = cv2.imread("sample.jpg")

img_bin = binarize(img, c1=(0, 20), c2=(0, 255), c3=(0, 255))

# アルファチャンネルを追加する
bgra = cv2.cvtColor(img, cv2.COLOR_BGR2BGRA)

# 2値画像の値が0の画素のアルファ値は0 (透過) にする
bgra[img_bin == 0, 3] = 0
imshow(bgra, ".png")

ipywidgets を使用したパラメータ調整

ipywidgets のスライダー機能を使って、インタラクティブにパラメータを決めるためのコードを紹介します。

スライダー

In [4]:
from ipywidgets import widgets, fixed


def binarize(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]])
    img_bin = cv2.inRange(hsv, lower, upper)
    imshow(img_bin)


# パラメータ 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(binarize, **parts, img=fixed(img))

コメント

コメントする

目次