実験1:画像の色検出

下記の黄色のボールを検出します。

In [1]:
from IPython.display import Image
Image(filename='./img/ball.jpg') 
Out[1]:
In [2]:
import cv2
import numpy as np

img = cv2.imread("./img/ball.jpg") # 画像を読み込む。

# 色基準で2値化する。
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

# 色の範囲を指定する
lower_color = np.array([20, 80, 10])
upper_color = np.array([50, 255, 255])

# 指定した色に基づいたマスク画像の生成
mask = cv2.inRange(hsv, lower_color, upper_color)
output = cv2.bitwise_and(hsv, hsv, mask = mask)

結果:

黄色のボールを検出しました。

In [3]:
# 結果のファイルを作成
cv2.imwrite("./img/mask_img.jpg", output)
Image(filename='./img/mask_img.jpg') 
Out[3]:

実験2: 粒子解析 (色を検出し、数を数える)

下記の粒子の画像は黄色、赤色、青色を認識して、粒子を数えます。

In [4]:
image_file='./img/img.jpg'
Image(filename=image_file) 
Out[4]:
In [20]:
import cv2
import matplotlib.pyplot as plt
from matplotlib.patches import Polygon

img = cv2.imread(image_file) # 画像を読み込む。

# 色基準で2値化する。
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

red = cv2.inRange(hsv, np.array([145, 70, 0]), np.array([180, 255, 255]))
yellow = cv2.inRange(hsv, np.array([10, 80, 0]), np.array([50, 255, 255]))
blue = cv2.inRange(hsv, np.array([108, 121, 0]), np.array([120, 255, 255]))

# 白だけゴミがあるので、収縮演算
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))

bin_imgs = {'red': red, 'yellow': yellow, 'blue': blue}

# 2値化結果を可視化する。
fig, axes_list = plt.subplots(3, 1, figsize=(10, 18))

for ax, (label, bin_img) in zip(axes_list.ravel(), bin_imgs.items()):
    ax.axis('off')
    ax.set_title(label)
    ax.imshow(bin_img, cmap=plt.cm.gray)
plt.show()
In [17]:
fig, ax = plt.subplots(figsize=(12,10))
ax.axis('off')
ax.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))

# 輪郭検出し、数を求める。

for label, bin_img in bin_imgs.items():
    _, contours, _ = cv2.findContours(
        bin_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    contours = list(filter(lambda cnt: len(cnt) > 1, contours))
    count = len(contours)

    print('color = {}  conunt: {}'.format(label, count))

    # 描画する。
    for cnt in contours:
        cnt = np.squeeze(cnt, axis=1)  
        ax.add_patch(Polygon(cnt, fill=None, lw=2., color=label))
plt.show()
color = red  conunt: 4
color = yellow  conunt: 112
color = blue  conunt: 0

結果

OpenCVのInRangeとcontoursを利用して、3色の粒子を数えました。