Используйте ffmpeg для выбора миниатюр

517
Tina J

Это дополнительный вопрос ЗДЕСЬ . Я хочу сэмплировать kкадры из nчисла кадров в данном видео, используя FFMpegего thumbnailфильтр. Существует пост здесь обеспечивая некоторое представление о том, как выбрать значимые кадры. Однако в этом вопросе требовалось выбрать тех, у кого изменения сцены превышают %40пороговое значение. В моем случае все наоборот. Я считаю, что мы должны выбирать кадры с наименьшими изменениями сцены по сравнению с предыдущими (обычно в видео, когда что-то сфокусировано, сцена более стабильна, а камера не двигается).

Как это сделать FFMpeg? Можем ли мы также объединить кадры и выбрать представителей?

0
Хотите команду для фильтра миниатюр? У него только один вариант - размер кластера Gyan 5 лет назад 0
@ Джан да. Начнем с самой команды. Я установил последнюю версию 2018 `N-91407`. Tina J 5 лет назад 0

1 ответ на вопрос

1
Gyan

Основная команда для фильтра миниатюр

ffmpeg -i in.mp4 -vf thumbnail=n=100 -vsync 0 -frame_pts 1 out%d.png 

Это выберет один репрезентативный кадр из каждых 100 кадров.

-vsync 0 сохраняет метки времени источника.

-frame_pts 1кодирует эту временную метку в выходном имени файла. Таким образом, если ваше видео имеет 24 кадра в секунду, а выходное имя файла - out322.png, то этот кадр был взят из отметки времени 322/24= 13.41sвидео.


Это соответствующие функции в фильтре,

Фильтр работает с упакованными 8-битными кадрами RGB пикселей, т.е.

R1G1B1R2G2B2R3G3B3... 

Гистограмма каждого кадра рассчитывается следующим образом:

// update current frame RGB histogram for (j = 0; j < inlink->h; j++) { for (i = 0; i < inlink->w; i++) { hist[0*256 + p[i*3 ]]++; hist[1*256 + p[i*3 + 1]]++; hist[2*256 + p[i*3 + 2]]++; } p += frame->linesize[0]; } 

Для каждого пикселя значения трех элементов массива увеличиваются. Их индексом являются значения цвета (отрегулированные в соответствии с макетом данных, показанным выше) этих компонентов пикселя.

Затем рассчитывается средняя гистограмма кластера.

// average histogram of the N frames for (j = 0; j < FF_ARRAY_ELEMS(avg_hist); j++) { for (i = 0; i < nb_frames; i++) avg_hist[j] += (double)s->frames[i].histogram[j]; avg_hist[j] /= nb_frames; } 

Для каждого значения цвета компонента их количество по всем кадрам усредняется.

Затем выбирается «лучший» кадр,

// find the frame closer to the average using the sum of squared errors for (i = 0; i < nb_frames; i++) { sq_err = frame_sum_square_err(s->frames[i].histogram, avg_hist); if (i == 0 || sq_err < min_sq_err) best_frame_idx = i, min_sq_err = sq_err; } 

где сумма квадратов ошибок выглядит следующим образом

for (i = 0; i < HIST_SIZE; i++) { err = median[i] - (double)hist[i]; sum_sq_err += err*err; } 

HIST_SIZE = 3 x 256 = 768.

Благодарю. Оно работает. Что я действительно хочу, так это если мы можем выбрать больше кадров из периодов, когда камера более стабильна и не движется? (поэтому разница между последовательными кадрами меньше) Tina J 5 лет назад 0
Кстати, как мы можем изменить `out% d`, чтобы увеличивать один за другим, а затем номер кадра вместо того, чтобы показывать только номер кадра? как `out1_69.png, out2_129.png, ...` Tina J 5 лет назад 0
Это либо тот, либо другой, как в настоящее время реализовано. Gyan 5 лет назад 1
у вас есть справка о том, как миниатюра действительно выбирает кадры? Эти гистограммы и еще много чего Tina J 5 лет назад 0
Благодарю. Так что в основном он выбирает лучшее на основе ближайшего к среднему. Tina J 5 лет назад 0

Похожие вопросы