Verwenden Sie ffmpeg für die Auswahl von Miniaturansichten

591
Tina J

Dies ist eine Folgefrage von HIER . Ich möchte kFrames aus der nAnzahl der Frames in einem bestimmten Video mit FFMpegseinem thumbnailFilter herausfiltern. Es gibt einen Beitrag , der einige Einblicke in die Auswahl aussagekräftiger Frames bietet . In dieser Frage war es jedoch erforderlich, diejenigen auszuwählen, deren Szenenänderungen höher als der %40Schwellenwert sind. In meinem Fall ist es umgekehrt. Ich glaube, wir sollten Bilder mit dem niedrigsten auswählen Szenenänderungen im Vergleich zu ihren vorherigen (normalerweise in einem Video, wenn etwas scharfgestellt ist, die Szene stabiler ist und die Kamera sich nicht viel bewegt).

Wie mache ich das mit FFMpeg? Können wir auch die Rahmen zusammenfassen und Vertreter auswählen?

0
Möchten Sie einen Befehl für den Miniaturbildfilter? Es gibt nur eine Option - die Clustergröße Gyan vor 5 Jahren 0
@Gyan ja. Beginnen wir mit dem Befehl selbst. Ich habe die neueste Version 2018 'N-91407' installiert. Tina J vor 5 Jahren 0

1 Antwort auf die Frage

1
Gyan

Der grundlegende Befehl für den Miniaturbildfilter lautet

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

Dadurch wird aus 100 Frames ein repräsentativer Frame ausgewählt.

-vsync 0 behält die Quellzeitstempel bei.

-frame_pts 1codiert diesen Zeitstempel im Ausgabedateinamen. Wenn Ihr Video also 24 fps hat und der Ausgabedateiname out322.png ist, wurde der Frame vom Zeitstempel 322/24= 13.41sdes Videos übernommen.


Dies sind die relevanten Funktionen im Filter.

Der Filter arbeitet mit gepackten 8-Bit-RGB-Pixel-Frames

R1G1B1R2G2B2R3G3B3... 

Das Histogramm jedes Frames wird wie folgt berechnet:

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

Für jedes Pixel werden die Werte von drei Feldelementen inkrementiert. Ihr Index sind die Farbwerte (gemäß dem oben gezeigten Datenlayout angepasst) dieser Pixelkomponenten.

Dann wird das durchschnittliche Histogramm eines Clusters berechnet.

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

Für jeden Komponentenfarbwert wird die Anzahl über alle Frames gemittelt.

Dann wird der beste Rahmen gewählt.

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

wobei die Summe der Fehlerquadrate wie folgt ist

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

HIST_SIZE = 3 x 256 = 768.

Vielen Dank. Es klappt. Was ich wirklich will, ist, wenn wir mehr Bilder aus Zeiträumen auswählen können, in denen die Kamera stabiler ist und sich nicht bewegt. (so ist der Unterschied zwischen aufeinanderfolgenden Frames geringer) Tina J vor 5 Jahren 0
Übrigens, wie können wir das 'out% d' so ändern, dass es um eins und dann um die Frame-Nummer erhöht wird, anstatt nur die Frame-Nummer anzuzeigen? wie 'out1_69.png, out2_129.png, ...' Tina J vor 5 Jahren 0
Es ist entweder die eine oder die andere, wie derzeit implementiert. Gyan vor 5 Jahren 1
Haben Sie einen Hinweis darauf, wie Miniaturbilder wirklich Frames auswählen? Das Histogramm und so weiter Tina J vor 5 Jahren 0
Vielen Dank. Im Grunde wählt es das Beste aus, das dem Durchschnitt am nächsten ist. Tina J vor 5 Jahren 0