我正在使用Android Camera2 API拍摄一系列照片,以进行实时姿势估计和环境重建(SLAM问题)。目前,我只是将所有这些图片保存在SD卡中以进行离线处理。
我使用Camera2Basic
和TextureView
根据Google的ImageReader
设置了处理管道,它们都被设置为重复预览请求的目标表面。
mButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(mIsShooting){
try {
mCaptureSession.stopRepeating();
mPreviewRequestBuilder.removeTarget(mImageReader.getSurface());
mCaptureSession.setRepeatingRequest(mPreviewRequestBuilder.build(), mCaptureCallback, mBackgroundHandler);
mIsShooting = false;
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
else{
try {
mCaptureSession.stopRepeating();
mPreviewRequestBuilder.addTarget(mImageReader.getSurface());
mCaptureSession.setRepeatingRequest(mPreviewRequestBuilder.build(), mCaptureCallback, mBackgroundHandler);
mIsShooting = true;
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
}
});
按下按钮时,会添加/删除ImageReader
。 ImageReader
的{{1}}的实现如下:
OnImageAvailableListener
我使用private ImageReader.OnImageAvailableListener mOnImageAvailableListener = new ImageReader.OnImageAvailableListener() {
@Override
public void onImageAvailable(ImageReader reader) {
Image img = reader.acquireLatestImage();
if(null == img){
return;
}
if(img.getTimestamp() <= mLatestFrameTime){
Log.i(Tag, "disorder detected!");
return;
}
mLatestFrameTime = img.getTimestamp();
ImageSaver saver = new ImageSaver(img, img.getTimestamp());
saver.run();
}
};
(缓冲区大小设置为2)丢弃旧帧,并检查了图像的时间戳以确保它们单调增加。
阅读器确实以可接受的速率(约25fps)接收图像。但是,仔细查看保存的图像序列会发现它们不是 始终按时间顺序保存。
以下图片来自该程序的长时间拍摄(很抱歉,无法直接发布图片:():
图片1:
图片2:
图片3:
这种混乱不是很经常发生,但是它们可以随时发生,并且似乎不是初始化问题。我想这与acquireLatestImage
的缓冲区大小有关,因为使用较大的缓冲区会减少“闪回”。有人有同样的问题吗?
答案 0 :(得分:0)
在启用ImageReader或只是TEMPLATE_PREVIEW时,您是对捕获请求使用TEMPLATE_STILL_CAPTURE吗?您在哪些设备上遇到问题?
如果您使用的是STILL_CAPTURE,请确保检查设备是否支持ENABLE_ZSL标志,并将其设置为false。如果将其设置为true(对于STILL_CAPTURE模板,通常设置为支持该设置的设备上的默认设置),则由于相机设备中存在零快门滞后队列,图像可能会无序返回。
答案 1 :(得分:0)
我终于发现,当在其构造函数中将ImageReader
的格式设置为YUV_420_888
时,这种混乱就消失了。最初,我将此字段设置为JPEG
。
使用JPEG
格式不仅会导致较大的处理延迟,还会导致混乱。我猜想从图像传感器数据到所需格式的转换会利用其他不能保证按时间顺序排列的硬件,例如DSP或GPU。