Android Camera2 Burst和ImageReader
我正在尝试获取具有不同曝光时间的多张图片,以执行我的Android Camera2 Burst和ImageReader,android,computer-vision,android-camera,camera2,Android,Computer Vision,Android Camera,Camera2,我正在尝试获取具有不同曝光时间的多张图片,以执行我的HDR算法。但是,我不知道如何在AndroidCamera2API和ImageReader中使用captureBurst()来保存文件。 我的代码将创建重复的文件。谁能帮我一把吗 private ImageReader mImageReader; private final ImageReader.OnImageAvailableListener mOnImageAvailableListener = new I
HDR算法
。但是,我不知道如何在AndroidCamera2API
和ImageReader
中使用captureBurst()
来保存文件。
我的代码将创建重复的文件。谁能帮我一把吗
private ImageReader mImageReader;
private final ImageReader.OnImageAvailableListener mOnImageAvailableListener =
new ImageReader.OnImageAvailableListener() {
@Override
public void onImageAvailable(ImageReader reader) {
mBackgroundHandler.post(new ImageSaver(reader.acquireNextImage()));
}
};
private static class ImageSaver implements Runnable {
private final Image mImage;
private ImageSaver(Image image) {
mImage = image;
}
private File createNewImageFile() throws IOException {
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "IMG_" + timeStamp;
File storageDirectory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM + "/Camera");
File image = File.createTempFile(imageFileName, ".jpg", storageDirectory);
return image;
}
@Override
public void run() {
ByteBuffer byteBuffer = mImage.getPlanes()[0].getBuffer();
byte[] bytes = new byte[byteBuffer.remaining()];
byteBuffer.get(bytes);
FileOutputStream fileOutputStream = null;
try {
File newFile = null;
try {
newFile = createNewImageFile();
} catch (IOException e) {
e.printStackTrace();
}
fileOutputStream = new FileOutputStream(newFile);
fileOutputStream.write(bytes);
mImageFileNameList.add(newFile.getName());
} catch (IOException e) {
e.printStackTrace();
} finally {
mImage.close();
if (fileOutputStream != null) {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
private void captureStillImage() {
try {
CaptureRequest.Builder captureStillBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
captureStillBuilder.addTarget(mImageReader.getSurface());
CaptureRequest.Builder captureStillBuilder2 = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
captureStillBuilder2.addTarget(mImageReader.getSurface());
int rotation = getWindowManager().getDefaultDisplay().getRotation();
captureStillBuilder.set(CaptureRequest.JPEG_ORIENTATION,
ORIENTATIONS.get(rotation));
captureStillBuilder2.set(CaptureRequest.JPEG_ORIENTATION,
ORIENTATIONS.get(rotation));
CameraCaptureSession.CaptureCallback captureCallback =
new CameraCaptureSession.CaptureCallback() {
@Override
public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
super.onCaptureCompleted(session, request, result);
unlockFocus();
}
};
List<CaptureRequest> list = new ArrayList<>();
captureStillBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_OFF);
captureStillBuilder.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_OFF);
captureStillBuilder.set(CaptureRequest.SENSOR_EXPOSURE_TIME, ONE_SECOND / 100);
captureStillBuilder2.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_OFF);
captureStillBuilder2.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_OFF);
captureStillBuilder2.set(CaptureRequest.SENSOR_EXPOSURE_TIME, ONE_SECOND / 20);
list.add(captureStillBuilder.build());
list.add(captureStillBuilder2.build());
mCameraCaptureSession.captureBurst(list, captureCallback, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
私有图像阅读器mImageReader;
private final ImageReader.OnImageAvailableListener监控mageAvailableListener=
新的ImageReader.OnImageAvailableListener(){
@凌驾
公共图像可用(图像阅读器){
mBackgroundHandler.post(新的图像保护程序(reader.acquireNextImage());
}
};
私有静态类ImageSaver实现可运行{
私有最终图像模拟;
专用图像保护程序(图像){
图像=图像;
}
私有文件createNewImageFile()引发IOException{
字符串时间戳=新的SimpleDateFormat(“yyyyMMdd_HHmmss”)。格式(新日期();
字符串imageFileName=“IMG_389;”+时间戳;
文件storageDirectory=Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM+“/Camera”);
File image=File.createTempFile(imageFileName,.jpg,.storageDirectory);
返回图像;
}
@凌驾
公开募捐{
ByteBuffer ByteBuffer=mImage.getPlanes()[0].getBuffer();
byte[]bytes=新字节[byteBuffer.remaining()];
get(字节);
FileOutputStream FileOutputStream=null;
试一试{
File newFile=null;
试一试{
newFile=createNewImageFile();
}捕获(IOE异常){
e、 printStackTrace();
}
fileOutputStream=新fileOutputStream(新文件);
fileOutputStream.write(字节);
添加(newFile.getName());
}捕获(IOE异常){
e、 printStackTrace();
}最后{
mImage.close();
if(fileOutputStream!=null){
试一试{
fileOutputStream.close();
}捕获(IOE异常){
e、 printStackTrace();
}
}
}
}
}
私有void captureStillImage(){
试一试{
CaptureRequest.Builder captureStillBuilder=mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE\u STILL\u CAPTURE);
addTarget(mImageReader.getSurface());
CaptureRequest.Builder captureStillBuilder2=mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE\u STILL\u CAPTURE);
addTarget(mImageReader.getSurface());
int rotation=getWindowManager().getDefaultDisplay().getRotation();
captureStillBuilder.set(CaptureRequest.JPEG\u方向,
方向。获取(旋转);
captureStillBuilder2.set(CaptureRequest.JPEG\u方向,
方向。获取(旋转);
CameraCaptureSession.CaptureCallback CaptureCallback=
新建CameraCaptureSession.CaptureCallback(){
@凌驾
捕获完成后的公共void(CameraCaptureSession会话、CaptureRequest请求、TotalCaptureResult){
super.onCaptureCompleted(会话、请求、结果);
解除锁定焦点();
}
};
列表=新的ArrayList();
captureStillBuilder.set(CaptureRequest.CONTROL_AE_模式,CaptureRequest.CONTROL_AE_模式关闭);
设置(CaptureRequest.CONTROL\u模式,CaptureRequest.CONTROL\u模式关闭);
captureStillBuilder.set(CaptureRequest.SENSOR\u曝光时间,1秒/100);
captureStillBuilder2.set(CaptureRequest.CONTROL\u AE\u MODE,CaptureRequest.CONTROL\u AE\u MODE\u OFF);
captureStillBuilder2.set(CaptureRequest.CONTROL\u模式,CaptureRequest.CONTROL\u模式关闭);
captureStillBuilder2.设置(CaptureRequest.SENSOR\u曝光时间,1秒/20);
add(captureStillBuilder.build());
add(captureStillBuilder2.build());
captureBurst(列表,captureCallback,null);
}捕获(CameraAccessE异常){
e、 printStackTrace();
}
}
以下是类似场景中的代码,我将文件保存在外部图片文件夹下名为C2的文件夹中:
@Override
public void onImageAvailable(ImageReader reader) {
String currentDateTime = generateTimestamp();
File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getAbsolutePath()
+ "/C2/" + mCount++ + "_" + currentDateTime + ".jpg");
if (mCount == 3) mCount = 1; // Reset the counter
mBackgroundHandler.post(new ImageSaver(reader.acquireNextImage(), file));
}
而mCount设置为
private int mCount = 1;
generateTimestamp来自谷歌的示例代码:
/**
* Generate a string containing a formatted timestamp with the current date and time.
*
* @return a {@link String} representing a time.
*/
private static String generateTimestamp() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss_SSS", Locale.US);
return sdf.format(new Date());
}
如果一切似乎都不正常,而您的问题只是文件名被复制,那可能是因为您的手机可以以超过1秒的速度捕获两个JPEG 图像文件名的格式字符串为:“yyyyMMdd_HHmmss” 这不包括任何分数秒,所以在 12:35:15.100和12:35:15.700(相隔600毫秒)将映射到同一文件名, IMG_u…123515.jpg 根据文档,您只需在字符串中添加“SSS”以包含毫秒,这将消除文件名的歧义,除非捕获速度非常快
或者,您可以为同名文件保留某种计数器,并在发生冲突时附加_1、_2等。查看CaptureRequest.CONTROL\u AE\u EXPOSURE\u COMPENSATION而不是CaptureRequest.SENSOR\u EXPOSURE\u time谢谢,我会查看一下。