cnf*_*cnf 8 ffmpeg imagemagick
我的最终目标是从 30 分钟或 1 小时长的视频中获取有意义的快照。“有意义”有点野心,所以我简化了我的要求。
图像应该清晰 - 不模糊。
最初,我认为这意味着获得“关键帧”。由于关键帧很多,我决定选择最接近视频第三分钟的关键帧,这对我来说通常“有意义”。我遵循了以下建议:FFmpeg 命令找到最接近第 3 分钟的关键帧
但问题是这些关键帧通常(并不总是)模糊。一个例子是:

然后我尝试使用 FFmpeg 为视频制作有意义的缩略图,这确实有助于获得更有意义的快照,但我仍然经常(并非总是)得到像上面这样的模糊帧。
您会注意到这种图像本质上是 2 个不同场景的重叠。然而,有时我会得到对我有用的图像 - 像这样:

上图意义不大,但很清晰。
理想情况下,我希望 FFmpeg 不返回模糊帧。或者,我想使用脚本来检测模糊帧并从 5 帧中选择最不模糊的帧。有谁知道如何做到这一点?
小智 7
“有意义”是相当主观的,但“模糊”是相当客观且易于检测的。
我有一个类似的问题,经过一些研究,最终得到了以下算法:
使用 ffmpeg 和场景变化检测生成 10 个 png 缩略图,例如:
ffmpeg -ss {$skip} -i {$input} -vf "select=gt(scene\,0.3)" -r 1 -frames:v 1 {$output}
Run Code Online (Sandbox Code Playgroud)在每次迭代$skip中,视频长度以秒为单位增加 10%。参数 0.3 可能不是最适合您,但您可以使用它。这解决了重叠场景和/或完全模糊图像的问题。
使用 ImageMagick 检测这 10 个缩略图的边缘并缩小它们以获得更好的性能:
convert {$input} -thumbnail {$w}x{$h} -colorspace Gray -edge 1 {$path_to_downscaled_image}
Run Code Online (Sandbox Code Playgroud)我正在使用-thumbnail缩放图像。然后我添加了一个黑白滤镜。最后,我使用半径为 1 进行边缘检测。这会生成一个黑白图像,仅将边缘标记为白色。这意味着图像越白,边缘就越多。你会得到这样的东西:

使用 ImageMagick 识别生成的黑白图像:
identify -format '{$format}' {$path_to_downscaled_image}
Run Code Online (Sandbox Code Playgroud)您应该感兴趣的是 %[mean] 和 %[standard-deviation]。和这些人一起玩,看看什么最适合你。例如,只需按“%[mean] + %[standard-deviation]”对所有结果图像进行排序。在我们开始调整大小和过滤它之前找到相同的图像。
最后选择最“前卫”的一个,找到它的原件,然后有选择地再次转换它:
convert {$input} -thumbnail {$w}x{$h} -adaptive-sharpen 1.25x0.75 {$final_output}
Run Code Online (Sandbox Code Playgroud)我发现 -adaptive-sharpen对最终结果确实有帮助,因为它仅在相同边缘周围锐化图像。我尝试了不同的几何图形,发现当我缩小到原始分辨率的四分之一时,1.25x0.75 最适合我。
我已经在 PHP 中完成了这项工作,执行一部 12 分钟的电影大约需要 25 秒,这对我来说很好。
我希望这可以帮到你。