开发者

教你在Linux中从视频流截取图片帧(ffmpeg)

开发者 https://www.devze.com 2024-09-17 09:56 出处:网络 作者: yfs1024
目录linux依赖说明:1. ffmpeg -i "https://cdn.pixabay.com/video/2023/10/22/186115-877653483_large.mp4"2. -vf "select='not(mod(n,10))'"3. -frames:v 54. -q:
目录
  • linux依赖说明:
    • 1. ffmpeg -i "https://cdn.pixabay.com/video/2023/10/22/186115-877653483_large.mp4"
    • 2. -vf "select='not(mod(n,10))'"
    • 3. -frames:v 5
    • 4. -q:v 1
    • 5. output_%03d.jpg
    • 整体含义:
  • extract_frames.sh
    • detect_sharpness.sh
      • create_directory.sh
        • 总结 

          Linux依赖说明:

          说明: 使用到的 依赖包  
          
          1. ffmpeg
          
          sudo apt update 
          sudo apt-get install ffmpeg
          
          2. imagemagick (选装)
          (检测图像边缘信息推断清晰度,如果是简单截取但个图像帧=>用不到<=)
          
          sudo apt-get install imagemagick
          
          备注: 
          指令及相关参数说明
          
          

          核心指令: (作用: 执行 ffmpeg 命令提取帧,每10帧选择一帧, 一共提取5张)

          示例:

          ffmpeg -i “https://cdn.pixabay.com/video/2023/10/22/186115-877653483_large.mp4” -vf “select=‘not(mod(n,10))’” -frames:v 5 -q:v 1 output_%03d.jpg

          指令说明:

          这条 ffmpeg 命令从视频流中提取帧并保存为图片,具体的参数含义如下:

          1. ffmpeg -i "https://cdn.pixabay.com/video/2023/10/22/186115-877653483_large.mp4"

          • ffmpeg:调用 ffmpeg 命令。
          • -i "https://cdn.pixabay.com/video/2023/10/22/186115-877653483_large.xSWIHmp4":指定输入文件,视频源为给定的网络视频 URL。

          2. -v编程客栈f "select='not(mod(n,10))'"

          • -vf:表示使用视频滤镜。

          • "select='not(mod(n,10))'"
            

            :视频帧选择器,这里

            mod(n,10)
            

            表示每 10 帧提取一次帧。

            n
            

            是当前帧的编号,

            mod(n,10)
            

            计算帧编号除以 10 的余数,

            not(mod(n,10))
            

            选择那些编号是 10 的倍数的帧。

            • 换句话说,这条命令每 10 帧提取一个帧。

          3. -frames:v 5

          • 只提取 5 帧图片。

          4. -q:v 1

          • -q:v 设置视频帧的质量,范围为 1 到 31,值越小质量越高,1 是最高质量。

          5. output_%03d.jpg

          • 输出文件名模板。%03d 是一个占位符,表示文件名中包含 3 位数字(例如 output_001.jpgoutput_002.jpg),这样可以保存多个帧。

          整体含义:

          从视频中每隔 10 帧提取一个帧,总共提取 5 帧,保存为高质量的 JPEG 图片文件,文件名为 output_001.jpgoutput_002.jpg, 以此类推。

          指令执行完可见当前文件夹中文件:

          教你在Linux中从视频流截取图片帧(ffmpeg)

          具体的命令可根据需求情况进行修改, 到这里文章的标题功能就已经实现了.

          下面是加餐环节

          需求: 提取视频中的图片帧, 并从多张中选取最清晰的一张照片

          注: 其中的文件路径需要改为自己所存在的路径

          这里准备了三个脚本文件如下:

          • extract_frames.sh 提取视频帧输出指定张数据照片并存到指定位置 并执行 detect_sharpness.sh 脚本(已注释掉, 需要的话自行打开)
          • detect_sharpness.sh 从多张照片中选择最清晰的一张 并将其余的照片删除, 且保留最清晰一张并重命名
          • create_directory.sh 判断文件夹是否存在, 不存在则创建, 存在则不处理

          extract_frames.sh

          提取视频帧输出指定张数据照片并存到指定位置 并执行 detect_sharpness.sh 脚本

          注: 执行该脚本需要指定—视频路径

          示例:

          /data/hikuser/handler_video_to_picture/extract_frames.sh  https://cdn.pixabay.com/video/2023/10/22/186115-877653483_large.mp4
          
          #!/bin/bash
          
          # 删除指定目录下已有的图片
          rm -f /data/hikuser/handler_video_to_picture/output*.jpg
          
          # 检查是否提供了视频流 URL 参数
          if [ "$#" -ne 1 ]; then
              echo "Usage: ${0##*/} <video_stream_url>"
              exit 1
          fi
          
          # 视频流 URL
          VIDEO_URL="$1"
          
          # 检查输出目录是否存在
          if [ ! -d "/data/hikuser/handler_video_to_picture" ]; then
              echo "Directory /data/hikuser/handler_video_to_picture does not exist."
              exit 1
          fi
          
          # 执行 ffmpeg 命令提取帧,每10帧选择一帧, 一共提取5张
          if ! ffmpeg -i "$VIDEO_URL" -vf "select='not(mod(n,10))'" -frames:v 5 -q:v 1 /data/hikuser/handler_video_to_picture/output_%03d.jpg; then
              echo "ffmpeg command failed."
              exit 1
          fi
          
          # 执行检测图片清晰度的脚本
          # if [ -f /data/hikuser/handler_video_to_picture/detect_sharpness.sh ]; then
          #    /bin/bash /data/hikuser/handler_video_to_picture/detect_sharpness.sh
          # else
          #    echo "detect_sharpness.sh script not found!"
          #    exit 1
          # fi
          
          

          detect_sharpness.sh

          从多张照片中选择像素最高的一张 并将其余的照片删除, 并将最新的一张重命名

          #!/bin/bash
          
          # 初始化最大边缘值和最清晰的图片变量
          max_edge_value=0
          sharpest_image=""
          
          # 进入图片所在目录
          cd /data/hikuser/handler_video_to_picture || exit 1
          
          # 遍历每张图片并计算边缘值
          for img in output_*.jpg; do
              # 计算图片的边缘检测值
              edge_value=$(convert "$img" -edge 1 -format "%[mean]" info:)
              echo "$img 边缘检测值: $edge_value"
              
              # 比较边缘值,保留最大值对应的图片
              if (( $(echo "$edge_value > $max_edge_value" | bc -l) )); then
                  max_edge_value=$edge_value
                  sharpest_image=$img
              fi
          done
          
          # 输出最清晰的图片
          echo "最清晰的图片是: $sharpest_image"
          
          # 删除其他图片
          for img in output_*.jpg; do
              if [ "$img" != "$sharpest_image" ]; then
                  rm "$img"
              fi
          done
          
          # 将最清晰的图片重命名为 output.jpg
          mv "$sharpest_image" /data/hikuser/handler_video_to_picture/output.jpg
          
          echo "已删除其他图片,保留最清晰的图片: $sharpest_image"
          

          脚本执行效果示例:php

          教你在Linux中从视频流截取图片帧(ffmpeg)

          所以截取的图片大小因为数据源是一个静态视频, 当然如果采集帧率过快时也会出现这样的情况, 注意空值

          create_directory.sh

          判断文件夹是否存在存在则创建不存在则不处理

          #!/bin/bash
          
          # 检查是否提供了文件夹名称参数
          if [ "$#" -ne 1 ]; then
              echo "Usage: ${0##*/} <directory_name>"
              exit 1
          fi
          
          # 文件夹名称
          DIR_NAME="$1"
          
          # 检查文件夹是否存在
          if [ -d "$DIR_NAME" ]; then
              echo "Directory '$DIR_NAME' already exists."
          else
              # 创建文件夹
              mkdir -p "$DIR_NAME"
              if [ $? -eq 0 ]; then
                  echo "Directory '$DIR_NAME' has been编程客栈 created."
              else
                  echo "Failed to create directory '$DIR_NAME'."
                  exit 1
              fi
          fi

          总结 

          到此这篇关于在Linux中从视频流截取图片帧(ffmpeg)的文章www.devze.com就介绍到这了,更多相关Linux从视频流截取图片帧内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)!

          0

          精彩评论

          暂无评论...
          验证码 换一张
          取 消