Camera2如何获取连续的摄像头预览图像访问权限

4
我想根据API将一个应用程序从Camera1扩展到Camera2。该应用程序的一个核心机制是以每秒约20张的速度拍摄预览图片。使用Camera1时,我创建了一个SurfaceView,向其持有者添加回调函数,并在表面创建后通过周期性setOneShotPreviewCallbacks访问预览图片。那非常容易和可靠。
现在,当研究Camera2时,我“从末尾”开始,设法将YUV420_888转换为位图(请参见YUV420_888 to Bitmap Conversion)。然而,我现在遇到了“捕获技术”的问题。从Google示例中可以看出,您需要使用CameraDevice.TEMPLATE_PREVIEW设置“setRepeating”CaptureRequest来显示预览,例如在surface视图上。这很好。但是,为了拍摄实际图片,我需要使用(这次)builder.addTarget(imageReader.getSurface())进行另一个捕获请求。也就是说,数据将在imageReader的onImageAvailable方法中可用。
问题是:捕获请求的创建是相当耗费时间的操作,在我的设备上大约需要200毫秒。因此,使用捕获请求(无论是STILL_CAPTUR还是PREVIEW模板)都不可能是每秒捕获20张图像的可行方法,这正是我所需的。我在SO上找到的建议主要基于(教育上中等有效的)Google示例,我并不真正理解...
我觉得解决方案必须是向ImageReader提供连续的预览图片流,然后可以以给定的频率从那里获取。请问有人能够指导如何实现吗?非常感谢。

抱歉,忘记添加 Android 标签了。 - Settembrini
1
你能解决它吗? - Prakhar Asthana
1个回答

4
如果您想将缓冲区发送到预览SurfaceView和YUV ImageReader,只需将两个Surface添加到重复预览请求中作为目标即可。一般来说,捕获请求可以针对会话配置的任何子集(或全部)输出目标进行定位。如果您只想偶尔使用.capture()将帧捕获到您的YUV ImageReader中,则不必每次重新创建捕获请求构建器;只需在同一构建器上再次调用.build(),或者如果您没有更改任何设置,则直接重用实际构造的CaptureRequest即可。即使进行这种偶尔捕获,您也可能希望在YUV捕获请求中包括预览Surface作为目标,以便在显示的预览中没有跳帧。

谢谢Eddy,这非常有帮助,听起来是一种直观的方法。然而,为了有效地实施它,我认为有必要更详细地研究Camera2,因为仍然有许多方面我不理解(例如线程的作用)。我会回来的,在接受你的答案之后,希望能够发布一些对其他人有帮助的代码。也许在那之前我还会有一些后续问题...再次感谢。 - Settembrini
3
我快要放弃了。每次我将ImageReader作为一个额外的目标添加时,预览要么不可见,要么会崩溃显示“无法使用未配置的表面”。我已经搜寻了很多小时,寻找通过imagereader获取预览图片的完整示例(我认为这是相当基本的应用程序),但我没有找到任何内容。我试图尽可能简化谷歌的示例,但它仍然太复杂了,无法评估各个部分与我的问题的相关性。 - Settembrini
2
很抱歉听到这个。"无法使用未配置的表面"意味着您没有将ImageReader Surface作为CameraDevice.createCaptureSession参数的一部分包含在内。您需要将两个表面作为createCaptureSession的参数,并且在使用setRepeatingRequest提交的CaptureRequest中。一个重要的细节:确保在完成后立即关闭从ImageReader接收的图像;否则,一切都会停滞不前(读取器中有固定数量的缓冲区,如果无法获取空缓冲区进行填充,则相机会停止)。 - Eddy Talvala
2
那就是缺失的一环!唯一的问题确实是我没有将ImageReaders的surface添加到mCameraDevice.createCaptureSession()的Arrays.asList(...)参数中...太简单了。谢谢你,Eddy!现在我真的很期待使用Camera2! - Settembrini

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接