在 android studio 中从视频中提取所有帧的最快方法?

问题描述

目标:要从视频中提取所有帧,请在机器学习模型中处理这些帧,并从这些处理过的帧中重建新视频。

问题:我目前能够从视频中提取帧,但速度非常慢。大约每秒 2 帧。我想将其加速到至少每秒 10-20 帧。

我使用 android 的原生 MediaMetadataRetriever 类将帧提取Bitmap 并将它们存储在 List

代码如下:

fun getAllFrames(uri: Uri): List<Bitmap> {
    val frameList = ArrayList<Bitmap>()

    setDataSource(context,uri)

    // playback duration (in ms) of the data source.
    val duration: String? = extractMetadata(MetaDATA_KEY_DURATION)
    val durationMillis = duration!!.toInt()
    val durationMicros = durationMillis * 1000

    // to get a video output with 30fps (input can be 60 or 30fps)
    val fps30 = ((1000/30)*1000).toLong()

    for (i in 0L..durationMicros step fps30) {

        val frame = getFrameAtTime(i,OPTION_CLOSEST)

        frame?.let {
           frameList.add(frame)
        }
    }

    return frameList
}

我查看了 ffmpegjavaCV 库,但没有看到一种可以准确有效地提取所有帧的方法(也许我错过了?)。我想要一个getFrameAtTime 这样的方法,而不是在 grabeAllFrames 中使用时间间隔。

谁能给我任何提示如何实现这个目标???

解决方法

您正在处理的几乎所有视频都将以一种或另一种格式进行编码,这些编码格式,例如h.264,通常会压缩视频以节省存储和带宽。

权衡是您需要解压缩视频并获取每一帧,而编解码器(编码器)越“高效”,它通常需要做的工作就越多。

大多数设备都有专用的硬件加速路径来解码和显示常见的视频编码格式,但这些通常针对显示而不是分析和修改视频进行了优化。

如果您可以选择在服务器端完成这项工作,通常会更容易,因为可用的处理能力更强,而且可用的库和服务也可能更广泛。

如果您确实必须在移动设备上工作,那么可能值得查看适用于 Android 的 OpenCV,但需要注意的是,编译可能很棘手,而且文档通常基于 Eclipse。

当然,如果您对每帧的分析不太需要处理器,那么您应该能够达到每秒 2 帧以上的效果。

首先要看的一个很好的简单示例是颜色俱乐部检测,它检测每帧特定颜色的对象或斑点:https://github.com/opencv/opencv/tree/master/samples/android/color-blob-detection/src/org/opencv/samples/colorblobdetect

这个答案提供了一个带注释的摘录来解释它是如何工作的:https://stackoverflow.com/a/40918718/334402

值得补充的是,机器学习用例也可能需要处理器和时间,因此可能是两者的结合导致您的用例放慢速度。