Linux:如何从视频中提取帧?(无损)

Linux:如何从视频中提取帧?(无损)

我读过一些关于使用VLC、、MPlayer等程序的答案和文章ffmpeg,但我见过的方法都不是“无损”的。它们不会捕捉每一帧。我想从视频中提取每一帧作为图像(100% 质量,我不想丢失任何细节),因此理论上可以拍摄这些图像并重新创建视频文件,而无法分辨出与原始文件的区别(当然,不包括缺少音频)。

如果我可以指定抓取帧的开始和结束时间,则可以获得加分,这样我就不必事先裁剪视频文件。

答案1

您可以将帧提取为 PNG,这是一种无损图片压缩格式。例如,要提取从 5 分钟标记到 10 分钟标记的帧:

ffmpeg -ss 05:00 -i <input> -t 05:00 filename%05d.png

答案2

有几种工具可以从电影文件中提取所有帧:

AVCONV
avconv -i file.avi -f image2 Out%00d.jpg

ffmpeg
ffmpeg -i input.file thumb%04d.png -hide_banner

这也可以导出 BMP,其处理时间比 PNG 或 JPG 少得多。

还有一个名为mov2frame.sh尝试自动化 FFMPEG 提取过程。

播放器
mplayer -ao null -vo png input.file

或者另一个选择:

mplayer -nosound -vo png:z=9 my_file.mp4

甚高频液晶 该媒体播放器显然可以使用其过滤器导出图像集,但除非这是您唯一的用途或您有一个便携版本,否则这似乎很麻烦。

  1. 创建一个文件夹来存储您的帧并复制其路径。对于 Mac OSX/Linux 用户,这必须是完整路径(没有 ~)。

  2. 单击 VLC 中的“工具/首选项”。

  3. 在“显示设置”下,单击“全部”。

  4. 在“视频”下,选择“滤镜”。勾选“场景视频滤镜”。

  5. 展开“滤镜”,选择“场景滤镜”,

  6. 将之前的路径粘贴到“目录路径前缀”中。

  7. 在“录制比例”框中选择要编码的帧比例。1/12 表示每 12 个输出一次,1/1 表示全部导出

  8. 点击“保存”。

  9. 单击“媒体/打开视频”并找到您的视频。耐心地播放整个视频。

  10. 点击工具/首选项。在“显示设置”下,点击“全部”。在“视频”下,选择“过滤器”。取消选中“场景视频过滤器”。点击“保存”。这样 VLC 就不会在您下次播放视频时生成缩略图。链接

第一次运行程序时,管理员权限似乎也存在一些潜在的问题:

sudo vlc [sudo] password for mint16: VLC is not supposed to be run as root. Sorry. If you need to use real-time priorities and/or privileged TCP ports you can use vlc-wrapper (make sure it is Set-UID root and cannot be run by non-trusted users first).

VLC 在提取 BMP 而不是 PNG 时的表现也更好

答案3

当使用 ffmpeg 执行此操作时,我发现我经常需要使用该-vsync 0选项(例如,在处理 DVD 中的某些 VOB 文件时):

ffmpeg -i video.VOB -vsync 0 %06d.bmp

如果您也想设置开始和停止时间,它看起来会像这样:

ffmpeg -i video.VOB -vsync 0 -ss 01:30 -to 01:40 %06d.bmp

答案4

下面是 opencv 中的代码,可以帮助我从视频中提取帧。

import cv2
import os

# Replace 'your_video_file.mp4' with the path to your video file
video_path = 'your_video_file.mp4'

# Create a VideoCapture object
cap = cv2.VideoCapture(video_path)

# Check if the video file is opened successfully
if not cap.isOpened():
    print("Error: Could not open video file.")
    exit()

# Create a directory to store the frames
output_directory = 'frames'
os.makedirs(output_directory, exist_ok=True)

# Loop to read frames from the video
frame_count = 0
while True:
    # Read a frame from the video
    ret, frame = cap.read()

    # Check if the frame is read successfully
    if not ret:
        print("End of video.")
        break

    # Save the frame as an image file
    frame_filename = os.path.join(output_directory, f'frame_{frame_count:04d}.png')
    cv2.imwrite(frame_filename, frame)

    frame_count += 1

# Release the VideoCapture object
cap.release()

print(f"{frame_count} frames saved in '{output_directory}'.")

相关内容