0

对于 Android 项目,我必须实时分析相机帧。现在我使用“android.hardware.Camera.PreviewCallback”来接收相机帧。问题是,当我尝试分析帧时,我的 FPS 从 30 fps 下降到 15 fps,而我需要 30 fps。我已经尝试在单独的线程中处理分析部分,帧停止下降,但分析不再是实时的。

有人有解决这个问题的方法吗?

4

4 回答 4

1

可能的选项:

  • 降低分辨率
  • 优化您的算法(或使用其他算法)
  • 在c中分析你的帧
  • 如果可能的话,使用着色器或者渲染脚本
  • 多于 2 个线程也可能有所帮助。(取决于硬件)

请记住,那里有很多慢速设备。帧率还取决于光照情况。因此,如果您想发布您的应用程序,请确保您的应用程序也能够支持较低的帧速率。

于 2016-05-26T07:02:41.943 回答
0

正如@oberflansch 所提到的,可能有多种方法可以解决您的问题。

如果您必须进行 YUV 到 RGB 的转换,这并不便宜,以及其他分析,RenderScript 可能是您的出路。它具有快速的YuvToRGB 转换内在特性,并且可能为您的分析带来巨大的性能提升。

这是一个使用带有相机的 RenderScript 的示例:https ://github.com/googlesamples/android-HdrViewfinder

您也可以尝试像上面的示例一样在 YUV 空间中进行分析,这将帮助您摆脱 YUVtoRGB 转换的成本。

但是如果你需要在 RGB 空间中进行,ScriptIntrinsicYuvToRGB 使用起来很简单:

    // Setup the Allocations and ScriptIntrinsicYuvToRGB.
    // Make sure you reuse them to avoid overhead.
    Type.Builder yuvTypeBuilder = new Type.Builder(rs, Element.YUV(rs));
    yuvTypeBuilder.setX(dimX).setY(dimX).setYuvFormat(ImageFormat.YUV_420_888);
    // USAGE_IO_INPUT is used with Camera API to get the image buffer
    // from camera stream without any copy. Detailed usage please
    // refer to the example.
    mInputAllocation = Allocation.createTyped(rs, yuvTypeBuilder.create(),
            Allocation.USAGE_IO_INPUT | Allocation.USAGE_SCRIPT);

    Type.Builder rgbTypeBuilder = new Type.Builder(rs, Element.RGBA_8888(rs));
    rgbTypeBuilder.setX(dimX).setY(dimY);
    // USAGE_IO_OUTPUT can be used with Surface API to display the
    // image to the surface without any copy.
    // You can remove it if you don't need to display the image.
    mOutputAllocation = Allocation.createTyped(rs, rgbTypeBuilder.create(),
            Allocation.USAGE_IO_OUTPUT | Allocation.USAGE_SCRIPT);

    ScriptIntrinsicYuvToRGB yuvToRgb = ScriptIntrinsicYuvToRGB.create(rs, Element.RGBA_8888(rs));

    .........

    // Each time on a new frame available, do the process.
    // Please refer to the example for details.
    mInputAllocation.ioReceive();
    // YUV to RGB conversion
    yuvToRgb.setInput(mInputAllocation);
    yuvToRgb.forEach(mOutputAllocation);

    // Do the analysis on the RGB data, using mOutputAllocation.
    ..........
于 2016-05-26T20:04:17.073 回答
0

因为我必须分析 RGB 和 HSV 值,所以我不能使用@Settembrini 提到的解决方案。为了解决我的问题,我使用 Android NDK 在 C 中创建了一个函数。C 函数处理分析并返回结果。即使在速度较慢的设备上,我也能达到我需要的 30 FPS。在大多数情况下,@Miao Wang 的解决方案可能会成立。

对于 Android Studio 用户:

  • 从 SDK 工具安装 NDK(文件 > 首选项 > 外观和行为 > 系统设置 > Android SDK(SDK 工具选项卡)
  • 创建一个名为“jni”的子目录,并将所有原生资源都放在这里。
  • 创建一个“Android.mk”来向 NDK 构建系统描述您的原生资源。
  • 通过运行项目目录中的“ndk-build”(在 NDK 安装目录中)脚本来构建您的本机代码。构建工具将应用程序所需的已剥离共享库复制到应用程序项目目录中的适当位置。

在您的活动中集成本机方法:

// loading native c module/lib
static {
    try {
        System.loadLibrary("rgbhsvc");
    } catch (UnsatisfiedLinkError ule) {
        Log.e(DEBUG_TAG, "WARNING: Could not load native library: " + ule.getMessage());
    }
}
//Create native void to calculate the RGB HSV
private native void YUVtoRBGHSV(double[] rgb_hsv, byte[] yuv, int width, int height);

创建 C 部分来处理数据:

JNIEXPORT
void
JNICALL Java_nl_example_project_classes_Camera_YUVtoRBGHSV(JNIEnv * env, jobject obj, jdoubleArray rgb_hsv, jbyteArray yuv420sp, jint width, jint height)
{

// process data

(*env)->SetDoubleArrayRegion(env, rgb_hsv, 0, sz, ( jdouble * ) &rgbData[0] );

   //Release the array data
(*env)->ReleaseByteArrayElements(env, yuv420sp, yuv, JNI_ABORT);

}

Android NDK 的一个很好的介绍:https ://www.sitepoint.com/using-c-and-c-code-in-an-android-app-with-the-ndk/

感谢所有的答案!

于 2016-05-31T09:27:27.737 回答
0

除了上面所说的,如果你的图像分析可以单独使用灰度信息,你不需要任何初始转换为 RGB。如果您的分辨率为 n 乘以 m 像素,则只需从 YUV 数据中获取前 (n*m) 个字节。对于旧相机和 Camera2 都是如此。

于 2016-05-29T15:08:20.717 回答