【问题标题】:Android Camera2 Burst and ImageReaderAndroid Camera2 Burst 和 ImageReader
【发布时间】:2023-03-12 13:06:01
【问题描述】:

我正在尝试获取多张具有不同曝光时间的照片来执行我的HDR algorithm。但是,我无法弄清楚如何在 Android camera2 APIImageReader 中使用 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();
        }
    }

【问题讨论】:

  • 查看 CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION 而不是 CaptureRequest.SENSOR_EXPOSURE_TIME
  • 谢谢,我去看看。

标签: android computer-vision android-camera camera2


【解决方案1】:

如果一切似乎都正常工作,而您的问题只是文件名重复,那可能只是因为您的手机捕获两个 JPEG 的速度快于 1 秒。

图像文件名的格式字符串是:“yyyyMMdd_HHmmss” 这不包括任何小数秒,所以拍摄的照片,比如说 12:35:15.100 和 12:35:15.700(相隔 600 毫秒)将映射到相同的文件名, IMG_..._123515.jpg。

根据SimpleDateFormat 文档,您也可以在字符串中添加“_SSS”以包含毫秒,这应该可以消除文件名的歧义,除非它们被真的快速捕获。

或者,您可以为同名文件保留某种计数器,并在发生冲突时附加 _1、_2 等。

【讨论】:

    【解决方案2】:

    这是我在类似场景中的代码,我将文件保存在外部图片文件夹下名为 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 来自 Google 的示例代码:

    /**
     * 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());
    }
    

    【讨论】:

      猜你喜欢
      • 2017-01-06
      • 1970-01-01
      • 2017-02-26
      • 1970-01-01
      • 2017-07-30
      • 1970-01-01
      • 2016-04-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多