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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Python 3.x

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

Q&A

解決済

1回答

796閲覧

検出した物体の時間計測について

tasuke

総合スコア53

Python 3.x

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

0グッド

0クリップ

投稿2018/11/16 07:11

現在、カメラが円を検出した場合何秒写っていたかを計測するプログラムを作成しています。コードは以下の通りです。

import numpy as np import cv2 import time import csv f = open("cl_save.csv","a") csvWriter = csv.writer(f) cap = cv2.VideoCapture(0) start = None while True: ret, frame = cap.read() if not ret: break gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) gray1 = cv2.GaussianBlur(gray, (5, 5), 1) circles = cv2.HoughCircles(gray1, cv2.HOUGH_GRADIENT, 1, 60, param1=10, param2=85, minRadius=0, maxRadius=85) if circles is not None and start is None: start = time.time() circles = np.uint16(np.around(circles)) for i in circles[0,:]: cv2.circle(frame,(i[0],i[1]),i[2],(0,0,0),2) cv2.circle(frame,(i[0],i[1]),2,(0,0,0),3) if circles is not None and start is not None: circles = np.uint16(np.around(circles)) for i in circles[0,:]: cv2.circle(frame,(i[0],i[1]),i[2],(0,0,0),2) cv2.circle(frame,(i[0],i[1]),2,(0,0,0),3) elif circles is None and start is not None: elapsed_time = time.time() - start print(elapsed_time) listData = [] listData.append(str(elapsed_time)) csvWriter.writerow(listData) start = None cv2.imshow('preview', gray1) key = cv2.waitKey(10) if key == ord("q"): break cv2.destroyAllWindows()

動かしてみたところ、時間を計測するようになったものの、前のフレームで円があったかなかったかでしか評価していないため、個々の円の時間は計測できていませんでした。そこで、円を中心座標により区別し、各座標でフレーム間処理を行えるようにしようと考えました。しかし、あまりプログラムに詳しくなく、どのように上記の内容を実現すればいいかわかりませでした。
OpenCV3にはラベリングパッケージがあることがわかったのですが、以下のサイトを見たところ、私がやろうとしていた検出した円を区別できるようにするためには使えないということがわかりました。
OpenCV3.0kから入ったラベリング処理について
検出した円を中心座標により区別し、各座標でフレーム間処理(時間計測)を行う場合、どのようにすれば検出した円の座標を保存できるのか、また、そもそも私が作成したいプログラムは実現可能なのか教えていただけると助かります。
長文かつわかりづらい文章となってしまい申し訳ありません。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

  • 各円は、一定速度以下で動く
  • 異なる円はそれぞれある程度離れている

という条件であれば可能です。以下、概念コードを示します。
問題を単純化するため、各円は中心位置(点)のみで管理しています。

基本的な考えとしては、領域内に残留している点を保持しておき
現フレームに映っている各点が、新規に侵入 or 残留 した点かを判定しています。
さらに、前フレームに存在したが現フレームに存在しない点を離脱判定しています。

コード書くのに力尽きたので詳細な説明は省きます。

Python

1from datetime import datetime 2import math 3 4FIND_DIST = 10 # 移動前後での同一点とみなす距離(最大移動速度) 5 6# 領域内の点群を保持。ID, 現在も領域内に残留しているか, 現在位置, 侵入日時 を記録 7targets = [] # [{'id':1, 'bIn':True, 'pos':[10,20],'in_time':'2018-11-16 19:51:02.516124'}, ...] 8 9# 領域内に存在する点群の位置を取得 10# Enterキーのみで終了 11def inp_points(): 12 pts = [] 13 while True: # 点の数だけ 14 s = input('領域にある点の位置を入力(10,20など):') 15 pt = s.split(',') 16 if len(pt) < 2: 17 break 18 pts.append( (float(pt[0]), float(pt[1]))) 19 return pts 20 21id = 1 22while True: 23 now_time = datetime.now() 24 25 # 現在、領域内に存在する点群の位置を取得 26 pts = inp_points() 27 if len(pts) <= 0: 28 break # 点群なし -> 全体終了 29 30 # 既存の点群の残留フラグをリセット(存在しない状態に) 31 for tgt in targets: 32 tgt['bIn'] = False 33 34 new_tgts = [] 35 36 # 現在の領域内の点群に対し、残留 or 侵入したか判定 37 for pt in pts: 38 bIn = False 39 for tgt in targets: 40 # 既存の点=残留なら位置を更新 41 if math.sqrt( math.pow(pt[0] - tgt['pos'][0], 2) + math.pow(pt[1] - tgt['pos'][1], 2)) <= FIND_DIST: 42 tgt['bIn'] = True 43 tgt['pos'] = pt 44 bIn = True 45 46 # 既存の点ではない -> 侵入した点として登録 47 if not bIn: 48 new_tgt = {'id':id,'bIn':True,'pos':pt,'in_time':now_time} 49 new_tgts.append(new_tgt) 50 print('侵入:', new_tgt) 51 id += 1 52 53 # 既存の残留点のうち、領域を離脱したものか判定 54 for tgt in targets: 55 if tgt['bIn']: # 残留 56 new_tgts.append(tgt) 57 else: # 離脱 58 print('離脱:',tgt) 59 print('{}sec'.format((now_time - tgt['in_time']).total_seconds())) 60 61 targets = new_tgts 62 print('-----') 63 64# 最後まで領域に残っていた点群 65for tgt in targets: 66 print('残留:',tgt)

実行結果例

PlainText

1領域にある点の位置を入力(10,20など):10,10 2領域にある点の位置を入力(10,20など):10,50 3領域にある点の位置を入力(10,20など): 4侵入: {'in_time': datetime.datetime(2018, 11, 16, 20, 55, 12, 328722), 'pos': (10.0, 10.0), 'id': 1, 'bIn': True} 5侵入: {'in_time': datetime.datetime(2018, 11, 16, 20, 55, 12, 328722), 'pos': (10.0, 50.0), 'id': 2, 'bIn': True} 6----- 7領域にある点の位置を入力(10,20など):15,10 8領域にある点の位置を入力(10,20など):15,50 9領域にある点の位置を入力(10,20など): 10----- 11領域にある点の位置を入力(10,20など):20,10 12領域にある点の位置を入力(10,20など): 13離脱: {'in_time': datetime.datetime(2018, 11, 16, 20, 55, 12, 328722), 'pos': (15.0, 50.0), 'id': 2, 'bIn': False} 1444.393635sec 15----- 16領域にある点の位置を入力(10,20など): 17残留: {'in_time': datetime.datetime(2018, 11, 16, 20, 55, 12, 328722), 'pos': (20.0, 10.0), 'id': 1, 'bIn': True}

投稿2018/11/16 12:09

can110

総合スコア38266

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tasuke

2018/11/19 02:22

サンプルコードまで書いていただいてありがとうございます。私は生物系の学生なのですが、研究室の教授にシステム作成の研究を任されてしまい、急きょプログラミングをやることになり知識も情報もなく大変困っていたところでした。本当にありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問