質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.52%

  • Python 3.x

    6319questions

    Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

  • OpenCV

    1068questions

    OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

同色のボールの区別ができません!

受付中

回答 1

投稿

  • 評価
  • クリップ 2
  • VIEW 310
退会済みユーザー

退会済みユーザー

前提・実現したいこと

◎やりたいこととしてはは、検出したボールをひとつひとつ区別して、ボール1・ボール2・ボール3でそれぞれ違う色の円で囲いたいです。
例えば、ボール1なら赤色の円でずっと追いかけ、ボール2なら青色の――といった感じです。

サンプルを組み合わせただけなのでかなり雑ですが、トラックバーで決めた範囲の色のボールを、円で囲って追いかけるというプログラムです。
今私が使用している動画は、緑色のボールを3つ使ってカスケードをしている動画で、トラックバーの初期値はおおよそ緑色を検出する数値になっています。

調べてみたところ、ユークリッド距離というものを利用するらしいことは分かったのですが、式などが難しく、調べれば調べるほど分からなくなってきてしまいました。
サンプルなどを見てみてはいるのですが、どれをどうやって組み込めばいいのかがわかりません。
どうかよろしくお願いします。

該当のソースコード

import cv2
import numpy as np
import math


def colorLow(position):
    global col_l
    col_l = position
def colorUp(position):
    global col_u
    col_u = position
def saturationLow(position):
    global sat_l
    sat_l = position
def saturationUp(position):
    global sat_u
    sat_u = position
def valueLow(position):
    global val_l
    val_l = position
def valueUp(position):
    global val_u
    val_u = position

def extract_hsv(frame,col_l,col_u,sat_l,sat_u,val_l,val_u):

    hsv=cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
    h,s,v=cv2.split(hsv)

    if col_l>col_u:
        ret,h_mask_1=cv2.threshold(h,col_l,255,cv2.THRESH_BINARY)
        ret,h_mask_2=cv2.threshold(h,col_u,255,cv2.THRESH_BINARY_INV)

        mask=cv2.bitwise_or(h_mask_1,h_mask_2)

    else:
        ret,mask=cv2.threshold(h,col_l,255,cv2.THRESH_TOZERO)
        ret,mask=cv2.threshold(mask,col_u,255,cv2.THRESH_TOZERO_INV)

        ret,mask=cv2.threshold(mask,0,255,cv2.THRESH_BINARY)

    ret,sat_mask=cv2.threshold(s,sat_l,255,cv2.THRESH_BINARY)
    ret,val_mask=cv2.threshold(v,val_l,255,cv2.THRESH_BINARY)

    mask=cv2.bitwise_and(mask,sat_mask)
    mask=cv2.bitwise_and(mask,val_mask)

    return mask

if __name__=="__main__":

    col_l=30
    col_u=97
    sat_l= 120
    sat_u= 255
    val_l= 80
    val_u= 255
    cap = cv2.VideoCapture("動画の名前")
    cv2.namedWindow("colorselect",cv2.WINDOW_NORMAL)

    cv2.createTrackbar('color(low)', "colorselect", col_l, 255, colorLow)
    cv2.createTrackbar('Color(up)', "colorselect", col_u, 255, colorUp)
    cv2.createTrackbar('Saturation(low)',"colorselect", sat_l, 255, saturationLow)
    cv2.createTrackbar('Saturation(up)', "colorselect", sat_u, 255, saturationUp)
    cv2.createTrackbar('Value(low)', "colorselect", val_l, 255, valueLow)
    cv2.createTrackbar('Value(up)',"colorselect", val_u, 255, valueUp)

while(1):

    # フレームを取得
    (grabbed,frame) = cap.read()
    if not grabbed:
        cap.set(cv2.CAP_PROP_POS_FRAMES,0)
        continue

    # フレームをHSVに変換
    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

    mask=extract_hsv(frame,col_l,col_u,sat_l,sat_u,val_l,val_u)
    mask=cv2.erode(mask, None, iterations=2)
    mask=cv2.dilate(mask, None, iterations=2)

    # フレーム画像とマスク画像の共通の領域を抽出する。
    img_color = cv2.bitwise_and(frame, frame, mask=mask)

    cnts = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL,
            cv2.CHAIN_APPROX_SIMPLE)[-2]
    center = None


    cnts3 = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL,
            cv2.CHAIN_APPROX_SIMPLE)[-2]
    center = None
    # 少なくとも1つの輪郭が見つかった場合
    if len(cnts) > 0:
            for i, contour in enumerate(cnts):
                #print("{}, {}".format(i, len(contour)))

                # area:面積
                area = cv2.contourArea(contour)
                if area < 100:
                    continue

                # moments:重心
                M = cv2.moments(contour)
                if M["m00"] != 0:
                    cx = int(M["m10"] / M["m00"])
                    cy = int(M["m01"] / M["m00"])
                else:
                    cx, cy = 0, 0
                # 重心を中心にした円
                cv2.circle(frame, (cx, cy), int(math.sqrt(area)), (0,255,0), 2, 8)
              #  pts1.appendleft(center)


    cv2.imshow("SHOW COLOR IMAGE", img_color)
    cv2.imshow("SHOW FRAME", frame)

    # qを押したら終了
    k = cv2.waitKey(50)
    if k == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()

補足情報(言語/FW/ツール等のバージョンなど)

windows7/Anaconda3.4.4/Spyder3(Python3.5)/OpenCV 3.1.0

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

+2

https://www.google.co.jp/amp/s/bipuljain.wordpress.com/2011/12/20/multiple-color-tracking-using-opencv-python/amp/
普通は認識しやすくするために色違いのボールを使います。

そうでないのなら運動方程式を解いて、物理法則に反していないようにラベル付けする必要があるのではないでしょうか?
囲んでいる円の中心を質点として高校物理をノイズありで解くのです。
検出精度が悪いと誤差が出ます。
フレームレートが安定しないと誤差が出ます。
それ許容した範疇で区別します。
ボール同士が近付いたりすると区別がつかなくなります。

どれほど真剣なプロジェクトかはわかりませんが、カルマンフィルタで調べてみるとそれなりに実用的なものができるのではないでしょうか。
これなら奥行き方向の重なりは処理できるかもしれません。
ボール同士が衝突した場合は無理です。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.52%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

  • 解決済

    wxPythonにおいて、USBカメラの画像表示をしたい

    前提・実現したいこと ここ一週間くらい、teratailの皆様の力を借りながら、python上で動く動画や画像を表示できるGUIを作っています。画像は何とか表示でき、画像とパネル

  • 解決済

    フーリエ変換・逆フーリエ変換後に値が振り切って画像に戻せません

    前提・実現したいこと Python+OpenCVで、カラー画像にフーリエ変換を行ってマスク処理をしたいと考えています。昨日からこちらの説明(鳥取大)を参考に、とりあえず動くところま

  • 解決済

    OpenCvSharp3で重心を求めたいです

    以下のように、ラベリングを実行するプログラムはできたのですが、ここから重心の座標や面積を求めるプログラムを作成したいです。どなたか、教えていただけますか? 最終的な目標としては

  • 解決済

    opencv python 画像処理

    # -*- coding: utf-8 -*- import cv2 import numpy as np # フレーム差分の計算 def frame_sub(src1, src

  • 解決済

    ラベリング処理を行いたい

    前提・実現したいこと こんにちは。 https://youtu.be/CBXrsAJOKhQ こちらのテニスシーンの映像においてラベリング処理をBackgroundSubtract

  • 受付中

    検出結果を修正・拡張したいです

    前提・実現したいこと 移動しているボール(ジャグリングなど)を検出して円を描くプログラムです。OpenCVで移動体検出を使ったサンプルをいくつかつなぎ合わせたハリボテプログラムなの

  • 解決済

    Opencvで画像の色を抽出してアルファチャンネル付きで保存したい

    コラージュを作るときのいわゆるBB(ブルーバック?)のような画像で、背景の単色だけを 抜いてその部分を透過させたいです。 画像はBGRです。最終的に入力に対して出力が周りが透過

  • 解決済

    opencvの処理をリアルタイムに

    処理が途中でとまり、 処理後フォルダにaviファイルは保存されるのですが2秒ほどの動画となってしまいます 動画を撮り続けて自分で止めたい場合どのようにすればよいでしょうか アドバイ

同じタグがついた質問を見る

  • Python 3.x

    6319questions

    Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

  • OpenCV

    1068questions

    OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。