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

news2024/11/18 14:23:11

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) {
        // 获取CameraManager
        cameraManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);

        try {
            // 获取相机设备ID
            cameraId = cameraManager.getCameraIdList()[0];

            // 打开相机设备
            cameraManager.openCamera(cameraId, new CameraDevice.StateCallback() {
                @Override
                public void onOpened(CameraDevice camera) {
                    cameraDevice = camera;
                    createCaptureSession();
                }

                @Override
                public void onDisconnected(CameraDevice camera) {
                    cameraDevice.close();
                }

                @Override
                public void onError(CameraDevice camera, int error) {
                    cameraDevice.close();
                }
            }, null);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

    private void createCaptureSession() {
        try {
            // 创建CaptureRequest.Builder
            captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
            captureRequestBuilder.addTarget(new Surface(ImageFormat.RAW_SENSOR));

            // 创建CameraCaptureSession
            cameraDevice.createCaptureSession(Arrays.asList(new Surface(ImageFormat.RAW_SENSOR)), new CameraCaptureSession.StateCallback() {
                @Override
                public void onConfigured(CameraCaptureSession session) {
                    cameraCaptureSession = session;
                    startCapture();
                }

                @Override
                public void onConfigureFailed(CameraCaptureSession session) {

                }
            }, null);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

    private void startCapture() {
        try {
            cameraCaptureSession.capture(captureRequestBuilder.build(), new CameraCaptureSession.CaptureCallback() {
                @Override
                public 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.coloradmin.cn/o/2184166.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JavaWeb——Vue组件库Element(4/6):案例:基本页面布局(基本框架、页面布局、CSS样式、完善布局、效果展示,含完整代码)

目录 步骤 基本页面布局 基本框架 页面布局 CSS样式 完善布局 效果展示 完整代码 Element 的基本使用方式以及常见的组件已经了解完了&#xff0c;接下来要完成一个案例&#xff0c;通过这个案例让大家知道如何基于 Element 中的各个组件制作一个完整的页面。 案例&am…

Labview helper

IMAQ Advanced Setup Learn Geometric Pattern 2 VI 参数说明Curve Extraction Mode (0)指定VI如何识别图像中的曲线。如果您希望VI不对图像中对象的均匀性或图像背景做出任何假设&#xff0c;请将此选项设置为正常。如果您希望VI假定图像中的对象或图像背景由均匀的像素值组成…

PCL 最远点采样(FPS)

目录 一、概述 1.1原理 1.2实现步骤 1.3应用场景 二、代码实现 2.1关键函数 2.1.1 可视化函数 2.1.2 最远点采样 2.2完整代码 三、实现效果 PCL点云算法汇总及实战案例汇总的目录地址链接&#xff1a; PCL点云算法与项目实战案例汇总&#xff08;长期更新&#xff0…

事务原理,以及MVCC如何实现RC,RR隔离级别的

事务原理 redo log 保持持久性&#xff1a; 首先原来的情况是我们做一组操作的时候&#xff0c;先去操作bufferpool缓冲区&#xff0c;如果没有&#xff0c;那么后台线程将数据页换入换出到缓冲区&#xff0c;然后我们对这个buffer pool进行修改&#xff0c;为脏页&#xff0c…

Redis篇(Redis原理 - 数据结构)(持续更新迭代)

目录 一、动态字符串 二、intset 三、Dict 1. 简介 2. Dict的扩容 3. Dict的rehash 4. 知识小结 四、ZipList 1. 简介 2. ZipListEntry 3. Encoding编码 五、ZipList的连锁更新问题 六、QuickList 七、SkipList 八、RedisObject 1. 什么是 redisObject 2. Redi…

开放式耳机哪个品牌好?2024年蓝牙耳机排行榜

开放式蓝牙耳机以其独树一帜的佩戴方式&#xff0c;正逐渐成为音乐爱好者和运动达人的新宠。时尚而又实用。如果你对传统耳机的佩戴方式感到厌倦&#xff0c;或者在寻找一款既能提供高品质音乐体验又能兼顾佩戴舒适性的耳机&#xff0c;那么开放式蓝牙耳机可能会是你的理想选择…

Vue3轻松实现前端打印功能

文章目录 1.前言2.安装配置2.1 下载安装2.2 main.js 全局配置3.综合案例3.1 设置打印区域3.2 绑定打印事件3.3 完整代码4.避坑4.1 打印表格无边框4.2 单选框复选框打印不选中4.3 去除页脚页眉4.4 打印內容不自动换行1.前言 vue3 前端打印功能主要通过插件来实现。 市面上常用的…

【CKA】八、扩容Deployment

8、扩容Deployment 1. 考题内容&#xff1a; 2. 答题思路&#xff1a; 直接使用命令扩容就行 我考的题只是把 loadbalancer 名字换了 &#xff0c;其他都一模一样 3. 官网地址&#xff1a; https://kubernetes.io/zh-cn/docs/concepts/workloads/controllers/deployment/ …

Golang | Leetcode Golang题解之第451题根据字符出现频率排序

题目&#xff1a; 题解&#xff1a; func frequencySort(s string) string {cnt : map[byte]int{}maxFreq : 0for i : range s {cnt[s[i]]maxFreq max(maxFreq, cnt[s[i]])}buckets : make([][]byte, maxFreq1)for ch, c : range cnt {buckets[c] append(buckets[c], ch)}an…

【AI大模型】深入Transformer架构:编码器部分的实现与解析(上)

目录 &#x1f354; 编码器介绍 &#x1f354; 掩码张量 2.1 掩码张量介绍 2.2 掩码张量的作用 2.3 生成掩码张量的代码分析 2.4 掩码张量的可视化 2.5 掩码张量总结 &#x1f354; 注意力机制 3.1 注意力计算规则的代码分析 3.2 带有mask的输入参数&#xff1a; 3.…

华为开源自研AI框架昇思MindSpore应用案例:计算高效的卷积模型ShuffleNet

如果你对MindSpore感兴趣&#xff0c;可以关注昇思MindSpore社区 ShuffleNet ShuffleNet网络介绍 ShuffleNetV1是旷视科技提出的一种计算高效的CNN模型&#xff0c;和MobileNet, SqueezeNet等一样主要应用在移动端&#xff0c;所以模型的设计目标就是利用有限的计算资源来达到…

文章解读与仿真程序复现思路——电网技术EI\CSCD\北大核心《基于节点碳势响应的新型电力系统鲁棒优化调度 》

本专栏栏目提供文章与程序复现思路&#xff0c;具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 论文与完整源程序_电网论文源程序的博客-CSDN博客https://blog.csdn.net/liang674027206/category_12531414.html 电网论文源程序-CSDN博客电网论文源…

生信初学者教程(二十二):Boruta+RF筛选候选标记物

文章目录 介绍加载R包导入数据准备数据机器学习特征筛选数据分割基础模型Boruta特征筛选调参最终分类模型测试集验证标记基因输出结果总结介绍 采用了Boruta结合 RF(Random Forest) 的方法,对差异基因(参考 @sec-different-limma) 进行了特征筛选。通过这种方法,能够从大…

你以为瀑布流布局很复杂?Vue-Waterfall让你秒变前端高手

你以为瀑布流布局很复杂&#xff1f;Vue-Waterfall让你秒变前端高手 Vue-Waterfall 是一个轻量级的 Vue.js 组件&#xff0c;专为实现灵活的瀑布流布局设计。如果你需要在页面上呈现动态、响应式的布局&#xff0c;那这个组件绝对能帮到你&#xff01;本文将带你快速了解这个组…

推荐 uniapp 相对好用的海报生成插件

插件地址&#xff1a;自定义canvas样式海报 - DCloud 插件市场 兼容性也是不错的&#xff1a;

微软准备了 Windows 11 24H2 ISO “OOBE/BypassNRO“命令依然可用

Windows 11 24H2 可能在未来几周内开始推出。 微软已经要求 OEM 遵循新的指南准备好 Windows 11 24H2 就绪的驱动程序&#xff0c;并且现在已经开始准备媒体文件 (.ISO)。 OEM ISO 的链接已在微软服务器上发布。 一个标有"X23-81971_26100.1742.240906-0331.ge_release_sv…

[Python学习日记-35] Python 中的内置函数(上)

[Python学习日记-35] Python 中的内置函数&#xff08;上&#xff09; 简介 内置函数详解&#xff08;A-E&#xff09; 简介 在 Python 中有很多内置函数&#xff0c;例如 len()&#xff0c;这些函数是 Python 解释器自带的&#xff0c;可以直接使用。本篇将介绍 A-H 的内置函…

基于Springboot+Vue的《计算机基础》网上考试系统(含源码数据库)

1.开发环境 开发系统:Windows10/11 架构模式:MVC/前后端分离 JDK版本: Java JDK1.8 开发工具:IDEA 数据库版本: mysql5.7或8.0 数据库可视化工具: navicat 服务器: SpringBoot自带 apache tomcat 主要技术: Java,Springboot,mybatis,mysql,vue 2.视频演示地址 3.功能 系统中…

YOLOv11:重新定义实时目标检测的未来

YOLO 版本发布历史回顾 YOLO (You Only Look Once), a popular object detection and image segmentation model, was developed by Joseph Redmon and Ali Farhadi at the University of Washington. Launched in 2015, YOLO quickly gained popularity for its high speed a…

vulnhub-mrRobot靶机的测试报告

目录 一、测试环境 1、系统环境 2、使用工具/软件 二、测试目的 三、操作过程 1、信息搜集 2、渗透网页 3、Getshell 4、提权 四、结论 一、测试环境 1、系统环境 渗透机&#xff1a;kali2021.1(192.168.202.134) 靶 机&#xff1a;linux 3.13.0-55-generic #94-…