画面上で円が動く動画があります。
その円を取得して座標(X,Y)を求めてフレームごとにXとYをプロットした
グラフをアニメーション(リアルタイム)で表示させたいです。
円を取得して、アニメーショングラフを作成してみたのですが
Traceback (most recent call last):
File "C:\Users\User\AppData\Local\Continuum\anaconda3\lib\site-packages\matplotlib\cbook_init_.py", line 216, in process
func(*args, **kwargs)
File "C:\Users\User\AppData\Local\Continuum\anaconda3\lib\site-packages\matplotlib\animation.py", line 953, in _start
self._init_draw()
File "C:\Users\User\AppData\Local\Continuum\anaconda3\lib\site-packages\matplotlib\animation.py", line 1523, in _init_draw
artist.set_visible(False)
AttributeError: 'list' object has no attribute 'set_visible'とエラーがでます。
いろいろ調べてみたのですが改善できません。
どなたかご教授いただけないでしょうか。
追記1)
ims.append(lines)でエラーが出ないようになりました。
ですが、グラフ画面が表示されたまま処理が止まります。
グラフ画面の×ボタンを押すとまたグラフ画面が表示されます。
何回か押しているとグラフの線が画面に表示されてきたので、
×ボタンを押すごとに1フレームごと処理が進んでいるみたいです。
どなたかご教授ください。
追記2)
plt.pauseで処理が止まらなくなりました。
ですが、1フレームごとにグラフが表示されています。
やりたいこととしては下記になります。
1.animation.ArtistAnimation()でims = []を取り込んで?
グラフを表示したままにしてリアルタイムで表示する。
2.ims = []に値を入れるまでの処理を進めて、動画を表示する
追記3)
追記2は解決しました。
cv2.imshow('MotionDetected Area Frame', frame)以下参照
下記のコードを実行すると、
TypeError: 'list' object is not callableとエラー出ます。
im= plt.plot(lengh, circle_x)が1フレーム目では問題ないですが、
2フレーム目にこのエラーが表示されます。
どなたかご教授ください。
import cv2 import time from matplotlib import pyplot as plt import matplotlib.animation as animation import numpy as np # 動画ファイルを読み込みclassオブジェクトに入れる cap = cv2.VideoCapture(ファイルパス) cap_fps = cap.get(cv2.CAP_PROP_FPS) fig = plt.figure() # Figureを作成 ims = [] lines = [] xmax = 2500 xmin = 0 ymax = 300 ymin = 200 mean_box = [] circle_x = [] circle_y = [] circle_r = [] # <cap:class>のget関数の引数で取得する数値を決定する。(この場合総フレーム数) frame_count = cap.get(cv2.CAP_PROP_FRAME_COUNT) # timeクラスのタイム関数((注)動画ファイルの実時間ではなく、プログラムの実行時間として使用) # 後でfpsの確認とかにも使う start = time.time() # フレームカウント用 i = 0 # 無限ループ def calc_mean(sig, center, radius): # 計算対象の領域は255, それ以外の領域は0としたマスク画像を作成する。 mask = np.zeros_like(sig) # すべての画素が0の画像 cv2.circle(mask, center, radius, color=255, thickness=-1) # 円を描画 # cv2.imshow("sss",mask) cv2.imwrite("mask.png", mask) # デバッグ用 # AND 演算 roi = cv2.bitwise_and(sig, mask) # cv2.imshow("sss", roi) cv2.imwrite("roi.png", roi) # デバッグ用 # 輝度値の平均を計算する。 n_pixels = (mask == 255).sum() # 計算対象の領域の画素数 # mean = roi[roi < 150].sum() / n_pixels # 平均輝度値 mean = roi.sum() / n_pixels # 平均輝度値 return mean while True: start2 = time.time() jikan2 = time.time() - start2 # 画像を順番にを取り込む(第二返り値が各フレーム) ret, frame = cap.read() # フレームカウント i += 1 # cap.read()の返り値がなかった場合、処理を中止 if frame is None: print(i, 'break') break # 三次元配列で格納されたBGRをGrayScaleに変換して二次元配列とする # 例[[[100,100,100][105,120,140]...]] ⇒ [[100,120...]] # ((注)Opencvにおいて一般的なRGBの並びではなくBGRで読み込まれる) # ####グレースケール画像に変換 #### S gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # ####グレースケール画像に変換 #### E # #### 円の位置をある程度推定する #### frame = frame[50:480, 50:640] dst = gray[50:480, 50:640] # cv2.imshow("triming", dst) # 閾値の設定 threshold = 40 # 二値化(閾値100を超えた画素を255にする。) ret, nck = cv2.threshold(dst, threshold, 255, cv2.THRESH_BINARY) # 経過時間 jikan = time.time() - start # 現在の経過時間 # fps # if jikan is 0.0: if jikan < 0.001: # fps = frame_no / jikan # frame per seconds cv2.putText(frame, "例外", (10, 50), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0), 1, cv2.LINE_AA) else: circles = cv2.HoughCircles(nck, cv2.HOUGH_GRADIENT, dp=2, minDist=0.07, param1=1520, param2=10, minRadius=74, maxRadius=77) print(circles, "iii") if circles is None: cv2.putText(dst, "false2", (10, 50), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0), 1, cv2.LINE_AA) else: circles = np.uint16(np.around(circles)) circles = circles.squeeze(axis=0) # (1, NumCircles, 3) -> (NumCircles, 3) for cx, cy, r in circles: # 輝度値最小の円を取得する mean = calc_mean(nck, center=(cx, cy), radius=r) # print(mean) mean_box.append(round(mean, 5)) min_idx = np.argmin(mean_box) # 輝度値が最小の要素のインデックスを取得 cx, cy, r = circles[min_idx] # 対応する円を取得 # 輝度値最小の円を取得する # draw the outer circle frame = cv2.circle(frame, (cx, cy), r, (0, 255, 0), 2) # draw the center of the circle frame = cv2.circle(frame, (cx, cy), 2, (0, 0, 255), 3) # print(circles) circle_x.append(cx) circle_y.append(cy) circle_r.append(r) mean_box.clear() cv2.imshow('MotionDetected Area Frame', frame) if i==1: lengh = range(0, len(circle_x), 1) im= plt.plot(lengh, circle_x) lines.extend(im) ims.append(lines) ani = animation.FuncAnimation(fig, ims, interval=1) else: plt.cla() lengh = range(0, len(circle_x), 1) im= plt.plot(lengh, circle_x) lines.extend(im) ims.append(lines) plt.xlim(xmin, xmax) plt.ylim(ymin, ymax) # ani.save("plot2.gif", writer='imagemagick') # ani.save('anim.mp4', writer="ffmpeg") plt.pause(0.001) k = cv2.waitKey(1) if k == 27: break cap.release() cv2.destroyAllWindows()
あなたの回答
tips
プレビュー