我正在尝试使用captureBurst()
方法在 Android 上使用 Camera2 API 捕获图像。我在按钮中开始突发捕获OnClickListener
:
button?.setOnClickListener(View.OnClickListener {
imageRequestBuilder?.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE)
imageRequest = imageRequestBuilder?.build()
val requests = Collections.nCopies(10, imageRequest)
cameraCaptureSession?.captureBurst(requests, captureCallback, backgroundHandler)
})
在我的OnImageAvailableListener
听众中,我正在读取捕获的图像,保存并关闭。在这一点上,我想在我的屏幕上显示一些东西,我想在连拍序列中的每个捕获的图像之间显示一些东西。所以我写了这段代码:
override fun onImageAvailable(reader: ImageReader?) {
val image = reader?.acquireNextImage()
if(image!=null) {
synchronized(uiUpdate) {
runOnUiThread(uiUpdate)
(uiUpdate as java.lang.Object).wait()
}
val buffer = image?.planes?.get(0)?.buffer
val bytes = ByteArray(buffer?.capacity()!!)
buffer.get(bytes)
SaveImageTask().execute(bytes)
}
image?.close()
}
private val uiUpdate = object : Runnable {
override fun run() {
synchronized(this) {
textView?.text = "" + ++imageNum
(this as java.lang.Object).notify()
}
}
}
为了测试它并确保这确实发生了,我正在使用我的前置摄像头,并在我的设备上方放置一面镜子,以便摄像头实际捕获应用程序的显示。不幸的是,显示和捕获不同步。我已经尝试将 10 个相同ImageRequests
的captureBurst
方法放在方法中,但是当我查看获得的图像时,前三个是相同的(显示仍然显示初始数字 0),但其余的都很好(显示正在同步变化)。为什么不能全部同步,即为什么前几张图像几乎同时拍摄(在连拍开始时),而其他的都很好?
我创建ImageReader
了最多 1 个图像,以便一次不捕获多个图像:
imageReader = ImageReader.newInstance(/*some width*/, /*some height*/, /*some format*/, 1)
并且使用模式RequestBuilder
创建TEMPLATE_PREVIEW
以最大化捕获屏幕。
我知道capture
每次在OnImageAvailableListener
侦听器中捕获新图像时我都可以调用方法,这是有效的(经过测试!)。但我需要让我的应用程序以尽可能快的速度捕获图像。
有什么帮助吗?
已编辑:这是@alex-cohn 建议的我的日志:
D/onImageAvailable: display #0 Timestamp #0: 111788230978655
D/onImageAvailable: display #1 Timestamp #1: 111788264308655
D/onImageAvailable: display #2 Timestamp #2: 111788297633655
D/onImageAvailable: display #3 Timestamp #3: 111788730892655
D/onImageAvailable: display #4 Timestamp #4: 111788930856655
D/onImageAvailable: display #5 Timestamp #5: 111789030840655
D/onImageAvailable: display #6 Timestamp #6: 111789097494655
D/onImageAvailable: display #7 Timestamp #7: 111789264133655
D/onImageAvailable: display #8 Timestamp #8: 111789364112655
D/onImageAvailable: display #9 Timestamp #9: 111789464097655
编辑2:
我已经设法为每个显示的数字获得一张图像,但是每次捕获一张图像后我都会丢弃两张图像,即:
private val onImageAvailableListener = ImageReader.OnImageAvailableListener {reader ->
val image = reader?.acquireLatestImage()
if(image!=null) {
capturedImagesCount++
if(capturedImagesCount % frameDrop == 1) {
Log.i("IMAGE_TIME", "Image available at: "+ SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.getDefault()).format(Date()))
synchronized(uiUpdate) {
runOnUiThread(uiUpdate)
(uiUpdate as java.lang.Object).wait()
}
val buffer = image.planes?.get(0)?.buffer
val bytes = ByteArray(buffer?.capacity()!!)
buffer.rewind()
buffer.get(bytes)
SaveImageTask().execute(bytes)
}
}
image?.close()
}
在这里,frameDrop
设置为 3。此外,maxImages
在创建 imageReader 时也设置为 3。我已经在另一台当时正在拍摄 2 张图像的设备上对其进行了测试,所以在该设备的情况下,我必须设置frameDrop
和maxImages
2 . 这样做的缺点是它仍然有点慢,毕竟它是以连拍模式拍摄的每三(第二)张图像,这不是您使用captureBurst
方法时想要的东西。
我仍然不太明白为什么会这样工作,以及为什么相机会以成对或三胞胎的形式拍摄图像。