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

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

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

1 ответ

Решение

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

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.

Другие вопросы по тегам