nanoを取り出して、したいこと
次のサイトにならい、各フレームが動画の最初のフレームから何分何秒後のフレームなのかを、PythonのDataFrameに格納してみようと思いました。
if cap.isOpened(): fps = cap.get(cv2.CAP_PROP_FPS) for sec in df['FrameTime']: # fpsと秒から何フレーム目かを計算する cap.set(cv2.CAP_PROP_POS_FRAMES, round(fps * sec))
上記のサイトに書かれている通り、「各フレームが動画の最初のフレームから何分何秒後のフレームなのか」がわかれば、動画のフレームレート数と合わせて、各フレームが動画中の何フレーム目のフレームなのかも、計算で求めることができます。
AttributeError: 'datetime.timedelta' object has no attribute 'nanos'エラーが発生
>>> import json
>>> from google.cloud import videointelligence
>>> from google.oauth2 import service_account
>>> service_account_key_name = "electroncgpvision-8bf54f743c93.json"
>>> info = json.load(open(service_account_key_name))
>>> creds = service_account.Credentials.from_service_account_info(info)
>>> video_client = videointelligence.VideoIntelligenceServiceClient(credentials=creds)
>>> features = [videointelligence.Feature.OBJECT_TRACKING]
>>> path = './olympic.mp4'
>>> import io
>>>
>>> with io.open(path, 'rb') as file:
... input_content = file.read()
...
>>>
>>> operation = video_client.annotate_video(
... request={"features": features, "input_content": input_content}
... )
>>>
>>> timeout = 300
>>> result = operation.result(timeout=timeout)
>>>
>>>
>>> import types
>>> print(type(result))
<class 'google.cloud.videointelligence_v1.types.video_intelligence.AnnotateVideoResponse'>
>>>
>>> for object_annotation in object_annotations:
... for frame in object_annotation.frames:
... box = frame.normalized_bounding_box
... result_table.append([
... object_annotation.entity.description,
... object_annotation.confidence,
... object_annotation.segment.start_time_offset.seconds + object_annotation.segment.start_time_offset.nanos / 1e9,
... object_annotation.segment.end_time_offset.seconds + object_annotation.segment.end_time_offset.nanos / 1e9,
... frame.time_offset.seconds + frame.time_offset.nanos / 1e9,
... box.left,
... box.top,
... box.right,
... box.bottom,
... [box.left, box.top, box.right, box.bottom],
... object_annotation.entity.entity_id
... ])
...
Traceback (most recent call last):
File "<stdin>", line 7, in <module>
AttributeError: 'datetime.timedelta' object has no attribute 'nanos'
>>>
>>> start_time_offset_listp = [object.segment.start_time_offset for object in object_list]
>>> start_time_offset_list = [object.segment.start_time_offset for object in object_list]
>>> len(start_time_offset_list)
1143
>>>
>>> start_time_offset_list[0:2]
[datetime.timedelta(0), datetime.timedelta(seconds=1, microseconds=201200)]
>>>
>>> print(start_time_offset_list[0:2])
[datetime.timedelta(0), datetime.timedelta(seconds=1, microseconds=201200)]
>>>
>>> start_time_seconds_list = [object.segment.start_time_offset.seconds for object in object_list]
>>> len(start_time_seconds_list)
1143
>>> print(start_time_seconds_list[0:2])
[0, 1]
>>>
>>> print(start_time_seconds_list[0:10])
[0, 1, 2, 4, 5, 7, 7, 7, 7, 7]
>>>
>>> start_time_nanos_list = [object.segment.start_time_offset.nanos for object in object_list]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <listcomp>
AttributeError: 'datetime.timedelta' object has no attribute 'nanos'
>>>
>>> start_time_offset_list = [object.segment.start_time_offset for object in object_list]
>>> print(start_time_offset_list[0])
0:00:00
>>>
>>> print(start_time_offset_list[0].seconds)
0
>>>
>>> print(start_time_offset_list[0].nanos)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'datetime.timedelta' object has no attribute 'nanos'
>>>
nanoを取り出して、したいこと
次のサイトにならい、各フレームが動画の最初のフレームから何分何秒後のフレームなのかを、PythonのDataFrameに格納してみようと思いました。
if cap.isOpened(): fps = cap.get(cv2.CAP_PROP_FPS) for sec in df['FrameTime']: # fpsと秒から何フレーム目かを計算する cap.set(cv2.CAP_PROP_POS_FRAMES, round(fps * sec))
上記のサイトに書かれている通り、「各フレームが動画の最初のフレームから何分何秒後のフレームなのか」がわかれば、動画のフレームレート数と合わせて、各フレームが動画中の何フレーム目のフレームなのかも、計算で求めることができます。
動画のフレーム数は、Pythonで出力できます。
# fps fps = video.get(cv2.CAP_PROP_FPS)
先ほどのサイトでは、以下の部分でfpsを取得しています。
fps = cap.get(cv2.CAP_PROP_FPS)
その上で、先ほどのサイトでは、以下の最後の行の次の部分で「あるフレームが動画内で何フレーム目に位置するフレームなのか」を計算しています。
round(fps * sec)
あるフレームが、動画の最初から数えて1,000sec経過後に登場するシーン(フレーム)であり、この動画が、15fps(1秒間に15フレーム表示される)のとき、「あるフレーム」は、動画の最初から数えて、1,000*15 = 15,000フレーム目に位置する計算になります。
そして、cap.set()メソッドで、「あるフレーム」に「現在のフレーム位置」を移動させて、OpenCV2を使って、目的のフレーム画像を取得しています。
if cap.isOpened(): fps = cap.get(cv2.CAP_PROP_FPS) for sec in df['FrameTime']: # fpsと秒から何フレーム目かを計算する cap.set(cv2.CAP_PROP_POS_FRAMES, round(fps * sec))
cap.set()メソッドの仕様は、次の通りです。
- 第一引数: 「フレームの現在位置」を指すcv2.CAP_PROP_POS_FRAMESを指定する。
- 第二引数: 動画の最初から数えたフレーム数を渡す。
その結果、「フレームの現在位置」が、「あるフレーム」になるよう、位置指定が行われます。
print(cap.set(cv2.CAP_PROP_POS_FRAMES, 100))
このCAP_PROP_POS_FRAMESは動画の現在位置を表すプロパティ。後述。
解決策を探索中
以下のサイトを見て、解決策を模索中です。
- https://living-sun.com/ja/python/733171-how-to-create-a-pandastimestamp-from-datetimedatetime-object-and-nanoseconds-value-python-datetime-pandas-timestamp.html
- https://qiita.com/KMiura95/items/fb50d3afa37b57ef9346
- https://qapicks.com/question/64383923-75880e0e5a4c
- https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.to_timedelta.html
計算を伴わない以下もエラー
エラー
>>> for object_annotation in object_annotations:
... for frame in object_annotation.frames:
... box = frame.normalized_bounding_box
... result_table.append([
... object_annotation.entity.description,
... object_annotation.confidence,
... object_annotation.segment.start_time_offset.seconds,
... object_annotation.segment.start_time_offset.nanos,
... object_annotation.segment.end_time_offset.seconds,
... object_annotation.segment.end_time_offset.nanos,
... frame.time_offset.seconds,
... frame.time_offset.nanos,
... box.left,
... box.top,
... box.right,
... box.bottom,
... [box.left, box.top, box.right, box.bottom],
... object_annotation.entity.entity_id
... ])
...
Traceback (most recent call last):
File "<stdin>", line 8, in <module>
AttributeError: 'datetime.timedelta' object has no attribute 'nanos'
>>>
エラー
>>> tmp = [object_annotation.segment.start_time_offset.nanos for object_annotation in object_annotations]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <listcomp>
AttributeError: 'datetime.timedelta' object has no attribute 'nanos'
>>>
エラー
>>> tmp = [float(object_annotation.segment.start_time_offset.nanos) for object_annotation in object_annotations]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <listcomp>
AttributeError: 'datetime.timedelta' object has no attribute 'nanos'
>>>
エラー
>>> tmp = [str(object_annotation.segment.start_time_offset.nanos) for object_annotation in object_annotations]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <listcomp>
AttributeError: 'datetime.timedelta' object has no attribute 'nanos'
>>>
エラー
>>> tmp = [int(object_annotation.segment.start_time_offset.nanos) for object_annotation in object_annotations]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <listcomp>
AttributeError: 'datetime.timedelta' object has no attribute 'nanos'
>>>
nanos呼出しがない処理は走る
>>> tmp = [object_annotation.segment.start_time_offset.seconds for object_annotation in object_annotations]
>>> len(tmp)
1142
>>> tmp[0:10]
[0, 1, 2, 4, 5, 7, 7, 7, 7, 7]
>>>