Android Camera2 与 Camera API技术探究和RAW数据采集

Android Camera2

Android Camera2 是 Android 系统中用于相机操作的一套高级应用程序接口(API),它取代了之前的 Camera API。以下是关于 Android Camera2 的一些主要信息:

  1. 主要特点
    • 强大的控制能力:提供对相机更深入的控制,允许开发者精确设置对焦模式、曝光模式、快门速度、白平衡、增益等各种拍摄参数,能够满足复杂的拍摄需求,例如专业摄影应用或对图像质量有较高要求的场景。
    • 多流输出支持:单个相机设备可以同时输出多个流,每个流针对不同的使用场景进行了优化,如预览、拍照、视频录制或图像分析等。这使得开发者可以根据应用的具体需求灵活地获取和处理不同类型的图像数据。
    • 高效的数据处理:支持高效的零复制连拍和视频流功能,能够快速地获取和处理连续的图像数据,提高了相机的响应速度和数据处理效率。
  2. 核心类与组件
    • CameraManager:用于管理系统中的相机设备,提供了获取相机设备列表、打开指定相机以及获取相机特性等方法。开发者可以通过它来检测系统中可用的相机,并获取相机的相关信息以进行后续的操作。
    • CameraDevice:代表系统中的摄像头硬件设备,负责建立与相机的连接,并管理相机的状态。它可以创建 CaptureSession(捕获会话)以及 CaptureRequest(捕获请求),是与相机硬件进行交互的核心类。
    • CameraCharacteristics:描述了特定相机设备所支持的各种特性,通过 CameraManager 获取。开发者可以根据这些特性来判断相机的能力,例如是否支持自动对焦、是否支持特定的分辨率等,以便在应用中进行相应的设置和处理。
    • CameraCaptureSession:是应用程序与相机设备之间进行数据传输和交互的会话。当程序需要预览、拍照或录制视频时,都需要创建一个 CameraCaptureSession。它管理着 CaptureRequest 的队列,将开发者设置的拍摄参数传递给相机设备,并接收相机返回的图像数据。
    • CaptureRequest 和 CaptureRequest.Builder:CaptureRequest 代表了一次捕获请求,用于描述捕获图片或视频的各种参数设置,如对焦模式、曝光模式、分辨率等。CaptureRequest.Builder 则负责生成 CaptureRequest 对象,方便开发者设置各种参数。
  3. 使用步骤
    1. 获取 CameraManager:首先需要获取 CameraManager 对象,这是进行所有相机操作的前提。可以通过 Context.getSystemService(Context.CAMERA_SERVICE) 方法来获取 CameraManager。
    2. 打开相机设备:使用 CameraManager 的 openCamera(String cameraId, CameraDevice.StateCallback callback, Handler handler) 方法打开指定的摄像头。其中,cameraId 是要打开的摄像头的标识符,callback 用于监听摄像头的状态变化,handler 表示执行回调的线程。
    3. 创建 CameraCaptureSession:当摄像头打开后,通过 CameraDevice.createCaptureSession(List<Surface> outputs, CameraCaptureSession.StateCallback callback, Handler handler) 方法创建 CameraCaptureSession。outputs 是一个包含所有需要从该摄像头获取图片的 Surface 的列表,callback 用于监听会话的创建过程,handler 表示执行回调的线程。
    4. 创建 CaptureRequest:调用 CameraDevice.createCaptureRequest(int templateType) 方法创建 CaptureRequest.Builder,其中 templateType 可以是 TEMPLATE_PREVIEW(预览)、TEMPLATE_RECORD(拍摄视频)、TEMPLATE_STILL_CAPTURE(拍照)等。然后使用 CaptureRequest.Builder 设置拍照的各种参数。
    5. 开始预览或拍照:调用 CameraCaptureSession.setRepeatingRequest() 方法开始预览,或调用 capture() 方法进行拍照。拍照的优先级比预览的优先级高,如果需要多次拍照,可以多次调用 capture() 方法。
  4. 支持的版本和兼容性:Android Camera2 从 Android 5.0(API 级别 21)开始支持。但需要注意的是,虽然 Android 5.0 及更高版本的设备支持 Camera2,但部分设备可能并不支持所有的 Camera2 功能。在实际开发中,需要根据设备的具体特性和支持情况进行适配和处理。

相比Camera API技术优势

Android Camera2 与 Camera API 相比,具有以下优势:

  1. 功能与控制方
    • 更多的手动控制选项
      • Camera2 提供了丰富的手动设置功能,如曝光时间、ISO 感光度、对焦模式、焦距等参数都可以由开发者手动设置和精确调整,能够满足专业摄影或对图像质量有较高要求的场景。而 Camera API 的手动控制功能非常有限,通常只能实现简单的自动调节拍摄。
      • 例如,在光线复杂的环境中,使用 Camera2 可以根据实际需求手动调整曝光时间,以获得更准确的曝光效果,避免画面过亮或过暗;在拍摄特写镜头时,可以手动设置对焦模式和焦距,确保主体清晰。
    • 支持 RAW 图像捕获:Camera2 支持 RAW 格式的图像捕获,RAW 格式的图像包含了更多的原始图像信息,为后期处理提供了更大的空间和更高的灵活性,可以让用户在后期对图像的色彩、对比度、锐度等进行更精细的调整。相比之下,Camera API 通常只能获取经过压缩和处理的图像格式,丢失了很多原始信息14。
    • 高速连拍模式:Camera2 支持高速连拍功能,能够以更快的速度连续拍摄多张照片,这对于捕捉快速运动的物体或瞬间的精彩场景非常有帮助。而在 Camera API 中,实现连拍功能相对较为困难,且连拍速度和效果可能不尽如人意4。
  2. 性能优化方面
    • 并行处理能力:Camera2 支持并行拍摄和预览,在同时进行多个操作时表现更好,可以在预览的同时进行拍照、录像等操作,并且不会相互干扰,提高了相机的使用效率和响应速度。而在 Camera API 中,切换不同的拍摄模式(如从预览模式切换到拍照模式)可能会比较耗时,影响用户体验1。
    • 高效的数据处理:Camera2 采用了更高效的数据处理方式,能够快速地获取和处理图像数据,减少了数据传输和处理的延迟。例如,在拍摄视频时,Camera2 可以更流畅地获取和编码视频数据,降低了视频的卡顿现象5。
  3. 架构与兼容性方面
    • 更灵活的架构:Camera2 的架构更加灵活,将相机系统塑造为一个管道,该管道可按照 1:1 的基准将传入的帧捕获请求转化为帧,并将图像数据的缓冲区输出到设置的目的 Surface 中。这种架构使得开发者可以更方便地定制和扩展相机的功能,实现各种复杂的拍摄需求。
    • 更好的兼容性:虽然 Camera API 在早期的 Android 版本中广泛使用,但随着 Android 系统的不断升级,Camera2 逐渐成为了 Android 相机功能的主要 API。新的 Android 版本会对 Camera2 进行更好的优化和支持,而 Camera API 可能会逐渐被淘汰,使用 Camera2 可以更好地保证应用在不同 Android 版本上的兼容性3。
  4. 设备特性支持与检测方面
    • 设备能力检测:通过 CameraCharacteristics 类,Camera2 可以方便地检查设备相机的各种特性和功能,开发者可以根据设备的支持情况来动态地调整相机的设置和功能,提高了应用的适应性和稳定性。例如,在应用启动时,可以先检测设备是否支持手动对焦功能,如果支持则开启手动对焦选项,否则隐藏该选项,避免出现功能不可用的情况。
    • 支持更多新硬件特性:随着手机硬件的不断发展,新的相机硬件特性不断涌现,Camera2 能够更好地支持这些新特性,如更高的分辨率、更快的对焦速度、更好的低光性能等,为用户提供更好的拍摄体验。

Android Camera2 RAW图像捕获

要使用 Android Camera2 进行 RAW 图像捕获,你可以按照以下步骤进行操作:

  1. 检查设备支持:首先,确保你的设备支持 Camera2 API 并且支持 RAW 图像捕获。你可以通过查询设备的 CameraCharacteristics 来获取相关信息123。
  2. 获取 CameraManager:通过Context.getSystemService(Context.CAMERA_SERVICE)获取 CameraManager 实例123。
  3. 打开相机设备:使用 CameraManager 的openCamera(String cameraId, CameraDevice.StateCallback callback, Handler handler)方法打开相机设备。你需要指定要打开的相机 ID 以及相应的回调和处理程序123。
  4. 创建 CaptureRequest.Builder:创建一个 CaptureRequest.Builder 对象,并设置相关的参数,如对焦模式、曝光模式等。同时,将图像格式设置为ImageFormat.RAW_SENSOR以指定捕获 RAW 图像1。
  5. 创建 CameraCaptureSession:使用 CameraDevice 的createCaptureSession(List<Surface> outputs, CameraCaptureSession.StateCallback callback, Handler handler)方法创建一个 CameraCaptureSession。将包含 RAW 图像的 Surface 添加到输出列表中1。
  6. 开始捕获:调用 CameraCaptureSession 的capture(CaptureRequest request, CameraCaptureSession.CaptureCallback callback, Handler handler)方法开始捕获 RAW 图像。你可以指定相应的回调来处理捕获结果1。
  7. 处理 RAW 图像数据:在 CaptureCallback 的onCaptureCompleted方法中,你将接收到包含 RAW 图像数据的 CaptureResult 对象。你可以从 CaptureResult 中获取图像数据,并进行相应的处理或保存。

示例代码如下:

import android.content.Context;
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.CaptureRequest;
import android.os.Handler;
import android.os.HandlerThread;
import android.util.Log;
import android.view.Surface;public class RawImageCapture {private CameraManager cameraManager;private String cameraId;private CameraDevice cameraDevice;private CameraCaptureSession cameraCaptureSession;private CaptureRequest.Builder captureRequestBuilder;public void startRawImageCapture(Context context) {// 获取CameraManagercameraManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);try {// 获取相机设备IDcameraId = cameraManager.getCameraIdList()[0];// 打开相机设备cameraManager.openCamera(cameraId, new CameraDevice.StateCallback() {@Overridepublic void onOpened(CameraDevice camera) {cameraDevice = camera;createCaptureSession();}@Overridepublic void onDisconnected(CameraDevice camera) {cameraDevice.close();}@Overridepublic void onError(CameraDevice camera, int error) {cameraDevice.close();}}, null);} catch (CameraAccessException e) {e.printStackTrace();}}private void createCaptureSession() {try {// 创建CaptureRequest.BuildercaptureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);captureRequestBuilder.addTarget(new Surface(ImageFormat.RAW_SENSOR));// 创建CameraCaptureSessioncameraDevice.createCaptureSession(Arrays.asList(new Surface(ImageFormat.RAW_SENSOR)), new CameraCaptureSession.StateCallback() {@Overridepublic void onConfigured(CameraCaptureSession session) {cameraCaptureSession = session;startCapture();}@Overridepublic void onConfigureFailed(CameraCaptureSession session) {}}, null);} catch (CameraAccessException e) {e.printStackTrace();}}private void startCapture() {try {cameraCaptureSession.capture(captureRequestBuilder.build(), new CameraCaptureSession.CaptureCallback() {@Overridepublic void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {// 处理RAW图像数据Log.d("RawImageCapture", "RAW image captured");}}, null);} catch (CameraAccessException e) {e.printStackTrace();}}
}

如何对接Android Camera2

大牛直播SDK前几年在做Android平台RTMP推送和轻量级RTSP服务的时候,实际上就已经支持了Camera2的采集和数据投递,考虑到,目前5.0以下版本的设备越来越少,后面的GB28181设备接入模块,更是以Camera2的demo为准。

Camera2数据回调并投递到底层jni示例代码如下:

/** Camera2MainActivity.java* Author:daniusdk.com* WeChat: xinsheng120*/
@Override
public void onCameraImageData(Image image) {Image.Plane[] planes = image.getPlanes();if (image.getFormat() != ImageFormat.YUV_420_888) {Log.i(TAG,  "image format is not YUV_420_888, format:" + image.getFormat());return;} else {// Log.i(TAG,  "image format is YUV_420_888, format:" + image.getFormat());}int w = image.getWidth(), h = image.getHeight();int y_offset = 0, u_offset = 0, v_offset = 0;Rect crop_rect = image.getCropRect();if (crop_rect != null && !crop_rect.isEmpty()) {w = crop_rect.width();h = crop_rect.height();y_offset += crop_rect.top * planes[0].getRowStride() + crop_rect.left * planes[0].getPixelStride();u_offset += (crop_rect.top / 2) * planes[1].getRowStride() + (crop_rect.left / 2) * planes[1].getPixelStride();v_offset += (crop_rect.top / 2) * planes[2].getRowStride() + (crop_rect.left / 2) * planes[2].getPixelStride();;// Log.i(TAG, "crop w:" + w + " h:" + h + " y_offset:"+ y_offset + " u_offset:" + u_offset + " v_offset:" + v_offset);}int scale_w = 0, scale_h = 0, scale_filter_mode = 0;scale_filter_mode = 3;int rotation_degree = cameraImageRotationDegree_;if (rotation_degree < 0) {Log.i(TAG, "onCameraImageData rotation_degree < 0, may need to set orientation_ to 0, 90, 180 or 270");return;}for (LibPublisherWrapper i : publisher_array_)i.PostLayerImageYUV420888ByteBuffer(0, 0, 0,planes[0].getBuffer(), y_offset, planes[0].getRowStride(),planes[1].getBuffer(), u_offset, planes[1].getRowStride(),planes[2].getBuffer(), v_offset, planes[2].getRowStride(), planes[1].getPixelStride(),w, h, 0, 0,scale_w, scale_h, scale_filter_mode, rotation_degree);}

总结

Android Camera2 API 是从 Android 5.0(Lollipop)开始引入的,相对Camera API,优势非常明显,如果需要通过Android平台采集视频数据,在设备支持的前提下,建议尽可能用Camera2做数据采集。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/439494.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

神秘的二叉树

一.什么是树 都说艺术来源于生活&#xff0c;技术同样也是来源于生活。什么是树&#xff0c;它是一种非线性的数据结构&#xff0c;它是由n&#xff08;n>0&#xff09;个有限结点组成一个具有层次关系的集合。把它叫做树是因为它看起来像一棵倒挂的树&#xff0c;也就是说…

小程序 uniapp+Android+hbuilderx体育场地预约管理系统的设计与实现

目录 项目介绍支持以下技术栈&#xff1a;具体实现截图HBuilderXuniappmysql数据库与主流编程语言java类核心代码部分展示登录的业务流程的顺序是&#xff1a;数据库设计性能分析操作可行性技术可行性系统安全性数据完整性软件测试详细视频演示源码获取方式 项目介绍 用户 注册…

VUE2常见问题以及解决方案汇总(不断更新中)

解决vue项目中 el-table 的 row-click 事件与行内点击事件冲突&#xff0c;点击事件不生效&#xff08;表格行点击事件和行内元素点击事件冲突&#xff09;需要阻止事件冒泡 问题描述 1.点击列的编辑按钮&#xff0c;会触发按钮本身事件&#xff0c;同时会触发行点击事件 2.点…

Kotlin 处理字符串和正则表达式(二十一)

导读大纲 1.1 处理字符串和正则表达式1.1.1 分割字符串1.1.2 正则表达式和三引号字符串1.1.3 多行三引号字符串IntelliJ IDEA 和 Android Studio 中三重引号字符串内部的语法高亮显示 1.1 处理字符串和正则表达式 Kotlin 字符串与 Java 字符串完全相同 可以将 Kotlin 代码中创建…

R包的安装、加载以及如何查看帮助文档

0x01 如何安装R包 一、通过R 内置函数安装&#xff08;常用&#xff09; 1.安装CRAN的R包 install.packages()是一个用于安装 R 包的重要函数。 语法&#xff1a;install.packages(pkgs, repos getOption("repos"),...) 其中&#xff1a; pkgs&#xff1a;要安…

问题-python-运行报错-SyntaxError: Non-UTF-8 code starting with ‘\xd5‘ in file 汉字编码问题

​ 编码: 把字符转换成字节序列的过程。因为计算机只能处 理二进制数据&#xff0c;所以不能直接处理文本&#xff0c;需要先把文本转换为二进制数据。 解码: 把二进制数据转换成字符的过程。把接收到的数据转换成程序中使用的编码方式。 ​ 这个报错原因就是编码和解码没达成…

【C++ STL】手撕vector,深入理解vector的底层

vector的模拟实现 前言一.默认成员函数1.1常用的构造函数1.1.1默认构造函数1.1.2 n个 val值的构造函数1.1.3 迭代器区间构造1.1.4 initializer_list 的构造 1.2析构函数1.3拷贝构造函数1.4赋值运算符重载 二.元素的插入,删除,查找操作2.1 operator[]重载函数2.2 push_back函数:…

[已解决] Install PyTorch 报错 —— OpenOccupancy 配环境

目录 关于 常见的初始化报错 环境推荐 torch, torchvision & torchaudio cudatoolkit 本地pip安装方法 关于 OpenOccupancy: 语义占用感知对于自动驾驶至关重要&#xff0c;因为自动驾驶汽车需要对3D城市结构进行细粒度感知。然而&#xff0c;现有的相关基准在城市场…

TriLite完成A轮扩展融资:加速AR微型投影仪技术创新与市场拓展

近日,全球领先的AR微型投影仪开发商TriLite宣布成功完成A轮扩展融资,将A轮融资总额提升至超过2000万欧元。这一轮融资不仅彰显了资本市场对TriLite技术实力和市场潜力的高度认可,更为其后续在AR微型投影仪领域的技术研发、产品迭代以及市场拓展提供了坚实的资金保障。以下是…

大厂笔试现已经禁用本地IDE怎么看

如果我说本来面试做题这种事情就是反人类你相信吗&#xff1f; 这个罪恶的源头就是 Google&#xff0c;说是为了选择高素质的计算机编程水平的人才&#xff0c;然后把面试就变成了考试&#xff0c;最大的受益者当然是印度人了。 当把一个考察过程变成标准化的考试过程&#x…

【AI知识点】置信区间(Confidence Interval)

置信区间&#xff08;Confidence Interval, CI&#xff09; 是统计学中用于估计总体参数的范围。它给出了一个区间&#xff0c;并且这个区间包含总体参数的概率等于某个指定的置信水平&#xff08;通常是 90%、95% 或 99%&#xff09;。与点估计不同&#xff0c;置信区间通过区…

Unity Input System自动生成配置

参考视频 创建及配置新输入系统 New Input System&#xff5c;Unity2022.2 最新教程《勇士传说》入门到进阶&#xff5c;4K_哔哩哔哩_bilibili ProjectSettings设置 Unity编辑器菜单栏选择Edit->Project Settings->Player->Other Settings,将Api Compatibility Level…

OpenAI 开发者大会!实时语音功能有API了,GPT-4o支持多模态微调,上下文cache功能上线

家人们&#xff01;十一假期第1天&#xff0c; OpenAI一年一度的开发者大会又来了惹&#xff01;今年的开发者大会分成三部分分别在美国、英国、新加坡三个地点举办&#xff0c;刚刚结束的是第一场。 去年的OpenAI开发者大会公布了GPT-4 Turbo和GPTs&#xff0c;今年没有大更新…

allegro精确画圆形边框

1.显示原点位置&#xff1a; 2.class-subclass依次选择Board Geometry-Outline 3.菜单ADD---Circle,右侧option,依次设置如下&#xff0c;如图可设置为圆心&#xff08;0&#xff0c;0&#xff09;&#xff0c;半径为42mm的边框&#xff0c;不要忘了右键Done&#xff0c;完成绘…

【目标检测】工程机械车辆数据集2690张4类VOC+YOLO格式

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;2694 标注数量(xml文件个数)&#xff1a;2694 标注数量(txt文件个数)&#xff1a;2694 标注…

《Windows PE》3.2.4节表

节表由多个节表项&#xff08;IMAGE_SECTION_ HEADER&#xff09;组成&#xff0c;每个节表项&#xff08;40个字节&#xff09;记录了 PE中与某个特定的节有关的信息&#xff0c;如节的属性、节 的大小、在文件和内存中的起始位置等。节表中节的数量由字段IMAGE_FILE_HEADER. …

防止错误输入!Excel单元格限制输入内容的三种有效方式

在Excel中&#xff0c;限制单元格输入内容可以帮助避免数据输入错误&#xff0c;确保数据的一致性和准确性。今天小编分享三种方法&#xff0c;可以轻松限制Excel单元格的输入内容&#xff0c;确保数据输入符合预期要求&#xff0c;一起来看看吧&#xff01; 方法一&#xff1a…

el-pagination组件封装

组件使用 源代码&#xff1a; <script setup> import Pagination from /components/pagination/index.vue import {ref} from "vue";const pageNum ref(1) const pageSize ref(10) const total ref(120)function loadData() {// 加载数据 } </script>…

[云] Hands-on with a sample application--DockerCoins 挖矿程序!

DockerCoins 挖矿程序&#xff01;&#x1f4b0;&#x1f433;&#x1f4e6;&#x1f6a2; 不&#xff0c;你不能用 DockerCoins 买咖啡。 DockerCoins 如何工作&#xff1a; 生成一些随机字节&#xff1a; 程序首先生成一串随机的字节数据。这些随机字节用于模拟挖矿过程中的…

R语言绘制散点图

散点图是一种在直角坐标系中用数据点直观呈现两个变量之间关系、可检测异常值并探索数据分布的可视化图表。它是一种常用的数据可视化工具&#xff0c;我们通过不同的参数调整和包的使用&#xff0c;可以创建出满足各种需求的散点图。 常用绘制散点图的函数有plot()函数和ggpl…