Android相机在PreviewCallback

时间:2016-05-26 06:39:36

标签: java android memory-management previewcallback

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

有人有解决此问题的方法吗?

4 个答案:

答案 0 :(得分:1)

可能的选择:

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

请记住,那些慢速设备就在那里。 帧率还取决于光线情况。 因此,如果您要发布应用,请确保您的应用也能够支持较低的帧速率。

答案 1 :(得分:0)

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

如果你必须进行YUV到RGB的转换,这不是很便宜,还有其他分析,RenderScript可能是你的出路。它具有快速YuvToRGB conversion intrinsic,可以为您的分析提供巨大的性能提升。

以下是将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.
    ..........

答案 2 :(得分:0)

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

答案 3 :(得分: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安装目录中)脚本来构建本机代码。构建工具将应用程序所需的剥离的共享库复制到应用程序项目目录中的正确位置。

在您的Activity中集成本机方法:

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

感谢所有答案!