将遥测数据添加到视频[python]

将遥测数据添加到视频[python],python,opencv,video,ffmpeg,moviepy,Python,Opencv,Video,Ffmpeg,Moviepy,我有一个数据帧,其中一列有到图像的路径,另一列有速度 id Cam4 speed roll 0 /cam4/0.jpg 6.178000 1.7 1 /cam4/1.jpg 9.910790 2.3 2 /cam4/2.jpg 17.286564 3.6 3 /cam4/3.jpg 19.000000 5.8 4 /cam4/4.jpg 19.000000 9.3 我想用图像

我有一个数据帧,其中一列有到图像的路径,另一列有速度

id   Cam4          speed        roll
0   /cam4/0.jpg    6.178000     1.7
1   /cam4/1.jpg    9.910790     2.3
2   /cam4/2.jpg    17.286564    3.6
3   /cam4/3.jpg    19.000000    5.8
4   /cam4/4.jpg    19.000000    9.3
我想用图像创建视频,在这样做的过程中,我还想动态地将遥测数据显示为覆盖

创建视频不是问题,这段python代码帮助我做到这一点

import ffmpeg
import pandas as pd

# List of JPEG files
jpeg_files = df.Cam4.to_list()

# Concatinating images to create video
process = ffmpeg.input('pipe:', r='20', f='jpeg_pipe').output('/tmp/video.mp4', vcodec='libx264').overwrite_output().run_async(pipe_stdin=True)

for in_file in jpeg_files:
    with open(in_file, 'rb') as f:
        jpeg_data = f.read()
        process.stdin.write(jpeg_data)

process.stdin.close()
process.wait()

问题是,随着帧的变化,我希望遥测数据显示为帧上的覆盖。这就是我不知道该怎么做的。有人能帮忙吗。

似乎最好的选择是使用OpenCV读取图像,在图像上绘制数据,然后将图像作为原始视频帧写入FFmpeg

FFmpeg支持覆盖过滤器,您可以使用该过滤器将图像放置在其他图像上,但使用管道很难使用覆盖过滤器,因为它需要两个输入流。
将两个输入流与管道一起使用需要使用“命名管道”-解决方案将非常复杂

我建议如下:

  • 读取第一幅图像以获得视频大小(分辨率)
  • rawvideo
    输入格式配置FFmpeg。
    使用原始视频时,我们还需要配置视频大小和像素格式。
    视频大小为cols x rows。
    像素格式为bgr24(匹配OpenCV像素格式)
  • 迭代JPEG文件列表。
  • 使用OpenCV读取图像文件
    图像是一个具有形状(行、列、3)的NumPy数组
  • 在图像上绘制数据。
    代码示例绘制文件名。
    (绘制漂亮的遥测数据超出了我的回答范围)
  • 将图像(连同数据)写入FFmpeg子进程的标准管道

以下是完整的代码示例:

import ffmpeg
import cv2
#import pandas as pd

# Build 10 synthetic images for testing: im001.jpg, im002.jpg, im003.jpg...
################################################################################
ffmpeg.input('testsrc=duration=10:size=192x108:rate=1', f='lavfi').output('im%03d.jpg').run()
################################################################################

# List of JPEG files
#jpeg_files = df.zed2.to_list()

# List of 10 images for testing
jpeg_files = ['im001.jpg', 'im002.jpg', 'im003.jpg', 'im004.jpg', 'im005.jpg', 'im006.jpg', 'im007.jpg', 'im008.jpg', 'im009.jpg', 'im010.jpg']

# Read the first image - just for getting the resolution.
img = cv2.imread(jpeg_files[0])

rows, cols = img.shape[0], img.shape[1]

# Concatenating images to create video - set input format to raw video
# Set the input pixel format to bgr24, and the video size to cols x rows
process = ffmpeg.input('pipe:', framerate='20', f='rawvideo', pixel_format='bgr24', s=f'{cols}x{rows}')\
                .output('/tmp/video.mp4', vcodec='libx264', crf='17', pix_fmt='yuv420p')\
                .overwrite_output().run_async(pipe_stdin=True)

for in_file in jpeg_files:
    img = cv2.imread(in_file)  # Read image using OpenCV

    # Draw something (for testing)
    img[(rows-30)//2:(rows+30)//2, 10:-10, :] = 60
    cv2.putText(img, str(in_file), (cols//2-80, rows//2+10), cv2.FONT_HERSHEY_PLAIN, 2, (255, 30, 30), 2)

    # Display image (for testing)
    cv2.imshow('img', img)
    cv2.waitKey(100)

    # Write raw video frame to stdin pipe of FFmpeg sub-process.
    process.stdin.write(img.tobytes())

process.stdin.close()
process.wait()
cv2.destroyAllWindows()

  • 代码示例首先创建10个JPEG图像-用于测试代码
  • 样本显示用于测试的图像
视频帧示例:

请参阅。谢谢@Rotem。这很有帮助。你必须知道我可以用来在视频中渲染地图的库吗。就像这个一样,我有经度和纬度数据。不客气,我没有任何计算机图形学的经验,也不能推荐任何渲染库。