葉の検出

葉は緑色をしている。緑色だけを検出するようにすれば、葉を検出できるようになる。写真は一般に RGB 色空間で記録されている。RGB 空間において、緑色は G の値で指定できるが、青みのかかった緑や黄色みのかかった緑などでは、R や B の値も調整する必要がある。このため、RGB 空間において、緑色を検出するには R, B, G の 3 パラメーターを調整することになり、効率が悪い。

これに対して、HSV 色空間であれば、色の種類(赤・緑・青など)は H という 1 つの値で決まる。また、同様に L*a*b* 色空間において、緑色は a という 1 つの値で決まる。そのため、緑色の検出は HSV 色空間あるいは L*a*b* 色空間で行った方が有効と思われる。

以下に OpenCV を利用して、圃場に植えられたダイズを検出するサンプルを示す。処理前の写真を以下に示す。

OpenCVによる植物個体検出(処理前)

HSV 空間を利用した植物個体の検出

HSV 色空間は、RGB 色空間から変換できる。HSV 色空間の H の値は、色の種類(赤、緑、青など)を表している。S と V は鮮やかさや明るさを表していて、色の種類に影響を与えない。そのため、HSV 色空間を利用して緑を検出する場合は、H の値だけに着目すればいい。一般に H は 0 ≤ H ≤ 360 範囲内の値を取り、50 ≤ H ≤ 150 の範囲において緑色となる。

従って、プログラムで 50 ≤ H ≤ 150 をフィルターとして用いれば緑色を検出できるようになる。OpenCV では H の値域を 0 ≤ H ≤ 179 と定義している。そのため、緑色は 50/360*179 ≤ H ≤ 150/360*179 の範囲内となる。OpenCV ではこれをフィルターとして利用することで、植物個体を検出することができる。検出精度を上げるには、H の値を少し広めたりする調整が必要かもしれない。

import cv2
import numpy as np

img_in = 'beans_field.jpg'

# load image and change the color spaces
img = cv2.imread(img_in)

# change BGR to HSV
# H: 0-179, S: 0-255, V: 0-255
img_HSV = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

# smoothing
img_HSV = cv2.GaussianBlur(img_HSV, (5, 5), 3)

# split photo into 3 channels (H, S, V)
img_H, img_S, img_V = cv2.split(img_HSV)

# binary transformation (only use H channnel)
_thre, img_H1 = cv2.threshold(img_H, 50 / 360 * 179, 255, cv2.THRESH_BINARY_INV)
_thre, img_H2 = cv2.threshold(img_H, 150 / 360 * 179, 255, cv2.THRESH_BINARY_INV)
img_greenarea = 255 - (img_H2 - img_H1)

# save
cv2.imwrite('output.beans_field.HSV.jpg', img_greenarea)
HSV色空間を利用したOpenCVによる植物個体検出(処理前)

L*a*b* 空間を利用した植物個体の検出

L*a*b* 色空間において、L は色の明るさ、a は赤色と緑色の色合い、b は黄色と青色の色合いをそれぞれ表している。そのため、L*a*b* 色空間も、HSV 色空間と同様に、緑色を支配しているパラメーターは 1 つだけであるので、緑色の検出に有効と考えられる。

a がマイナスの大きな値をとると緑みが強くなり、プラスの大きな値をとると赤みが強くなり、0 の場合は無彩色となる。そのため、a < 0 と指定すれば、緑色の領域を検出できるようになる。OpenCV では、a の取りうる範囲を 0 ≤ a ≤ 255 と定義している。そのため、無彩色は 127.5 近くになる。OpenCV を使って、植物個体検出を行う際に、a ≤ 127.5 とすればよい。個体検出精度を上げるには、a の範囲を少し調整する必要があるかもしれない。

import cv2
import numpy as np

img_in = './data/beans_field.jpg'

# load image and change the color spaces
img = cv2.imread(img_in)

# change BGR to L*a*b*
# L: 0-255, a:0-255, b:0-255
img_Lab = cv2.cvtColor(img, cv2.COLOR_BGR2Lab)

# smoothing
img_Lab = cv2.GaussianBlur(img_Lab, (5, 5), 3)

# split photo into 3 channels (L, a, b)
img_L, img_a, img_b = cv2.split(img_Lab)

# binary transformation (only use a channel)
_thre, img_greenarea = cv2.threshold(img_a, 125, 255, cv2.THRESH_BINARY)

# save
cv2.imwrite('output.beans_field.Lab.jpg', img_greenarea)
HSV色空間を利用したOpenCVによる植物個体検出(処理前)