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

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

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

多くのプログラミング言語におけるDateTimeオブジェクトは、日付と時間に関する演算と出力を行います。

OpenCV

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

Python 3.x

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

pandas

Pandasは、PythonでRにおけるデータフレームに似た型を持たせることができるライブラリです。 行列計算の負担が大幅に軽減されるため、Rで行っていた集計作業をPythonでも比較的簡単に行えます。 データ構造を変更したりデータ分析したりするときにも便利です。

Q&A

解決済

1回答

250閲覧

動画像からリストの中にある指定の時間にフレームを切り出して保存したい(Python)

syosinsya8

総合スコア5

DateTime

多くのプログラミング言語におけるDateTimeオブジェクトは、日付と時間に関する演算と出力を行います。

OpenCV

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

Python 3.x

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

pandas

Pandasは、PythonでRにおけるデータフレームに似た型を持たせることができるライブラリです。 行列計算の負担が大幅に軽減されるため、Rで行っていた集計作業をPythonでも比較的簡単に行えます。 データ構造を変更したりデータ分析したりするときにも便利です。

0グッド

0クリップ

投稿2024/04/12 07:23

編集2024/04/14 14:39

実現したいこと

動画像をリストの中にある指定の時間にフレームを切り出して保存したいです。リストには時間が入っており、その時間に合わせてフレームを切り出して保存したいのですがリストの小数関連?のエラーの対処がよく分からないです。動画はおよそ30秒ほどでリストは5744行の時間のデータが入っています。また、小数点以下の時刻も守ってフレームを切り出して保存したいです。

リストには以下のように計算されたデータが入っています。
0 2.088480
1 2.092519
2 2.096480
3 2.100537
4 2.108488
...

```time_listの中身 #time_listの作成 #time_list= pd.to_datetime(UNIX TIME)で計算されたデータ #0 days 00:00:02.088479997 この時のtime_listの中身のデータ,一部他の行は省略 from datetime import timedelta time_list=time_list/timedelta(seconds=1)#1秒を基準 print(time_list) print(type(time_list)) #実行結果 0 2.088480 1 2.092519 2 2.096480 3 2.100537 4 2.108488 ... 5739 34.027863 5740 34.035860 5741 34.039846 5742 34.043850 5743 34.047793 Name: time_list Length: 5744, dtype: float64 <class 'pandas.core.series.Series'> #0から5743は行数ですリストの中には入っていません #0days 00:00 などが邪魔だったため消しました、ここまではエラーは出ていません。 #変更したプログラム import cv2 import os def save_frame_range_sec(video_path, dir_path, basename, ext='jpg'): cap = cv2.VideoCapture(video_path) if not cap.isOpened(): return os.makedirs(dir_path, exist_ok=True) base_path = os.path.join(dir_path, basename) digit = len(str(int(cap.get(cv2.CAP_PROP_FRAME_COUNT)))) fps = cap.get(cv2.CAP_PROP_FPS) fps_inv = 1 / fps for sec in time_list: n = round(fps * sec) cap.set(cv2.CAP_PROP_POS_FRAMES, n) ret, frame = cap.read() if ret: cv2.imwrite( '{}_{}_{:.9f}.{}'.format( base_path, str(n).zfill(digit), n * fps_inv, ext ), frame ) else: return save_frame_range_sec('動画のパス', '保存先のパス', 'sample_img')

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

エラー文
TypeError Traceback (most recent call last)
<ipython-input-3-fbffaa21dda2> in <cell line: 32>()
30 return
31
---> 32 save_frame_range_sec('動画のパス',
33 '保存先のファイルのパス', 'sample_img')

<ipython-input-3-fbffaa21dda2> in save_frame_range_sec(video_path, dir_path, basename, ext)
17
18 for sec in time_list:
---> 19 n = round(fps * sec)
20 cap.set(cv2.CAP_PROP_POS_FRAMES, n)
21 ret, frame = cap.read()

TypeError: type Timedelta doesn't define round method

補足

google colaboratoryで実行しました。
動画とファイルのパスに問題はなかったです。

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

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

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

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

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

TakaiY

2024/04/12 07:42

> while文をずっとループしています とありますが、なぜそうと思ったのですか。 結果としてどのような動作をしているのでしょうか。
syosinsya8

2024/04/12 08:04

google colaboratoryにどこの行を実行しているか表示されるのでwhileの中の処理に時間がかかっていると思いました。 実行はできますが実行時間が長すぎてgoogle colaboratoryのランタイム接続が切れてしまいます。
poto568

2024/04/12 08:22

とりあえず1件とか10件とかで試してみれば全体の時間が 予想できるんじゃないですかね
can110

2024/04/12 08:32 編集

whileの終了条件、およびそのためにどのような処理、コードを書いたのか? についての説明を追記ください。
melian

2024/04/12 08:58

sec が更新されていないので無限ループですね。
melian

2024/04/14 13:23

print(time_list/timedelta(seconds=1))#1秒を基準 としているので、time_list の中身は timedelta 型のままです。なので、 time_list = time_list/timedelta(seconds=1) とするか、 time_list = time_list.dt.total_seconds() とする必要があります。
syosinsya8

2024/04/14 15:04

コメントありがとうございます。修正を行いプログラムは正しく実行されたのですが、動画から切り取る時間が小数点第3位以降の数値が反映されず全て0になってしますのですがどうすれば良いでしょうか。 例time_list が2.0884811の時、切り取った画像の時間が2.10になっている
melian

2024/04/14 15:39

おそらく、動画の fps が 30 程度なのかもしれません。 n = round(fps * sec) => round(30 * 2.0884811) == 63 n * fps_inv => print(f'{63.0 * ( 1.0 / 30.0 ):.9f}') 2.100000000
syosinsya8

2024/04/14 15:54

わかりました。ありがとうございます。 やりたいことはできたため、質問は以上となります。 皆様、ありがとうございました。
guest

回答1

0

ベストアンサー

まず、質問のコードですが、以下の核心部分の処理がおかしいので、質問の通りwhileを抜けません。

python

1 while sec < stop_sec: 2 n = round(fps * sec) 3 cap.set(cv2.CAP_PROP_POS_FRAMES, n) 4 ret, frame = cap.read() # ★ 設定したフレームを取得 5 if ret: # ★ retが空でなければ書き出す。 6 cv2.imwrite( 省略 ) 7 else: # ★ retが空なら処理終了 8 return 9 for i in time_list: # ★ 終了なのでここは絶対に実行されない。 10 sec = time_list[i]#time_listは切り取りたい時間のリスト # ★ しかも sec の値を変えているだけ。

このwhileループが終了するには、secの値をリストの内容で順に変更して、対応するフレームがなくなる必要があるのですが、そのsecの値を変える処理が間違えているし、しかも、そこを通るようにすらなっていません。

想定どおりに動くかどうかはわかりませんが、以下のように変えてみてはどうでしょうか。

python

1 for sec in time_list: 2 n = round(fps * sec) 3 cap.set(cv2.CAP_PROP_POS_FRAMES, n) 4 ret, frame = cap.read() 5 if ret: 6 cv2.imwrite( 省略 ) 7 else: 8 return 9` `` 10 11このようなループの回しかたは、pythonの基本ですので、初心者向けの書籍でpythonの文法などについて勉強することをお勧めします。

投稿2024/04/12 09:05

TakaiY

総合スコア12774

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

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

syosinsya8

2024/04/13 08:15 編集

回答ありがとうございます。以下のように修正を行い、試してみましたが解決できませんでした。 import cv2 import os def save_frame_range_sec(video_path, dir_path, basename, ext='jpg'): cap = cv2.VideoCapture(video_path) if not cap.isOpened(): return os.makedirs(dir_path, exist_ok=True) base_path = os.path.join(dir_path, basename) digit = len(str(int(cap.get(cv2.CAP_PROP_FRAME_COUNT)))) fps = cap.get(cv2.CAP_PROP_FPS) fps_inv = 1 / fps for sec in time_list: n = round(fps * sec) cap.set(cv2.CAP_PROP_POS_FRAMES, n) ret, frame = cap.read() if ret: cv2.imwrite( '{}_{}_{:.9f}.{}'.format( base_path, str(n).zfill(digit), n * fps_inv, ext ), frame ) else: 以下略 コードを修正したのですが TypeError: type Timedelta doesn't define __round__ method と表示されます。 動画からミリ秒単位で切り抜きを行いたいのですがどのように修正すれば良いでしょうか。 また、time_listは修正を行いました print(type(time_list)) 結果: Length: 5744, dtype: float64 中身 0 2.088480 1 2.092519 2 2.096480 3 2.100537 4 2.108488 ... 5739 34.027863 5740 34.035860 5741 34.039846 5742 34.043850 5743 34.047793 0~5743は行です。
TakaiY

2024/04/13 14:57

ここに書いてもインデントが保存されないのでコードが読めません(特にpythonは) 質問は編集できるので、そちらに追記してください。 また、エラーメッセージは最後の行だけでなく、 Traceback から始まる全てを記載してください。エラーの発生した場所などの重要な情報が含まれています。
syosinsya8

2024/04/14 15:55

ありがとうございました。
syosinsya8

2024/04/14 16:02

一番回答が早かったためベストアンサーに選ばさせていただきました。 皆様、ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.47%

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

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

質問する

関連した質問