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

问题描述

我有一个数据框,其中一列有图像路径,另一列有速度。

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 文件列表。
    1. 使用 OpenCV 读取图像文件
      图像是一个形状为 (row,cols,3) 的 NumPy 数组。
    2. 在图像上绘制数据。
      代码示例绘制文件名。
      (绘制漂亮的遥测数据超出了我的回答范围)。
    3. 将图像(带有数据)写入 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 图像 - 用于测试代码。
  • 示例显示用于测试的图像。

示例视频帧:
enter image description here

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...