我试图在一秒钟内捕获多张图像,即使10 fps也应该可以。我正在使用华为Mate20Pro。我尝试了处理程序方法,但实现了1fps,并减少了延迟,从而进一步导致相机挂起。代码在这里:
button.setOnClickListener {
prepareUIForCapture()
if(isRunning){
handler.removeCallbacksAndMessages(null)
restartActivity()
}else{
button.text = "Stop"
handler.postDelayed(object : Runnable {
override fun run(){
twoLens.reset()
twoLens.isTwoLensShot = true
MainActivity.cameraParams.get(dualCamLogicalId).let {
if (it?.isOpen == true) {
Logd("In onClick. Taking Dual Cam Photo on logical camera: " + dualCamLogicalId)
takePicture(this@MainActivity, it)
Toast.makeText(applicationContext, "Captured", Toast.LENGTH_LONG).show()
}
}
handler.postDelayed(this, 1000)
}
}, 2000)
}
isRunning = !isRunning
}
此处第一枪是2秒后,并且每1秒捕获一次。工作正常。我希望增加这个比率。我正在尝试突发捕获。
这是我到目前为止所做的。
在takePicture()
方法中:
val captureList = ArrayList<CaptureRequest>()
for (i in 0 until 10){
captureList.add(params.previewBuilder?.build()!!)
}
params.captureSession?.captureBurst(captureList, StillCaptureSessionCallback(activity, params), params.backgroundHandler)
params.captureBuilder?.removeTarget(normalParams?.imageReader?.surface!!)
params.captureBuilder?.removeTarget(wideParams?.imageReader?.surface!!)
我认为这是可行的,因为没有错误或异常。但是,我看不到保存的图像。这是我如何保存它们。
Toast.makeText(activity, "Burst Captured", Toast.LENGTH_LONG).show()
var tempBitmap: Bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888)
//We need both shots to be done and both images in order to proceed
if (!twoLens.normalShotDone || !twoLens.wideShotDone || (null == twoLens.normalImage)
|| (null == twoLens.wideImage))
return tempBitmap //Return empty bitmap
Logd("Normal image timestamp: " + twoLens.normalImage?.timestamp)
Logd("Wide image timestamp: " + twoLens.wideImage?.timestamp)
val wideBuffer: ByteBuffer? = twoLens.wideImage!!.planes[0].buffer
val wideBytes = ByteArray(wideBuffer!!.remaining())
wideBuffer.get(wideBytes)
val normalBuffer: ByteBuffer? = twoLens.normalImage!!.planes[0].buffer
val normalBytes = ByteArray(normalBuffer!!.remaining())
normalBuffer.get(normalBytes)
val tempWideBitmap = BitmapFactory.decodeByteArray(wideBytes, 0, wideBytes.size, null)
val tempNormalBitmap = BitmapFactory.decodeByteArray(normalBytes, 0, normalBytes.size, null)
//Utils.bitmapToMat(tempNormalBitmap, normalMat)
save(tempWideBitmap, "NormalShot")
save(tempNormalBitmap, "WideShot")
保存方法在这里:
fun save(bytes: Bitmap, tempName: String) {
val timeStamp = SimpleDateFormat("yyyyMMdd_HHmmss").format(Date())
val dataDir = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "TwoCameraImagesNew")
if (!dataDir.exists()) {
dataDir.mkdir()
}
val fileName = tempName + "_IMG_$timeStamp.jpg"
val fileDir = File(dataDir.path + File.separator + fileName)
try {
val fileOutputStream = FileOutputStream(fileDir)
bytes.compress(Bitmap.CompressFormat.JPEG, 100, fileOutputStream)
//fileOutputStream.write(bytes)
fileOutputStream.close()
} catch (e: FileNotFoundException) {
e.printStackTrace()
} catch (e: IOException) {
e.printStackTrace()
}
}
但是,我看不到已保存的图片(它正常工作而不会破裂)。有单独的方法保存连拍图像吗? 这是我的onImageAvailableListener:
imageReader = ImageReader.newInstance(960, 720, ImageFormat.JPEG, 20)
imageReader?.setOnImageAvailableListener(imageAvailableListener, backgroundHandler)
ImageAvailableListener类获取下一张图像(这对于连拍是否正确?),然后调用该方法以获取图像并保存它们(如上所示)。完整的ImageAvailableListener类在此处给出:
class ImageAvailableListener(private val activity: MainActivity, internal var params: CameraParams) : ImageReader.OnImageAvailableListener {
override fun onImageAvailable(reader: ImageReader) {
Log.d(MainActivity.LOG_TAG, "ImageReader. Image is available, about to post.")
val image: Image = reader.acquireNextImage()
if (MainActivity.twoLens.isTwoLensShot) {
if (MainActivity.wideAngleId == params.id) {
twoLens.wideImage = image
} else if (MainActivity.normalLensId == params.id) {
twoLens.normalImage = image
}
if (twoLens.wideShotDone && twoLens.normalShotDone
&& null != twoLens.wideImage
&& null != twoLens.normalImage) {
val finalBitmap: Bitmap = DoBokeh(activity, twoLens)
setCapturedPhoto(activity, params.capturedPhoto, finalBitmap)
twoLens.normalImage?.close()
twoLens.wideImage?.close()
}
}
Log.d(MainActivity.LOG_TAG, "ImageReader. Post has been set.")
}
}
这是捕获照片时至少达到10fps的正确方法吗?如果没有,应该如何进行?如何保存连拍的图像?
答案 0 :(得分:0)
不幸的是,拍照不是正确的方法,因为相机的回收时间取决于多种因素,包括硬件。 我建议您拍摄视频,然后检索帧。 您可以使用MediaRecorder拍摄和保存视频,然后可以使用MediaMetadataRetriever提取帧。 也许最后一堂课可能会给您带来一些问题。如果可以,我认为可以使用FFmpegMediaMetadataRetriever更好。 要拍摄框架,可以使用以下方法:
retriever.getFrameAtTime(time, MediaMetadataRetriever.OPTION_CLOSEST);
请注意,时间以微秒为单位,而不是毫秒。