これは [〜#〜] here [〜#〜] からのフォローアップの質問です。 k
とそのn
フィルターを使用して、特定のビデオのFFMpeg
フレーム数からthumbnail
フレームをサンプリングしたいと思います。投稿があります ここ意味のあるフレームを選択する方法についての洞察を提供します。ただし、その質問では、シーンの変化が%40
しきい値よりも高いものを選択する必要がありました。私の場合、それは反対です。以前のシーンと比較して最も低いシーンの変化があるフレームを選択する必要があると思います(通常、何かに焦点が合っているビデオでは、シーンはより安定していてカメラですあまり動かない)。
FFMpeg
でこれを行う方法は?フレームをクラスター化して代表者を選ぶこともできますか?
サムネイルフィルターの基本的なコマンドは
ffmpeg -i in.mp4 -vf thumbnail=n=100 -vsync 0 -frame_pts 1 out%d.png
これにより、100フレームごとに1つの代表的なフレームが選択されます。
-vsync 0
はソースのタイムスタンプを保持します。
-frame_pts 1
は、そのタイムスタンプを出力ファイル名にエンコードします。したがって、ビデオが24 fpsで、出力ファイル名が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];
}
ピクセルごとに、3つの配列要素の値が増分されます。それらのインデックスは、それらのピクセルコンポーネントのカラー値(上記のデータレイアウトに従って調整)です。
次に、クラスターの平均ヒストグラムが計算されます。
// 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。