tensorflow 如何利用ffmpeg从视频流中提取关键帧并只打印这些帧中的标签?

7ivaypg9  于 2022-11-16  发布在  其他
关注(0)|答案(2)|浏览(143)

我在一个项目中使用了TensorFlow对象检测API,我修改了visualization_utils文件,将所有当前的类标签打印到终端,然后将它们写入.txt文件。我想知道是否有一个函数,我可以在FFmpeg中使用,使它只打印和写入视频中的关键帧的类标签?当视频中有变化时。此时,即使没有变化,它也会打印每帧的所有类标签,因此即使视频中没有新对象,我也会有重复的标签编号。接下来,我是否必须事先对输入视频应用此关键帧过滤?
提前感谢!
我使用opencv 2来捕获视频输入。
请参阅以下代码:
visualization_utils.py -在draw_bounding_box_on_image_array函数中:

# Write video output to file for evaluation.

  f = open("ObjDecOutput.txt", "a")
  print(display_str_list[0])
  f.write(display_str_list[0])
rta7y2nd

rta7y2nd1#

我想我应该跟进这个问题,我最终使用ffmpeg mpdecimate和setpts过滤器来删除重复和相似的帧。

ffmpeg -i example.mp4 -vf mpdecimate=frac=1,setpts=N/FRAME_RATE/TB  example_decimated.mp4

然而,这并没有解决我正在写入标签的文件中的重复问题--为了解决这个问题,我将文件中的每一行附加到一个列表中,并在其中循环以删除重复元素组,只保留第一个出现的元素,并将其附加到一个新列表中。

oxalkeyp

oxalkeyp2#

最后,我在一年后找到了解决方案here。然而,从这个脚本转换的代码中有一个小bug。
修复程序为and frame["key_frame"]

import json
import subprocess

def get_frames_metadata(file):
    command = '"{ffexec}" -show_frames -print_format json "{filename}"'.format(ffexec='ffprobe', filename=file)
    response_json = subprocess.check_output(command, shell=True, stderr=None)
    frames = json.loads(response_json)["frames"]
    frames_metadata, frames_type, frames_type_bool = [], [], []
    for frame in frames:
        if frame["media_type"] == "video":
            video_frame = json.dumps(dict(frame), indent=4)
            frames_metadata.append(video_frame)
            frames_type.append(frame["pict_type"])
            if frame["pict_type"] == "I" and frame["key_frame"]:
                frames_type_bool.append(True)
            else:
                frames_type_bool.append(False)
#     print(frames_type)
    return frames_metadata, frames_type, frames_type_bool

帧类型存储在frames_type中,但不要相信它。真正的关键帧存储在frames_type_bool中。我测试了一个剪辑,开始时有两个连续的I帧,但avidemux只显示了一个。因此我检查了原始代码,发现一些帧可能有pict_type = I,但有key_frame = False。因此我修复了代码。
拥有frames_type_bool之后,您可以提取True索引和opencvimageio,以便仅提取关键帧。
以下是如何使用此函数和imageio来显示关键帧:

import matplotlib.pyplot as plt
import imageio

filename = 'Clip.mp4'

# extract frame types
_,_, isKeyFrame = get_frames_metadata(filename)

# keep keyframes indices
keyframes_index = [i for i,b in enumerate(isKeyFrame) if b]

# open file
vid = imageio.get_reader(filename,  'ffmpeg')

for i in keyframes_index:
    image = vid.get_data(i)
    fig = plt.figure()
    fig.suptitle('image #{}'.format(i), fontsize=20)
    plt.imshow(image)
plt.show()

相关问题