OpenCVで赤色のボールを検出

昔作ったOpenCVでのボール認識を微調整しました。赤色のボールを複数認識させています。正確にはボール認識ではなく、色のみを認識する単純なプログラムです。

赤いボールに緑の丸を付ける

映像の中に赤いボールを見つけらたら、緑の丸を付けるようにします。

一定の面積以上の赤色を見つけたら、その周囲に緑色の円を描くという、単純な処理です。

赤色を見つける際、映像によっては茶色やベージュなどの赤みを含むものを誤認するかもしれません。その場合は認識させたい赤の色相、彩度、明度の範囲を調整します。

環境・バージョン

Windows10
Python 3.6.4
OpenCV3.4.0

赤色ボールの検出コード

最小半径30px以上のすべての赤色(ボール)に、緑色の輪郭を描画します。

赤色はH(色相)が分断されているため、例えば「0~10または170~180」という条件になります。

赤色の判定は、コードが少し複雑になります。

赤色抽出の確認

コード64行目を、cv2.imshow(‘video’,res_red)と変えることで、赤色が抽出された映像を確認できます。

ちょうど良いHSVを探ってください。

やはり、この方法では正確にボールの位置を検出するような使い方には向いていません。

おおざっぱに検出して楽しむ(?)時の、参考になればと思います。

“OpenCVで赤色のボールを検出” への5件の返信

  1. 質問します。
    Raspberry Pi4のPicameraを使用して動画を撮影して、撮影しながら赤色かつボールだけを取得したいと思っています。
    参考させていただきながら作ってみましたがうまくいきません教えていただきたいですお願いします。
    いかにソースコードを示します。
    import numpy as np
    import cv2
    import time

    cap = cv2.VideoCapture(0)

    while(1):
    re, frame = cap.read()
    original = frame.copy()
    def getMask(l, u):
    # HSV変換
    image = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
    # 指定した色の下限
    lower = np.array(l)#([0, 208, 94], dtype=”uint8″)
    # 指定した色の上限
    upper = np.array(u)#([179, 255, 232], dtype=”uint8″)
    # 指定した色の画素を 255、それ以外の画素を0として2値化を行う関数
    mask = cv2.inRange(image, lower, upper)
    return mask

    def getContours(mask):
    # 輪郭抽出
    cnts = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    # バージョンに応じて輪郭抽出する
    cnts = cnts[0] if len(cnts) == 2 else cnts[1]
    if len(cnts) > 0:
    # 等高線を反復処理し、頂点の数でフィルタリングする
    for c in cnts:
    # 周囲長
    perimeter = cv2.arcLength(c, True)
    # 輪郭の近似
    approx = cv2.approxPolyDP(c, 0.04 * perimeter, True)
    if len(approx) > 6:
    umbrella=cv2.drawContours(original, [c], -1, (36, 255, 12), -1)
    return umbrella
    else:
    return original
    mask = getMask([-20 ,100, 94], [180, 255, 232])
    cv2.imshow(‘mask’, mask)
    cv2.imshow(‘original’, original)
    umbrella_frame = getContours(mask)

    cv2.imshow(‘umbrellaCnt’, umbrella_frame)

    key = cv2.waitKey(1) & 0xFF
    if key == ord(‘c’):
    cv2.imwrite(‘mask.png’, mask)
    cv2.imwrite(‘original.png’, original)
    elif key == ord(‘q’):
    break

    cv2.destroyAllWindows()

    1. 頂いたコードを貼り付けて実行してみると、カメラ映像から赤色の物体がなくなったときにエラーで止まりました。
      症状は同じでしょうか?
      問題を特定できていませんが、私のコードの不備かもしれません。

      1. 回答ありがとうございます。
        同じく赤い物体がなくなるとエラーになります
        その原因はなぜでしょうか?
        リアルタイムで取得することがよろしくない?

        1. リアルタイムは関係なさそうでした。
          28行目のif len(cnts) > 0:で、輪郭抽出できるものが0個の時(else:)の処理がないことが原因のようです。
          37行目の後に、
          else:
          return original

          を追加すると、いかがでしょうか?

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)