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

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

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

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

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Arduino

Arduinoは、AVRマイコン、単純なI/O(入出力)ポートを備えた基板、C言語を元としたArduinoのプログラム言語と、それを実装した統合開発環境から構成されたシステムです。

Q&A

解決済

1回答

1271閲覧

arduinoについたセンサーと、pythonで動かすカメラを時間を使って同期を取りたい

kakakatokyoeki

総合スコア85

OpenCV

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

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Arduino

Arduinoは、AVRマイコン、単純なI/O(入出力)ポートを備えた基板、C言語を元としたArduinoのプログラム言語と、それを実装した統合開発環境から構成されたシステムです。

0グッド

1クリップ

投稿2023/03/29 09:29

編集2023/03/30 08:55

python

1コード1 2# -*- coding: utf-8 -*- 3""" 4Created on Tue Mar 28 18:05:27 2023 5 6@author: kawashima 7""" 8 9# -*- coding: utf-8 -*- 10""" 11Created on Mon Mar 27 19:18:37 2023 12 13@author: kawashima 14""" 15import os 16os.environ["OPENCV_VIDEOIO_MSMF_ENABLE_HW_TRANSFORMS"] = "0" 17import cv2 18import time 19import serial 20import csv 21 22# Arduinoのポート名 23ser = serial.Serial('COM3', 9600) 24 25# データを保存するためのリスト 26data = [] 27 28# 録画時間(秒) 29record_time = 360 30# カメラの設定 31cap1 = cv2.VideoCapture(0) 32cap2 = cv2.VideoCapture(1) 33cap1.set(cv2.CAP_PROP_FPS, 30) 34cap2.set(cv2.CAP_PROP_FPS, 30) 35 36# 動画保存の設定 37fourcc = cv2.VideoWriter_fourcc(*'XVID') 38out1 = cv2.VideoWriter('output1.avi', fourcc, 30.0, (640, 480)) 39out2 = cv2.VideoWriter('output2.avi', fourcc, 30.0, (640, 480)) 40 41# 録画フラグの初期化 42recording = False 43 44# 録画開始時間の初期化 45start_time = None 46 47while True: 48 # フレームの取得 49 ret1, frame1 = cap1.read() 50 ret2, frame2 = cap2.read() 51 52 # キー入力の取得 53 key = cv2.waitKey(1) 54 55 # sキーが押された場合の処理 56 if key == ord('s'): 57 recording = True 58 start_time = time.time() 59 print("Recording started") 60 # プログラム開始時刻を保存 61 # 録画中の場合の処理 62 if recording: 63 # 動画にフレームを追加 64 out1.write(frame1) 65 out2.write(frame2) 66 # Arduinoからデータを受信 67 line = ser.readline().decode().strip() 68 print(line) 69 # 受信したデータをカンマで分割 70 x, y, z, timestamp = line.split(',') 71 72 # プログラム開始時刻からの経過時間を計算 73 elapsed_time = time.time() - start_time 74 75 # データを保存 76 data.append([elapsed_time, x, y, z]) 77   **# 現在のタイムスタンプを取得し、リストに追加する** 78 timestamp = time.time() 79 timestamps.append(timestamp) 80 # 指定した録画時間が経過した場合の処理 81 if elapsed_time > record_time: 82 recording = False 83 print("Recording stopped") 84 break 85 86 # 画面表示 87 cv2.imshow('camera1', frame1) 88 cv2.imshow('camera2', frame2) 89 90 # qキーが押された場合の処理 91 if key == ord('q'): 92 break 93# データをCSVファイルに出力 94with open('acceleration_data.csv', mode='w', newline='') as f: 95 writer = csv.writer(f) 96 writer.writerow(['Time (s)', 'Acceleration X', 'Acceleration Y', 'Acceleration Z']) 97 writer.writerows(data) 98 99ser.close() 100 101# 終了処理 102cap1.release() 103cap2.release() 104out1.release() 105out2.release() 106cv2.destroyAllWindows()

python

1コード2 2import cv2 3 4# 動画ファイルのパス 5video_path = 'output2.avi' 6 7# 動画ファイルを開く 8cap = cv2.VideoCapture(video_path) 9 10# 動画のフレーム数を取得 11frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) 12 13# 動画のFPSを取得 14fps = cap.get(cv2.CAP_PROP_FPS) 15 16# 動画の長さ(秒)を計算 17video_length_sec = frame_count / fps 18 19# 結果を表示 20print(f'動画のフレーム数: {frame_count}') 21print(f'動画のFPS: {fps}') 22print(f'動画の長さ: {video_length_sec:.2f}秒') 23 24# メモリを開放して終了 25cap.release() 26cv2.destroyAllWindows()

arduino

1void setup() { 2 Serial.begin(9600); 3} 4 5void loop() { 6 uint8_t i; 7 long x=0; 8 long y=0; 9 long z=0; 10 long t=0; 11 for (i=0;i< 100;i++){ 12 x=x+analogRead(0); 13 y=y+analogRead(1); 14 z=z+analogRead(2); 15 16 } 17 x=x/100; 18 y=y/100; 19 z=z/100; 20 t=millis(); 21 22 Serial.print(x); 23 Serial.print(","); 24 Serial.print(y); 25 Serial.print(","); 26 Serial.print(z); 27 Serial.print(","); 28 Serial.print(t); // タイムスタンプ 29 Serial.print('\n'); 30 delay(20); 31} 32

コードの説明

コード1
arduinoから送られてきたセンサーの値と時間のセットを拾いながら録画をするものです。
arduinoとwebカメラ二台をusbでつなげています。
コード2
動画のフレーム数、fps、長さ、を調べるものです
コード3
arduinoに書かれているプログラムです

発生している問題・エラーメッセージ

1.録画した動画が、倍速になることがあります。

2.arduinoから最後に出された時間とカメラの録画時間が一緒になりません。
arduinoの時間はrecord_timeとほぼ同じになりますが、撮影した動画の長さはrecord_timeよりも短くなります。record_timeを20に設定すると13秒、400に設定すると243秒程度の動画になります。

 

試したこと

1.一様プログラム2を使って調べてみましたが、プロパティと同じです。
2.record_timeを400にしたとき、タイムスタンプをプログラム1の77行目のように追加しました。すると398秒でした。398秒撮影して243秒の動画を7311フレームで構成しています。
400秒程度撮影して400秒程度の動画を12000フレームで構成してもらう必要があります。

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

やがては動画をフレームに分割し、一枚一枚の画像に分割したものを解析し、センサーのデータと時間を用いて照らし合わせる予定です。
動画での時間とarduinoからのtimestampが合わないと(実験の性質上誤差0.05秒程度で)、困ります。

追加で行った実験

python

1# -*- coding: utf-8 -*- 2""" 3Created on Mon Mar 27 19:18:37 2023 4 5@author: kawashima 6""" 7import os 8os.environ["OPENCV_VIDEOIO_MSMF_ENABLE_HW_TRANSFORMS"] = "0" 9import cv2 10import time 11 12# 録画時間(秒) 13record_time = 360 14# カメラの設定 15cap1 = cv2.VideoCapture(0) 16cap2 = cv2.VideoCapture(1) 17cap1.set(cv2.CAP_PROP_FPS, 30) 18cap2.set(cv2.CAP_PROP_FPS, 30) 19 20# 動画保存の設定 21fourcc = cv2.VideoWriter_fourcc(*'XVID') 22out1 = cv2.VideoWriter('output1.avi', fourcc, 30.0, (640, 480)) 23out2 = cv2.VideoWriter('output2.avi', fourcc, 30.0, (640, 480)) 24 25# 録画フラグの初期化 26recording = False 27 28# 録画開始時間の初期化 29start_time = None 30 31while True: 32 # フレームの取得 33 ret1, frame1 = cap1.read() 34 ret2, frame2 = cap2.read() 35 36 # キー入力の取得 37 key = cv2.waitKey(1) 38 39 # sキーが押された場合の処理 40 if key == ord('s'): 41 recording = True 42 start_time = time.time() 43 print("Recording started") 44 45 # 録画中の場合の処理 46 if recording: 47 # 動画にフレームを追加 48 out1.write(frame1) 49 out2.write(frame2) 50 51 # 指定した録画時間が経過した場合の処理 52 if time.time() - start_time > record_time: 53 recording = False 54 print("Recording stopped") 55 break 56 57 # 画面表示 58 cv2.imshow('camera1', frame1) 59 cv2.imshow('camera2', frame2) 60 61 # qキーが押された場合の処理 62 if key == ord('q'): 63 break 64 65# 終了処理 66cap1.release() 67cap2.release() 68out1.release() 69out2.release() 70cv2.destroyAllWindows()

動画を撮るシステムだけを残して動かしてみました。
record_time を360にすると
動画のフレーム数: 10800
動画のFPS: 30.0
動画の長さ: 360.00秒
と正常でした。やはり、途中で処理を挟むと負荷がかかりすぎてダメなのでしょうか

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

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

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

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

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

dameo

2023/03/29 11:53

まるで説明不足で調査不足です。同じ環境を持たない人に原因を聞くという状況をよく考えましょう。 万一全く同じモノを持ってる人なら、それが書いてある情報で認識できて、簡単に再現できるように聞かないといけません。 また調査も全部いっぺんにリアルタイムでやってしまっていては、どれが正しいのかどうか分かりませんよね?1つ1つ正しいことを確認してください。 私は多分以降コメント・回答はしません。
yominet

2023/03/29 14:51

1. カメラを1つだけにしても同じ結果になるか? 2. 撮影ループにカウンターをいれて、 撮影開始から終了までループが何周したか(フレーム数)を数えましょう それが期待した値になっているか?
fana

2023/03/30 01:09

e.g. カメラ映像の取得速度が秒間15回であったとして,2秒間取得したフレーム群(:30枚の画像)を用いて「30FPSという設定の動画」を作成したとき,できた動画の再生時間は1秒になる. ……みたいな話をしているのか? (だとしたらどこにも謎は無いわけで)
tmp

2023/03/30 03:19

説明が足りないので、プログラムそのものよりも何故そう書いてしまったかの方に 重点的に頭を働かせてエスパークイズとして挑戦してみようと思いますw シリアルの出力は、周期は1行50ms程度と仮定すると ser.readline()で、処理が待たされ動画データを1/30 (33ms)で記録することができないので フレームが落ちてしまう為、約倍で再生されてしまう。 「倍速でされてしまうこともある」と、あるがそれは、動画撮影を開始するキーを押す前でも シリアルはオープンされているので、その間バッファーに溜まっているので 動画撮影開始は、データ待ちが発生せず通常速度で記録されて、 バッファがなくなった場合に、データ待ちが発生してフレーム落ちが発生して動画後半が 速く再生されてしまう。 この推理が主張と合うか! 1.録画した動画が、倍速になってしまいます。 2.プロパティで見た動画の長さは、record_timeよりも20秒ほど短いです。ですが、センサーから計算した値はほぼrecord_timeと同じでした。 360秒記録で20秒短いで倍速だけだと、倍速だと180秒短くなるのではないかと思うが、タイトルのほうが「なることもある」とあるので 360秒記録で後半が倍速になって20秒ほど短くなるということで 2つの主張とタイトルあわせて辻褄があう! 外れてたらすまん。
tmp

2023/03/30 13:15

arduinoの出力50ms周期あたった!? analogReadが0.1ms × 3 x100=30ms とdelay(20)で50msぐらい? 1/30(33ms)付近にしたとても全く一緒にならないので、12000フレームも記録するのだったら同期させる処理をいれないとずれていきますね。 1フレームに1データを考えているんですね?
kakakatokyoeki

2023/03/30 23:54

ありがとうございます。ワンフレームにワンデーターである必要は無いです。 動画、arduinoの始まりの時間と終わりの時間さえ一緒であればそれぞれのデータ取得の間隔が違っていても構いません。時間を横軸にしたグラフを作りたいだけなので。  ただ、それぞれ毎秒20から30回データは取りたいです。
dameo

2023/03/31 04:49

以下の情報は普通言われなくても付けてください。 ■環境について 調査対象はPCですか?スペックを詳細に記述してください 調査対象のOSは何ですか? 調査対象のPythonのバージョンは何ですか? 調査対象のPythonでpipなどで明示的にインストールしているパッケージとそのバージョンは何ですか? arduinoを動かしている基盤は何ですか? arduinoのバージョンは何ですか? カメラの型番は何ですか? ■動作確認について カメラはそれぞれ単品でリアルタイム全フレーム(所定の時間でほぼバッファリングせずに)キャプチャできている確認は済んでいますか? arduinoは9660bpsで確実に所定の時間でほぼバッファリングせずに通信できている確認は済んでいますか? カメラ2台でリアルタイム全フレーム(所定の時間でほぼバッファリングせずに)キャプチャできている確認は済んでいますか? カメラ2台+arduinoでリアルタイム全フレーム(所定の時間でほぼバッファリングせずに)キャプチャしつつ、シリアル通信できている確認は済んでいますか? ※調査対象の高精度タイマを用いて、目標時間以内に処理が終わっていることの確認ができているかという意味 ■システム要件について 何をしたいシステムなのか明確にしてください。その際以下も必ず入れてください。 - arduinoを使っている意味は何ですか? - カメラでやりたいことは何ですか? ■発生している問題について 行ったこととその結果が足りていません。グラフに出来るくらい測定した上で、現象を言葉で明快に説明してください。 ■tmpさんの考察について シリアル処理が足を引っ張っている可能性は高いですね。 (単一スレッドでバッファリング前提の処理であるため)受信待ちしてる間にフレームを落とすという意味なので、一言で言えば9600bpsを変えて測定する必要があるということ。 ただし上の書いたことを全部やってからでないと、結果に信憑性がありません。 ■最後に 約2日でてこれしか進まないとか遅すぎです。10倍くらいの速度を目標にやってください。 ※またしばらく見れないかも
tmp

2023/04/01 03:37

もとから別々に記録してるので、平行して記録するプログラムが書けないなら、映像記録とArudinoからのデータ記録をそれぞれ別のソフトにして、それぞれ記録開始時PCの日時などを記録すれば、あとから動画とデータ合わせることが映像とシリアルでの遅延時間の差とかもあるけど、できるのでは?
kakakatokyoeki

2023/04/01 03:52

ありがとうございます。それでコードを作り直すとうまくいきました
guest

回答1

0

自己解決

もとから別々に記録してるので、平行して記録するプログラムが書けないなら、映像記録とArudinoからのデータ記録をそれぞれ別のソフトにして、それぞれ記録開始時PCの日時などを記録すれば、あとから動画とデータ合わせることが映像とシリアルでの遅延時間の差とかもあるけど、できるのでは?

投稿2023/04/01 03:53

kakakatokyoeki

総合スコア85

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問