Warning: Undefined variable $position in /home/pystyles/pystyle.info/public_html/wp/wp-content/themes/lionblog/functions.php on line 4897

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

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 は画像から特定の色を抽出したい場合に便利です。

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)


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))