当前位置: 首页 > 知识库问答 >
问题:

如何在Android中使用Camera2 API拍摄无需预览的多张照片?

齐建安
2023-03-14

我需要捕捉多张照片使用Camera2 API后,特定的间隔,如5秒。我需要在没有预演的情况下做。我可以捕获一张单张照片没有预览,但我需要知道如何捕获多张照片?一旦相机打开,我不想一次又一次地设置所有的参数,我只想在特定的间隔后捕捉照片,一旦所有的照片都捕捉到了,然后我会关闭相机。

也只是第一次被捕获的图像。第二次调用takepciture()方法时,什么也没有发生。

下面是我的代码。

import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.ImageFormat;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CameraMetadata;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.TotalCaptureResult;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.media.Image;
import android.media.ImageReader;
import android.os.Build;
import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
import androidx.annotation.NonNull;

import android.util.Log;
import android.util.Size;
import android.widget.Toast;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.UUID;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

import androidx.annotation.RequiresApi;
import androidx.core.content.ContextCompat;

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public class CameraAdmin {

    Context context;

    private static final String TAG = "CameraAdmin";

    private String mCameraId;
    private CameraCaptureSession mCaptureSession;
    private CameraDevice mCameraDevice;

    private HandlerThread backgroundThread;
    private ImageReader imageReader;
    private String cImgType,cFileToSave;
    public boolean CaptureCompleted;
    CaptureRequest.Builder captureBuilder;

    public CameraAdmin(Context context,String CameraID) {
        this.context = context;
        this.mCameraId=CameraID;
        this.CaptureCompleted=false;
    }

    public void openCamera() {
        if (ContextCompat.checkSelfPermission(context, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
            return;
        }
        setUpCameraOutputs();
        CameraManager manager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
        try {
            manager.openCamera(mCameraId, mStateCallback, null);
        } catch (Exception e) {
            e.printStackTrace();

        }
    }

    private void setUpCameraOutputs() {
        CameraManager manager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
        try {
            CameraCharacteristics characteristics = manager.getCameraCharacteristics(mCameraId);

            StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);

            imageReader = ImageReader.newInstance(1920, 1080, ImageFormat.JPEG, /*maxImages*/2);
            imageReader.setOnImageAvailableListener(mOnImageAvailableListener, null);

            return;
        } catch (CameraAccessException e) {
            e.printStackTrace();
        } catch (NullPointerException e) {
            e.printStackTrace();
        }
    }

    private final CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() {

        @Override
        public void onOpened(@NonNull CameraDevice cameraDevice) {
            mCameraDevice = cameraDevice;
            createCameraCaptureSession();
        }

        @Override
        public void onDisconnected(@NonNull CameraDevice cameraDevice) {
            cameraDevice.close();
            mCameraDevice = null;
        }

        @Override
        public void onError(@NonNull CameraDevice cameraDevice, int error) {
            cameraDevice.close();
            mCameraDevice = null;
        }

    };

    private final ImageReader.OnImageAvailableListener mOnImageAvailableListener = new ImageReader.OnImageAvailableListener() {

        @Override
        public void onImageAvailable(ImageReader reader) {
            Log.d(TAG, "ImageAvailable");
            final Image image = reader.acquireLatestImage();
            final ByteBuffer buffer = image.getPlanes()[0].getBuffer();
            final byte[] bytes = new byte[buffer.capacity()];
            buffer.get(bytes);
            saveImageToDisk(bytes);
            Intent intent = new Intent();
            intent.setAction(MainActivity.MyBroadcastReceiver.ACTION);
            intent.putExtra("dataToPass", "Image Saved!");
            context.sendBroadcast(intent);
            image.close();
        }
    };

    private void saveImageToDisk(final byte[] bytes)
    {
        final File file = new File(Environment.getExternalStorageDirectory() + "/" + cFileToSave +".jpg");
        try (final OutputStream output = new FileOutputStream(file)) {
            output.write(bytes);
            Log.d("FileSaved","FileSaved");

        } catch (final IOException e) {
            Log.e(TAG, "Exception occurred while saving picture to external storage ", e);
        }
    }
    public void closeCamera() {
        try {
            if (null != mCaptureSession) {
                mCaptureSession.close();
                mCaptureSession = null;
            }
            if (null != mCameraDevice) {
                mCameraDevice.close();
                mCameraDevice = null;
            }
            if (null != imageReader) {
                imageReader.close();
                imageReader = null;
            }
        } catch (Exception e) {
            throw new RuntimeException("Interrupted while trying to lock camera closing.", e);
        } finally {
        }
    }


    private void createCameraCaptureSession() {
        try {

            captureBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
            captureBuilder.set(CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION,-3);
            captureBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
            captureBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_AUTO);
            captureBuilder.set(CaptureRequest.LENS_FOCUS_DISTANCE, 0f);
            captureBuilder.addTarget(imageReader.getSurface());

            mCameraDevice.createCaptureSession(Arrays.asList(imageReader.getSurface()),
                    new CameraCaptureSession.StateCallback() {
                        @Override
                        public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) {
                            if (null == mCameraDevice) {
                                return;
                            }
                            mCaptureSession = cameraCaptureSession;
                        }

                        @Override
                        public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) {
                            Log.d(TAG, "Configuration Failed");
                        }
                    }, null
            );
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

    public void takePicture(String ImgType,String FileToSave) {
        try {
            if (null == mCameraDevice) {
                return;
            }
            this.cImgType = ImgType;
            this.cFileToSave = FileToSave;
            CameraCaptureSession.CaptureCallback CaptureCallback = new CameraCaptureSession.CaptureCallback() {
                @Override
                public void onCaptureCompleted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull TotalCaptureResult result) {
                }
            };

            mCaptureSession.capture(captureBuilder.build(), CaptureCallback, null);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
        Toast.makeText(context, file.getAbsolutePath(), Toast.LENGTH_SHORT).show();
    }
}

共有1个答案

南宫胡媚
2023-03-14

您需要在CameracAptureSession对象上配置重复请求。相关文档如下:https://developer.android.com/reference/android/hardware/camera2/cameracapturesession.html#setRepeatingRequest(Android.hardware.camera2.captureRequest,%20android.hardware.camera2.cameracapturesession.capturecallback,%20android.os.handler)

 类似资料:
  • 标题问题99.9%的答案如下: 当您在

  • 问题内容: 我需要在活动中获得并显示照片库中最近拍摄的3张照片,而无需任何点击。 完成此步骤后,滚动时,我应该以3 x 3的方式拍摄其他照片。 您知道快速执行此操作的正确方法吗?谢谢。 问题答案: 这是使用适用于iOS 8+设备的框架的解决方案:

  • 可使用前端相机或背面相机拍摄照片。 A ) (显示模式) 轻触图标可切换为显示模式。 B ) (位置数据)/(切换相机)/(切换图像大小) 启用位置数据的使用设定即可显示(位置数据)。轻触图标可使用Wi-Fi、GPS*、手机基地台*的信息取得位置数据。取得后会显示(已取得位置数据),拍摄照片时会同时记录位置数据。 * 仅限3G/Wi-Fi机种 C ) (快门) 轻触图标可拍摄照片。 D ) 已拍摄

  • 我试图在没有预览的情况下配置相机兼容性,但在拍摄第二张照片后,应用程序异常崩溃: 2018-12-27 14:36:20.392 123 89-12977/com.example.android.braillefeedere/requestThread-0:捕获调用期间收到设备异常:java.io.ioException:setPreviewTexture在Android.hardware.cam

  • 问题内容: 我想在我的应用中以真实的黑白照片。我也在该网站上搜索了解决方案,但是我总是找到将照片放成灰度的解决方案(例如在本主题中),但这不是我想要的… 我还发现了一个提出这一建议的主题: 但是图像质量太差了… 请问有人有主意吗? 谢谢 问题答案: 如果您希望图像为1位黑白,则可以使用简单的(慢速)阈值算法 但是,根据看起来不太好的东西,要获得更好的结果,您需要使用抖动算法,请参阅算法概述 -这是

  • 如何获取容器快照并将快照加载到另一个docker主机中。我想知道容器快照,而不是图像。我对docker中的导出/导入和保存/加载命令感到困惑。我喜欢更清晰或更深入地理解它们。 快照包含运行容器和屋顶的元数据。另一个docker主机中的确切状态。这方面的帮助将是巨大的。