Android Camera2 API实践:实现预览与图像数据捕获

十念  论坛元老 | 2025-2-19 16:06:20 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 1002|帖子 1002|积分 3006

本文还有配套的精品资源,点击获取  

  简介:介绍了在Android 5.0及以上版本中使用Camera2 API进行相机预览和图像数据捕获的方法。从基础概念到预览设置,再到图像数据的获取和处置惩罚,具体阐述了Camera2 API的核心组件和功能,以及如何通过实战示例学习和应用这些技术。

1. Camera2 API基础介绍

1.1 Camera2 API的作用与上风

  Camera2 API是Android平台上用于控制相机硬件的先辈接口,它提供了比旧版Camera API更丰富、更精细的控制本领。开发者可以使用Camera2 API来控制高级摄影功能,比如手动曝光、手动对焦、raw图像捕获等。如许的灵活性使得开发者能创建出更专业、更符合用户需求的照相应用。
1.2 Camera2 API与旧版Camera API的区别

  与旧版的Camera API相比,Camera2 API具有诸多改进之处。首先,Camera2 API对摄像头硬件的操作提供了更细粒度的控制,从初始化到捕获过程的每一帧,都能进行精细的调解。其次,Camera2 API支持更高分辨率的图像捕获,以及更广泛的图像格式。此外,Camera2 API引入了异步回调机制,从而提供更低延迟的预览和捕获体验,这对于寻求高质量用户体验的应用来说是一个明显的提升。
1.3 Camera2 API的核心概念和架构

  Camera2 API的核心概念包括CameraDevice、CameraCaptureSession、CaptureRequest等。CameraDevice代表了具体的相机硬件,而CameraCaptureSession则用于管理与相机硬件的会话,并负责发送捕获请求。CaptureRequest则用于界说一次捕获的具体设置,比如曝光、ISO、白平衡等。Camera2 API的架构是高度模块化的,允许开发者根据本身的需求进行灵活配置和使用。通过理解这些核心组件和它们之间的交互方式,开发者可以更好地利用Camera2 API的功能来实现复杂和高度定制化的相机应用。
2. 摄像头获取与预览设置

2.1 摄像头权限的申请与管理

  在Android平台上开发涉及摄像头的应用时,权限管理是首当其冲的重要部门。无论是为了遵照Google Play的政策还是为了用户数据的安全,正确地处置惩罚用户权限是开发过程中不可或缺的一环。
2.1.1 用户权限请求与处置惩罚

  为了使用摄像头,应用必要请求用户授予摄像头访问权限。这一过程通常发生在运行时,即应用运行时向用户请求必要的权限。以下是一段示例代码,展示如何检查并请求摄像头权限:
  1. if (ContextCompat.checkSelfPermission(thisActivity, Manifest.permission.CAMERA)
  2.         != PackageManager.PERMISSION_GRANTED) {
  3.     // Permission is not granted
  4.     ActivityCompat.requestPermissions(thisActivity,
  5.             new String[]{Manifest.permission.CAMERA},
  6.             MY_PERMISSIONS_REQUEST_CAMERA);
  7. }
复制代码
在上述代码中,  ContextCompat.checkSelfPermission  用于检查应用是否已经得到了摄像头权限,  requestPermissions  方法则是当应用未得到权限时向用户申请权限的函数。
2.1.2 系统权限的声明与获取

  除了在代码中动态请求外,还必要在AndroidManifest.xml文件中声明必要的权限。例如:
  1. <uses-permission android:name="android.permission.CAMERA" />
复制代码
假如您的应用面向Android 6.0(API 级别 23)或更高版本,必须在运行时请求权限。当用户授予权限后,系统会调用  onRequestPermissionsResult  方法。您的应用必要实现此方法以正确处置惩罚用户的响应。
2.2 摄像头装备的枚举与选择

  摄像头装备的枚举和选择是构建任何摄像头应用的基础,它涉及到如何在多个摄像头装备中选择最合适的装备供用户使用。
2.2.1 遍历可用摄像头装备

  首先,我们必要遍历装备上全部的摄像头,并得到它们的具体信息。以下是使用Camera2 API遍历摄像头装备的代码段:
  1. CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
  2. for (String cameraId : manager.getCameraIdList()) {
  3.     CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
  4.     // 获取摄像头的详细信息
  5.     Integer facing = characteristics.get(CameraCharacteristics.LENS_FACING);
  6.     if (facing != null && facing == CameraCharacteristics.LENS_FACING_FRONT) {
  7.         // 此处添加代码选择前摄像头设备
  8.     }
  9. }
复制代码
2.2.2 根据必要选择合适的摄像头

  摄像头的种类可能非常多,包括前后摄像头、深度摄像头等,我们必要根据应用需求来选择最合适的摄像头。例如,假如应用必要进行人脸辨认,那么通常会选用前摄像头。
2.3 摄像头预览参数的配置

  配置摄像头预览参数是实现个性化预览体验的关键,参数的合理设置能够影响预览的流畅度和质量。
2.3.1 设置预览巨细和格式

  预览的尺寸和格式直接关系到用户所见的预览效果和性能。以下代码展示了如何设置预览尺寸和格式:
  1. CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
  2. StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
  3. Size[] previewSizes = map.getOutputSizes(SurfaceTexture.class);
  4. // 假设我们选择的预览大小为1080x1920
  5. Size previewSize = new Size(1080, 1920);
复制代码
2.3.2 预览帧率的调解和限制

  预览帧率的调解是平衡装备性能和用户体验的重要手段。过高的帧率会导致装备负荷增加,而过低的帧率则会影响用户体验。
  1. // 设置期望的帧率范围
  2. int[] frameRates = map.getOutputMinFrameDuration(SurfaceTexture.class, previewSize);
  3. int minFps = frameRates[0];
  4. int maxFps = frameRates[1];
  5. // 根据设备性能调整实际帧率
  6. int actualFps = Math.min(Math.max(minFps, desiredFps), maxFps);
复制代码
在上述代码中,首先获取预览巨细对应的最小和最大帧率,然后在允许的范围内根据应用需求选择合适的帧率。
   表格展示不同预览尺寸与帧率的组合对性能的影响:
  | 预览尺寸(像素) | 最小帧率(fps) | 最大帧率(fps) | |------------------|-----------------|-----------------| | 1280x720 | 30 | 60 | | 1080x1920 | 24 | 48 | | 1920x1080 | 15 | 30 |
  通过表格可以清晰看到,预览尺寸和帧率对装备性能的要求。开发者可以根据表格信息和应用需求进行合理的预览参数配置。
  通过本章节的介绍,我们了解了摄像头权限申请与管理、摄像头装备的枚举与选择以及预览参数的配置等核心内容。这些内容为后续章节中进行高级配置和应用开发打下了坚固的基础。接下来,我们将进一步深入探讨如何创建和配置预览Surface,从而将摄像头的实时画面展示给用户。
3. 预览Surface的创建与配置

  在第三章中,我们将深入探讨如何在Android应用中创建和配置用于Camera2 API的预览Surface。预览Surface是显示摄像头预览画面的关键组件,本章将涵盖从创建Surface到绑定预览流的整个流程,并说明如何管理和更新动态Surface。
3.1 Surface的创建与预览流的绑定

3.1.1 创建Surface用于显示预览

  为了在Android应用中显示摄像头预览,首先必要创建一个Surface。在Camera2 API中,可以使用  SurfaceView  或  TextureView  来显示预览。以下代码展示了如何使用  TextureView  创建一个用于预览的Surface:
  1. TextureView textureView = (TextureView) findViewById(R.id.texture_view);
  2. textureView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {
  3.     @Override
  4.     public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
  5.         // 当Surface可用时,配置摄像头并开始预览
  6.         setupCameraAndStartPreview(surface);
  7.     }
  8.     @Override
  9.     public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
  10.         // 处理Surface尺寸变化
  11.     }
  12.     @Override
  13.     public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
  14.         // 表面被销毁时,释放资源
  15.         return true;
  16.     }
  17.     @Override
  18.     public void onSurfaceTextureUpdated(SurfaceTexture surface) {
  19.         // 表面被更新时的回调
  20.     }
  21. });
复制代码
在上述代码中,我们为  TextureView  设置了  SurfaceTextureListener  ,此中  onSurfaceTextureAvailable  回调会在Surface准备好时被调用。在这时,我们可以开始配置摄像头并启动预览。
3.1.2 将预览流与Surface绑定

  在获取到可用的Surface之后,我们必要将其与摄像头预览流绑定。这可以通过  CameraDevice  和  CaptureRequest.Builder  来完成。下面的代码段展示了如何将Surface与摄像头预览流绑定:
  1. private void setupCameraAndStartPreview(SurfaceTexture surface) {
  2.     try {
  3.         // 创建CaptureRequest.Builder实例,用于构建预览请求
  4.         CaptureRequest.Builder previewBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
  5.         // 将Surface添加到预览请求中
  6.         previewBuilder.addTarget(surface);
  7.         // 开始摄像头预览
  8.         mCameraDevice.createCaptureSession(Arrays.asList(surface), new CameraCaptureSession.StateCallback() {
  9.             @Override
  10.             public void onConfigured(CameraCaptureSession session) {
  11.                 // 当预览会话配置成功时,提交预览请求
  12.                 session.setRepeatingRequest(previewBuilder.build(), null, null);
  13.             }
  14.             @Override
  15.             public void onConfigureFailed(CameraCaptureSession session) {
  16.                 // 配置失败时的处理
  17.             }
  18.         }, mBackgroundHandler);
  19.     } catch (CameraAccessException e) {
  20.         // 处理摄像头访问异常
  21.     }
  22. }
复制代码
在上面的代码段中,我们首先创建了一个  CaptureRequest.Builder  的实例,并通过  addTarget  方法将Surface添加到预览构建器中。然后,我们创建了一个  CameraCaptureSession  并通过  setRepeatingRequest  方法开始周期性地提交预览请求。
3.2 Surface的管理与更新

3.2.1 监听Surface状态变革

  Surface的状态可能会因为各种原因发生变革,例如,当用户按下Home键或应用进入后台时,Surface可能会被系统销毁。因此,必要对Surface的状态变革进行监听,以便在应用必要时正确地处置惩罚这些变革。这可以通过  SurfaceTextureListener  中的  onSurfaceTextureDestroyed  和  onSurfaceTextureSizeChanged  回调实现。
3.2.2 动态Surface的配置更新

  在某些情况下,可能必要根据应用的必要动态地更新Surface的配置。例如,用户在应用内调解了预览窗口的巨细,或者摄像头的某些参数发生了变革。在这些情况下,必要重新绑定或更新Surface配置。以下是如何在运行时更新Surface配置的示例代码:
  1. private void updateSurfaceConfiguration(SurfaceTexture newSurface) {
  2.     // 停止当前的捕获会话
  3.     mCaptureSession.stopRepeating();
  4.     // 移除旧的Surface并添加新的Surface
  5.     try {
  6.         mCaptureSession.setRepeatingRequest(
  7.             mPreviewRequestBuilder.build(),
  8.             null,
  9.             mBackgroundHandler);
  10.     } catch (CameraAccessException e) {
  11.         // 处理摄像头访问异常
  12.     }
  13. }
复制代码
在上述代码中,首先停止了当前的捕获会话,然后更新了Surface配置,并重新开始了预览请求。如许的操作确保了预览窗口可以顺应Surface的变革。
  通过本章的介绍,我们已经了解了如何创建和配置用于Camera2 API的预览Surface,以及如何管理动态Surface。这些知识对于实现流畅的摄像头预览功能至关重要。在接下来的章节中,我们将继承探索构建CaptureSession和发送预览请求的具体步调,使我们能更全面地掌握Camera2 API的使用。
4. CaptureSession的构建与预览请求的发送

4.1 CaptureSession的初始化与配置

4.1.1 创建CaptureSession实例

  在深入探讨如何构建  CaptureSession  实例之前,有必要先理解  CaptureSession  是什么。  CaptureSession  是Camera2 API中的一个核心概念,用于控制相机的捕获操作。它是一个会话,用于将预览、录制、静态图片捕获等功能联合起来,协调它们的实行。在Camera2中,几乎全部的捕获操作都是通过  CaptureSession  来进行的。
  创建  CaptureSession  实例的代码如下所示:
  1. // 创建CameraDevice实例后,进行Session的创建
  2. CameraCaptureSession mCaptureSession = null;
  3. // 构建一个列表,列出我们想要与CaptureSession关联的输出目标
  4. List<Surface> outputs = new ArrayList<>();
  5. outputs.add(previewSurface); // 假设previewSurface是有效的Surface实例
  6. // 开始创建Session
  7. mCameraDevice.createCaptureSession(outputs, new CameraCaptureSession.StateCallback() {
  8.     @Override
  9.     public void onConfigured(CameraCaptureSession session) {
  10.         // 当Session配置完成时,此回调会被触发。
  11.         mCaptureSession = session;
  12.         // 这里可以发送预览请求等操作。
  13.     }
  14.     @Override
  15.     public void onConfigureFailed(CameraCaptureSession session) {
  16.         // 如果配置失败,将无法开始捕获。
  17.         // 此处可以进行错误处理。
  18.     }
  19. }, mBackgroundHandler);
复制代码
参数说明: -  outputs  : 这是一个  Surface  的列表,包含了一个或多个必要在  CaptureSession  中使用的  Surface  实例。 -  StateCallback  : 这是一个回调接口,它界说了几个重要的方法,比如  onConfigured  和  onConfigureFailed  ,用于吸取Session配置成功与否的通知。
  逻辑分析: 在这段代码中,我们首先创建了一个  CameraCaptureSession.StateCallback  实例,界说了处置惩罚  CaptureSession  配置成功或失败的回调函数。接着,我们使用  CameraDevice.createCaptureSession  方法创建  CaptureSession  ,传入了输出目标列表和状态回调。在  onConfigured  回调函数中,我们可以得到一个配置好的  CaptureSession  实例,并可以开始发送请求,如预览请求。
4.1.2 配置Session的输出目标

  在  onConfigured  回调中,一旦我们得到了配置好的  CaptureSession  实例,下一步就是设置输出目标。输出目标可以是屏幕预览、视频录制输出、图像捕获等,每一个输出目标都对应一个  Surface  对象。
  设置  CaptureSession  输出目标的代码如下:
  1. // 假设我们已经创建了CaptureSession实例和相应的Surface
  2. // 下面的代码应当在onConfigured()回调函数内执行
  3. try {
  4.     // 开始配置CaptureSession的输出目标
  5.     mCaptureSession.setRepeatingRequest(request, null, mBackgroundHandler);
  6. } catch (CameraAccessException e) {
  7.     // 处理可能出现的CameraAccessException异常
  8. }
复制代码
参数说明: -  request  : 是一个  CaptureRequest  对象,它表现一个请求,指示相机应该以何种方式捕获一帧图像。  setRepeatingRequest  方法将这个请求配置为重复实行,从而实现一连的预览。 -  null  : 这是  CaptureCallback  的占位符,假如必要吸取每个单独捕获请求的回调,则可以传入一个有效的  CaptureCallback  实例。在这里我们不必要,所以传入  null  。
  逻辑分析:  setRepeatingRequest  方法用于设置一个重复实行的捕获请求,例如一连的视频预览。这个方法接受三个参数:捕获请求、回调函数以及一个  Handler  。在上述代码中,  null  代表我们不必要为单个捕获事件吸取回调。假如捕获请求成功配置,将开始一连预览。假如在请求配置过程中出现非常,比如  CameraAccessException  ,则必要进行非常处置惩罚。
   CaptureSession  与输出目标的配置是实现相机应勤劳能的关键一步,它确保了图像数据可以流向正确的方向,例如屏幕预览或文件存储等。接下来的章节,我们将探讨如何构建预览请求并发送管理这些请求。
5. ImageReader的使用与图像数据处置惩罚

5.1 ImageReader基础与配置

5.1.1 ImageReader的工作原理

  ImageReader是Android中的一个类,专门用于处置惩罚图像数据的捕获。通过ImageReader,应用步伐能够高效地从摄像头预览中捕获帧,并将其转换为图像缓冲区,以便进行进一步的处置惩罚。ImageReader在内部使用生产者-消耗者模型,此中摄像头作为生产者,应用步伐作为消耗者。它允许应用步伐以同步或异步的方式从摄像头吸取一连的图像帧。
5.1.2 创建ImageReader实例并配置参数

  使用ImageReader时,首先必要创建一个ImageReader实例,该实例将界说所盼望的图像巨细和格式。例如,假如你希望捕获YUV格式的图像,巨细为1280x720像素,你可以如许做:
  1. ImageReader imageReader = ImageReader.newInstance(1280, 720, PixelFormat.YUV_420_888, 2);
复制代码
这段代码创建了一个ImageReader实例,它将提供两个缓冲区(缓冲区的数量由最后一个参数决定),每个缓冲区包含YUV格式的图像数据。
5.2 图像数据的捕获与处置惩罚

5.2.1 同步捕获图像帧

  在ImageReader创建之后,你可以将其与一个CaptureSession绑定,并注册一个ImageAvailableListener监听器来吸取图像帧。当缓冲区可用时,监听器的onImageAvailable方法会被调用:
  1. imageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
  2.     @Override
  3.     public void onImageAvailable(ImageReader reader) {
  4.         Image image = null;
  5.         try {
  6.             image = reader.acquireLatestImage();
  7.             if (image != null) {
  8.                 // 处理图像数据...
  9.             }
  10.         } finally {
  11.             if (image != null) {
  12.                 image.close(); // 确保及时释放资源
  13.             }
  14.         }
  15.     }
  16. }, handler);
复制代码
5.2.2 图像数据的处置惩罚方法和流程

  处置惩罚图像数据时,通常会涉及到对图像缓冲区的操作。根据所使用的图像格式,处置惩罚方法也会有所不同。例如,对于YUV格式的图像,你可能会必要进行色彩转换,以便将其用于图像处置惩罚库或显示到屏幕上。
  图像处置惩罚流程可能包括以下步调: - 获取图像缓冲区的引用。 - 读取缓冲区中的图像数据。 - 根据必要转换图像数据的格式。 - 应用图像处置惩罚算法,例如图像增强或滤镜效果。 - 将处置惩罚后的图像数据用于显示或生存。
5.3 图像数据的存储与使用

5.3.1 图像数据的格式转换

  捕获的图像数据通常必要转换为其他格式以顺应不同的用途。例如,将YUV格式转换为RGB格式,以便于图像编辑或显示。转换过程中要注意服从和质量的平衡。
  1. // 示例:YUV到RGB的转换过程(简化示例)
  2. byte[] yuvData = ... // 假设从Image对象中获取到的YUV数据
  3. int[] rgbData = new int[yuvData.length]; // 为转换后的RGB数据分配空间
  4. // 转换算法的实现(这里省略具体实现细节)
  5. // ...
  6. // 此时rgbData数组中包含了转换后的RGB数据
复制代码
5.3.2 将图像数据用于进一步处置惩罚或存储

  捕获并处置惩罚后的图像数据可以用于多种用途,例如实时分析、对象辨认、图像编辑或者直接生存到存储装备。在生存图像之前,通常还必要编码转换为JPEG或PNG格式:
  1. Bitmap bitmap = ... // 假设从Image对象中创建的Bitmap对象
  2. ByteArrayOutputStream stream = new ByteArrayOutputStream();
  3. bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
  4. byte[] byteArray = stream.toByteArray();
  5. File file = new File(getExternalFilesDir(null), "captured_image.png");
  6. FileOutputStream fos = new FileOutputStream(file);
  7. fos.write(byteArray);
  8. fos.close();
复制代码
以上章节的代码示例展示了ImageReader的基本使用方法和图像数据处置惩罚的初步步调,为读者提供了一个从捕获随处置惩罚和存储图像数据的完备流程。在现实应用中,必要针对具体需求进行相应的优化和调解。
   本文还有配套的精品资源,点击获取  

  简介:介绍了在Android 5.0及以上版本中使用Camera2 API进行相机预览和图像数据捕获的方法。从基础概念到预览设置,再到图像数据的获取和处置惩罚,具体阐述了Camera2 API的核心组件和功能,以及如何通过实战示例学习和应用这些技术。
   本文还有配套的精品资源,点击获取  


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

十念

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表