对于Android项目,我必须实时分析相机帧。现在我使用'android.hardware.Camera.PreviewCallback'来接收相机帧。问题是,当我尝试分析帧时,我的FPS从30 fps下降到15 fps,而我需要30 fps。我已经尝试在一个单独的线程中处理分析部分,帧停止下降,但分析不再是实时的。
有人有解决此问题的方法吗?
答案 0 :(得分:1)
可能的选择:
请记住,那些慢速设备就在那里。 帧率还取决于光线情况。 因此,如果您要发布应用,请确保您的应用也能够支持较低的帧速率。
答案 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用户:
在您的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/
感谢所有答案!