6

Моя конечная цель - получить значимые снимки из видеороликов продолжительностью 30 минут или 1 час. "Значимое" немного амбициозно, поэтому я упростил свои требования.

Изображение должно быть четким, а не размытым.

Первоначально я думал, что это означает получение "ключевого кадра". Поскольку существует много ключевых кадров, я решил выбрать ключевой кадр, ближайший к третьей минуте видео, что для меня было достаточно "значимым". Я следовал совету по адресу: команда FFmpeg, чтобы найти ключевой кадр, ближайший к 3-й минуте

Но проблема в том, что эти ключевые кадры часто (не всегда) размыты. Примером является:

Затем я попробовал « Значимые миниатюры для видео», используя FFmpeg, что помогло получить более значимые снимки, но я все еще часто (не всегда) получал размытые кадры, как указано выше.

Вы заметите, что этот вид изображения, по сути, является перекрытием двух разных сцен. Иногда, однако, я получаю изображения, которые работают для меня - как это:

Изображение выше не очень значимое, но оно четкое.

В идеале я бы хотел, чтобы FFmpeg не возвращал размытые кадры. В качестве альтернативы я хотел бы использовать скрипт для обнаружения размытых кадров и выбора наименее размытых кадров, скажем, из 5 кадров. Кто-нибудь знает как это сделать?

1 ответ1

6

"Значимое" довольно субъективно, но "размытое" довольно объективно и легко обнаружить.

У меня была похожая проблема, и после небольшого исследования я получил следующий алгоритм:

  • Определите длину видеофайла в секундах.
  • Создайте 10 png миниатюр с помощью ffmpeg и определения смены сцены с помощью чего-то вроде:

    ffmpeg -ss {$skip} -i {$input} -vf "select=gt(scene\,0.3)" -r 1 -frames:v 1 {$output}
    

На каждой итерации $skip увеличивается на 10% от длины видео в секундах. Параметр 0.3 может быть не самым подходящим для вас, но вы можете играть с ним. Это решило проблему с перекрывающимися сценами и / или полностью размытыми изображениями.

  • Определите края этих 10 миниатюр и уменьшите их для повышения производительности с помощью ImageMagick:

    convert {$input} -thumbnail {$w}x{$h} -colorspace Gray -edge 1 {$path_to_downscaled_image}
    

Я использую -thumbnail чтобы масштабировать изображение. Затем я добавляю черно-белый фильтр. Наконец я делаю обнаружение края с радиусом 1. Это создает черно-белое изображение только с краями, отмеченными как белый. Это означает, что чем более белое изображение, тем больше краев. Вы получите что-то вроде этого:

  • Определите получившиеся черно-белые изображения с помощью ImageMagick:

    identify -format '{$format}' {$path_to_downscaled_image}
    

Что вас должно заинтересовать, так это% [среднее] и% [стандартное отклонение]. Поиграйте с ними и посмотрите, что вам больше подходит. Просто отсортируйте все полученные изображения, например, по «% [среднее] +% [стандартное отклонение]». Найдите то же изображение, прежде чем мы начнем изменять его размер и фильтровать.

  • Наконец, выберите самый "острый", найдите его оригинал и при необходимости снова конвертируйте:

    convert {$input} -thumbnail {$w}x{$h} -adaptive-sharpen 1.25x0.75 {$final_output}
    

Я обнаружил, что -adaptive-sharpen действительно помогает с конечным результатом, потому что он обостряет изображения только по тем же краям. Я попробовал разные геометрии и обнаружил, что 1,25x0,75 лучше всего подходит для меня, когда я уменьшаю до четверти исходного разрешения.

Я сделал это в PHP, и для выполнения 12-минутного фильма требуется около 25 секунд, что меня устраивает.

Я надеюсь, что это было полезно.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .