OpenCV の connectedComponentsWithStats
は、2 値画像中のオブジェクトを検出するメソッドである。その戻り値には、オブジェクトの位置、オブジェクトを囲む矩形情報、オブジェクトの面積(ピクセル)や重心などの情報も含まれている。このオブジェクトの位置とオブジェクトの面積を利用することで、小さすぎるオブジェクトあるいは大きすぎるオブジェクトを取り除くことができる。
次の Python スクリプトでは、オブジェクトを除去する remove_objects
関数をまず作ってから、それを呼び出して使う手順を取っている。remove_objects
では、connectedComponentsWithStats を利用してすべてのオブジェクトを検出して、その後、オブジェクトのサイズを利用して lower_size
以上かつ upper_size
以下のオブジェクトだけを残す処理を行なっている。
import cv2
import numpy as np
def remove_objects(img, lower_size=None, upper_size=None):
# find all objects
nlabels, labels, stats, centroids = cv2.connectedComponentsWithStats(img)
sizes = stats[1:, -1]
_img = np.zeros((labels.shape))
# process all objects, label=0 is background, objects are started from 1
for i in range(1, nlabels):
# remove small objects
if (lower_size is not None) and (upper_size is not None):
if lower_size < sizes[i - 1] and sizes[i - 1] < upper_size:
_img[labels == i] = 255
elif (lower_size is not None) and (upper_size is None):
if lower_size < sizes[i - 1]:
_img[labels == i] = 255
elif (lower_size is None) and (upper_size is not None):
if sizes[i - 1] < upper_size:
_img[labels == i] = 255
return _img
if __name__ == '__main__':
img = cv2.imread('chirsuta_1_w1024.jpg')
# change color space
img_Lab = cv2.cvtColor(img, cv2.COLOR_BGR2Lab)
# smoothing
img_Lab = cv2.GaussianBlur(img_Lab, (5, 5), 3)
img_L, img_a, img_b = cv2.split(img_Lab)
# binary transformation
_thre, img_greenarea = cv2.threshold(img_a, 120, 255, cv2.THRESH_BINARY_INV)
# remove very-large and very-small objects
img_greenarea_clean = remove_objects(img_greenarea, lower_size=2500, upper_size=None)
# save
cv2.imwrite('output.beans_field.cleanobj.before.jpg', img_greenarea)
cv2.imwrite('output.beans_field.cleanobj.after.jpg', img_greenarea_clean)
実際に、入力した画像、2 値化直後の画像、および 2500 ピクセル以下のオブジェクトを除去した画像は以下のようになっている。