22

我想用原始图像进行图像处理而不在屏幕上显示它,这显然会降低性能。

根据这个线程的答案,在没有预览的情况下从相机拍照,这在 Android 1.5 中是不可能的,但有人知道在 Android 4(API 级别 15)中是否可能吗?

4

3 回答 3

47

在 Android 4 中,接收原始图像数据而不将其显示在屏幕上的最简单方法是使用Camera.setPreviewTexture()调用将预览帧路由到 GPU。

您可以通过两种方式使用它:

  1. 在 GPU 上进行实际处理:设置 OpenGL 上下文(OpenGL ES 2 教程),并在该上下文中创建SurfaceTexture对象。然后将该对象传递给 setPreviewTexture,并开始预览。然后,在您的 OpenGL 代码中,您可以调用 SurfaceTexture.updateTexImage,与 SurfaceTexture 关联的纹理 ID 将更新为来自相机的最新预览帧。如果需要,您还可以使用 glReadPixels 将 RGB 纹理数据读回 CPU 进行进一步处理。
  2. 在 CPU 上进行处理:您可以简单地创建一个虚拟 SurfaceTexture 对象,而无需设置任何 OpenGL 上下文。传递您想要的任何整数作为纹理 ID,并使用 setPreviewTexture 将 SurfaceTexture 连接到相机。只要您不调用 updateTexImage,SurfaceTexture 就会简单地丢弃相机传递给它的所有数据。然后使用setPreviewCallback设置预览回调,并使用该数据(通常以 YUV 格式)进行 CPU 处理。这可能比 #1 效率低,但不需要了解 OpenGL。
于 2012-05-27T18:41:50.177 回答
1

因为我不允许评论。关于艾迪的回答。您需要在 NDK 中使用它,因为使用 Java 接口会抵消任何性能优势。从性能的角度来看,必须使用 PixelBuffer 绝对是疯狂的。您从 RGBA888 到 YUV 的转换也需要在 C 中完成。

不要尝试使用 TextureView 会更糟。在转换为 YUV 之前,您必须将像素复制到位图中,然后从位图复制到数组中。这本身就占据了全新 Nexus 7 2013 品牌近 30% 的 CPU 利用率。

最有效的方法是直接与 Camera.h 对话并绕过所有 Android API。您可以创建自己的缓冲区并在 YUV 数据进入其他任何地方之前对其进行拦截。

于 2013-09-30T15:15:59.457 回答
1

在屏幕上显示预览不会对性能产生影响。在我遇到的所有设备上,相机输出都“连接”到不涉及 CPU 的表面或纹理,所有颜色转换和缩放都由专用硬件负责。

“隐藏”预览可能还有其他原因,但请记住,出于隐私和安全原因,API 最初的目的是确保最终用户看到从相机到达应用程序的任何内容。

于 2013-12-20T20:04:04.460 回答