Android:访问硬件相机预览帧数据而不绘制它们

Posted

技术标签:

【中文标题】Android:访问硬件相机预览帧数据而不绘制它们【英文标题】:Android: Accessing hardware camera preview frame data without drawing them 【发布时间】:2012-08-09 02:47:44 【问题描述】:

根据 Java SDK 端的 android 相机文档,必须为相机预览帧提供一个(可见且活动的)表面以进行绘制,以便访问帧数据。我已经链接了我在这里遇到的一些事情(我是新手,所以最多只能有 2 个超链接),但是在结束在 SO 上发布我自己的问题之前,我查阅了大量关于各种事情的文档。

我的问题:

a) 我明确不想将相机预览绘制到屏幕上,我只想尽可能直接从相机缓冲区中获取字节数据(我可以从这里获取)。

b) 是的,我看到了: Taking picture from camera without preview.

但是,这要求使用此库的应用程序必须将此(看似)任意视图插入到其应用程序布局中,该视图必须始终可见(它们不能切换布局、更改父容器的可见性或使用子活动)在应用生命周期中。

事实上,我的需求与this poster's 类似,除了我想要相机预览数据的连续实时流,而不是保存到磁盘上的图像的捕获。因此PictureCallbackmyCamera.takePicture 通话一起为他工作。出于显而易见的原因,将连续捕获写入磁盘不是我的解决方案,因此在我的情况下不起作用。 myCamera.takePicture 也比获取预览帧慢得多。

c) 我已经开始涉足 NDK,并且感觉很好。然而,根据this 的说法,通过本机访问相机数据是不被支持或不推荐的,即便如此,设备兼容性也是一个巨大的麻烦。

如果这已经过时,并且有可靠的 NDK 路由从 android 设备获取相机数据,我找不到它们,所以如果你能指出它们,那就太好了。

d) 我想让这个库可以从 Unity 之类的工具(以统一插件的形式)中访问,我希望能够将它编译成 JAR(或 .so 对于本机)并期待它处理以这种方式导入库的 android 应用程序,这样他们就可以使用相机,而无需应用程序开发人员进行特定的 UI/布局配置。

上下文:

我希望能够创建一个用于 android 应用程序的视觉处理库,并且不想限制使用该库的应用程序必须使用特定的应用程序布局并将特定视图绘制到屏幕上才能使用视觉处理结果 - 举一个非常简单的例子,如果一个应用想要使用我的库来获取相机看到的平均颜色,并且想要在屏幕上为图像着色该颜色。

无论我对我的任何观点提出什么建议,都会非常有帮助。非常感谢您的宝贵时间!

【问题讨论】:

你有解决这个问题的办法吗? 我已添加我的解决方案作为此问题的答案。抱歉,拖了这么久。 【参考方案1】:

我完全忘记了我有这个问题。 2 年和几个 Android SDK 版本之后,我们有了一个工作系统。

我们正在使用扩展的SurfaceTexturecameraSurface 并引用所需的摄像头。使用cameraSurface的SurfaceTexture,我们调用

mCamera.setPreviewTexture(mSurfaceTexture);
mCamera.startPreview();

然后从您的活动或您需要的任何地方覆盖当前活动相机的previewCallback

mCamera.setPreviewCallback(new PreviewCallback() 

     public void onPreviewFrame(final byte[] data, final Camera camera) 
         // Process the contents of byte for whatever you need
     
);

这使您可以连续处理相机看到的内容,而不必只浏览存储的图像。当然,这将受限于您相机的预览分辨率(可能与静态捕捉或视频分辨率不同)。

如果我有时间,我会尝试抛出一个准系统工作演示。

编辑:我链接到的 SDK 不再免费提供。您仍然可以通过BitGym contact page 申请。

【讨论】:

很高兴您找到了解决问题的方法;谢谢分享。让我添加一些对您的用例可能不是必需的提示,但可以对其他人产生影响。首先,如果您使用Camera.setPreviewCallbackWithBuffer(),可以显着减少视频捕获期间的垃圾收集。其次,要将回调从 UI 线程中推送出去,您必须使用 Handler thread。 这不需要opengl和android 5.0(camera api 2)来处理数据吗?如果我需要在其上仅使用相机 api1 进行一些渲染脚本操作怎么办? 从大约 Android API 级别 11 开始工作,即 3.0 (虽然不同的风格有稍微不同的行为)。它确实需要 openGL ES 2,它可用于预冰淇淋三明治设备。 我正在尝试编写一个与您的非常相似的应用程序,但我遇到了同样的问题。您使用 SurfaceTexture 的代码是否仍然可用?我尝试了您提供的链接,但它不再有效。非常感谢看到一个有效的演示,谢谢! Camera2 API 有什么可用的答案吗?【参考方案2】:

使用SurfaceView 进行图像预览是不可能的。您可以做的是将捕获byte[] 的责任委托给实现您的库的应用程序,这将允许他们使用您的库来获取来自相机的图像,以及已经拍摄的图像。

【讨论】:

问题是试图持续进行,而不仅仅是在孤立的时间实例中。把这个责任委派给应用程序真的很麻烦,开发人员最好告诉我们的库“开始处理”/“停止处理”,我们给他们处理的结果,他们可以通过“lastProcessingOutput”或等效的方式访问。这将使其尽可能地拖放,从而仍然为用户提供尽可能多的控制权。如果我们希望它们能够处理存储的图像,我们可以将其包含为标志+url,但我们是一个运动检测库,所以静止图像没有多大意义。 @Justin-slade:你可以通过TextureView使用SurfaceTexture或者直接连接OpenGL来代替SurfaceView。

以上是关于Android:访问硬件相机预览帧数据而不绘制它们的主要内容,如果未能解决你的问题,请参考以下文章

Android:编码的相机预览帧总是横向的。如何旋转?

Android 绘制相机预览

如何在一帧后面显示预览相机并拍照包括帧

Android 相机预览在预览中拉伸,而不是在拍照后

如何确定相机预览帧的默认方向?

如何在android中的相机预览上绘制矩形