Use o ffmpeg para seleções de miniaturas

0

Esta é uma pergunta de acompanhamento de AQUI . Quero amostrar k frames do número n de quadros em um determinado vídeo usando FFMpeg e seu filtro thumbnail . Há uma postagem aqui fornecendo algumas informações sobre como selecionar quadros significativos . No entanto, nessa questão, o requisito era selecionar aqueles com mudanças de cena maiores que %40 threshold. No meu caso, é o oposto. Acredito que devemos escolher quadros com menor alteração de cena em comparação com os anteriores (geralmente em um vídeo quando algo está focado, a cena é mais estável e a câmera não se move muito).

Como fazer isso com FFMpeg ? Podemos também agrupar os quadros e escolher representantes?

    
por Tina J 03.07.2018 / 22:59

1 resposta

1

O comando básico para o filtro de miniaturas é

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

Isso selecionará um quadro representativo de cada 100 quadros.

-vsync 0 preserva os timestamps de origem.

-frame_pts 1 codifica esse registro de data e hora no nome do arquivo de saída. Por isso, se o seu vídeo tiver 24 fps e o nome do ficheiro de saída for out322.png, esse frame foi retirado do timestamp 322/24 = 13.41s do vídeo.

Estas são as funções relevantes no filtro

O filtro funciona com quadros de pixels RGB de 8 bits compactados, ou seja,

R1G1B1R2G2B2R3G3B3...

O histograma de cada quadro é calculado da seguinte forma,

// 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];
}

Para cada pixel, os valores de três elementos da matriz são incrementados. Seu índice é os valores de cor (ajustados conforme o layout de dados mostrado acima) desses componentes de pixel.

Em seguida, o histograma médio de um cluster é calculado.

// 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;
}

Para cada valor de cor do componente, é calculada a média de sua contagem em todos os quadros.

Em seguida, o quadro "melhor" é escolhido,

// 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;
}

em que a soma dos erros quadrados é a seguinte

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

HIST_SIZE = 3 x 256 = 768.

    
por 05.07.2018 / 07:39