当前位置: 首页 > news >正文

Android摄像头采集选Camera1还是Camera2?

Camera1还是Camera2?

好多开发者纠结,Android平台采集摄像头,到底是用Camera1还是Camera2?实际上,Camera1和Camera2分别对应相机API1和相机API2。Android 5.0开始,已经弃用了Camera API1,新平台重点开发Camera API2,Camera API1 会逐渐被淘汰。Camera API2 框架为应用提供更接近底层的相机控件,包括高效的零复制连拍/视频流以及曝光、增益、白平衡增益、颜色转换、去噪、锐化等方面的每帧控件。

Camera2 相对Camera1有哪些优势?

1. 更灵活的相机控制

  • 细粒度参数调整:Camera2 API提供了更多的相机参数和配置选项,开发者可以更精确地控制相机的焦距、曝光时间、ISO感光度、白平衡等,以满足不同场景下的需求。
  • 多摄像头支持:能够同时管理和控制多个相机设备,包括前置摄像头、后置摄像头以及其他可用的摄像头,提高了系统的灵活性和扩展性。

2. 更高的性能

  • 异步操作:Camera2 API使用异步操作模式,减少了对UI线程的阻塞,提高了应用的响应速度和流畅性。
  • 并发访问:支持并发访问和操作多个相机设备,提高了相机的利用率和整体性能。

3. 更好的图像处理能力

  • RAW图像捕获:支持原生的RAW图像捕获和处理,开发者可以获取到相机传感器的原始数据,进行更高质量的图像处理和分析。
  • 实时预览和后处理:提供实时的图像预览和后处理功能,有助于开发者实现更丰富的图像效果。

4. 更好的适配性和扩展性

  • 统一的接口和架构:Camera2 API提供了更统一的接口和更清晰的架构,便于开发者进行相机功能的开发和适配。
  • 功能扩展:允许开发者通过CameraCharacteristics和CaptureRequest等接口获取和设置摄像头的各种功能和参数,支持自定义功能的开发。

5. 广泛的应用场景

  • 相机应用开发:Camera2 API提供了丰富的相机控制接口,可以用于开发各种相机应用,如拍照、录像、实时滤镜等。
  • 视频通话和实时视频应用:支持高质量的视频捕获和处理,适用于视频通话、视频会议等实时视频应用。
  • 计算机视觉和图像处理:结合OpenCV等图像处理库,可以进行实时的图像分析、特征提取、目标识别等计算机视觉任务。

如何使用Camera2进行相机操作

使用Android的Camera2 API来进行相机操作,包括预览、拍照等功能,是一个相对复杂但功能强大的过程。以下是一个基本的步骤指南,帮助你开始使用Camera2 API:

1. 添加权限

首先,你需要在AndroidManifest.xml文件中添加必要的权限,以便应用能够访问设备的相机。至少需要添加相机权限:

<uses-permission android:name="android.permission.CAMERA"/>

如果你的应用还需要录制视频或音频,还需要添加相应的权限:

<uses-permission android:name="android.permission.RECORD_AUDIO"/>  
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>  
<uses-feature android:name="android.hardware.camera" android:required="true"/>  
<uses-feature android:name="android.hardware.camera.autofocus"/>

需要注意的是,从Android 6.0(API 级别 23)开始,需要在运行时请求这些权限,而不是仅仅在清单文件中声明。

2. 初始化CameraManager

在你的Activity或Fragment中,首先需要获取CameraManager的实例,这个类是用于管理设备上的相机资源:

CameraManager cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);

3. 获取相机ID

使用CameraManagergetCameraIdList()方法获取设备上所有可用的相机列表,并选择一个相机ID进行后续操作。通常,后置摄像头的ID是"0",前置摄像头的ID是"1",但这不是绝对的,需要根据实际情况判断:

try {  String[] cameraIdList = cameraManager.getCameraIdList();  for (String cameraId : cameraIdList) {  CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(cameraId);  // 根据需要选择合适的相机,例如选择后置摄像头  if (characteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_BACK) {  // 选择后置摄像头  break;  }  }  
} catch (CameraAccessException e) {  e.printStackTrace();  
}

4. 打开相机

使用CameraManageropenCamera()方法打开选定的相机。这个方法是异步的,并且需要一个CameraDevice.StateCallback来接收相机打开的结果:

cameraManager.openCamera(cameraId, new CameraDevice.StateCallback() {  @Override  public void onOpened(@NonNull CameraDevice cameraDevice) {  // 相机打开成功,可以进行后续操作  }  @Override  public void onDisconnected(@NonNull CameraDevice cameraDevice) {  // 相机断开连接  }  @Override  public void onError(@NonNull CameraDevice cameraDevice, int error) {  // 打开相机发生错误  }  
}, null);

5. 创建CameraCaptureSession

一旦相机成功打开,你需要创建一个CameraCaptureSession来进行预览、拍照等操作。这个过程也是异步的,并且需要设置Surface来接收相机数据(如TextureView或SurfaceView):

cameraDevice.createCaptureSession(Arrays.asList(surface), new CameraCaptureSession.StateCallback() {  @Override  public void onConfigured(@NonNull CameraCaptureSession session) {  // 会话创建成功,可以开始预览或拍照  }  @Override  public void onConfigureFailed(@NonNull CameraCaptureSession session) {  // 会话配置失败  }  
}, null);

6. 预览和拍照

CameraCaptureSession配置成功后,你可以通过调用setRepeatingRequest()方法来开始预览,并通过调用capture()方法来拍照。这些操作都需要CaptureRequest对象,该对象描述了捕获请求的各种参数:

CaptureRequest.Builder previewRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);  
// 设置预览的参数...  
previewRequestBuilder.addTarget(surface);  // 预览  
cameraCaptureSession.setRepeatingRequest(previewRequestBuilder.build(), null, null);  // 拍照  
CaptureRequest.Builder captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);  
// 设置拍照的参数...  
captureRequestBuilder.addTarget(imageReader.getSurface());  
cameraCaptureSession.capture(captureRequestBuilder.build(), captureCallback, null);

7. 释放资源

当相机不再需要时,你应该及时释放相关资源,避免内存泄漏等问题。

如何从Camera1和Camera2获取原始数据?

我们在做Android平台RTMP推送、轻量级RTSP服务、实时录像和GB28181设备对接模块的时候,都需要用到摄像头采集,早期,我们提供了Camera1的采集demo,后面碎渣Camera2的优势越来越明显,高版本设备已成主流,目前一般建议采用Camera2的采集。

先说针对Camera1的采集和数据投递处理:

/** CameraPublishActivity.java* Author: daniusdk.com* WeChat: xinsheng120*/
@Override
public void onPreviewFrame(byte[] data, Camera camera) {frameCount++;if (frameCount % 3000 == 0) {Log.i("OnPre", "gc+");System.gc();Log.i("OnPre", "gc-");}if (data == null) {Parameters params = camera.getParameters();Size size = params.getPreviewSize();int bufferSize = (((size.width | 0x1f) + 1) * size.height * ImageFormat.getBitsPerPixel(params.getPreviewFormat())) / 8;camera.addCallbackBuffer(new byte[bufferSize]);} else {if (isRTSPPublisherRunning || isPushingRtmp || isRecording || isPushingRtsp) {if (1 == video_opt_) {libPublisher.SmartPublisherOnCaptureVideoData(publisherHandle, data, data.length, currentCameraType, currentOrigentation);} else if (3 == video_opt_) {int w = videoWidth, h = videoHeight;int y_stride = videoWidth, uv_stride = videoWidth;int y_offset = 0, uv_offset = videoWidth * videoHeight;int is_vertical_flip = 0, is_horizontal_flip = 0;int rotation_degree = 0;// 镜像只用在前置摄像头场景下if (is_mirror && FRONT == currentCameraType) {// 竖屏, (垂直翻转->顺时旋转270度)等价于(顺时旋转旋转270度->水平翻转)if (PORTRAIT == currentOrigentation)is_vertical_flip = 1;elseis_horizontal_flip = 1;}if (PORTRAIT == currentOrigentation) {if (BACK == currentCameraType)rotation_degree = 90;elserotation_degree = 270;} else if (LANDSCAPE_LEFT_HOME_KEY == currentOrigentation) {rotation_degree = 180;}int scale_w = 0, scale_h = 0, scale_filter_mode = 0;libPublisher.PostLayerImageNV21ByteArray(publisherHandle, 0, 0, 0,data, y_offset, y_stride, data, uv_offset, uv_stride, w, h,is_vertical_flip, is_horizontal_flip, scale_w, scale_h, scale_filter_mode, rotation_degree);}}camera.addCallbackBuffer(data);}
}

再说针对Camera2的数据投递处理:

/** Camera2Activity.java* Author: daniusdk.com* WeChat: xinsheng120*/
@Override
public void onCameraImageData(Image image) {Image.Plane[] planes = image.getPlanes();int w = image.getWidth(), h = image.getHeight();int y_offset = 0, u_offset = 0, v_offset = 0;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控制更灵活,性能、图像处理能力优异、适配性和扩展性也好,在版本支持的前提下,一般建议采用Camera2实现摄像头采集技术诉求,以上是Camera1和Camera2技术扫盲和技术探讨,感兴趣的开发者,可以单独跟我沟通探讨。

相关文章:

Android摄像头采集选Camera1还是Camera2?

Camera1还是Camera2&#xff1f; 好多开发者纠结&#xff0c;Android平台采集摄像头&#xff0c;到底是用Camera1还是Camera2&#xff1f;实际上&#xff0c;Camera1和Camera2分别对应相机API1和相机API2。Android 5.0开始&#xff0c;已经弃用了Camera API1&#xff0c;新平台…...

零基础5分钟上手亚马逊云科技AWS核心云开发/云架构 - 创建高可用数据库集群

简介&#xff1a; 欢迎来到小李哥全新亚马逊云科技AWS云计算知识学习系列&#xff0c;适用于任何无云计算或者亚马逊云科技技术背景的开发者&#xff0c;让大家零基础5分钟通过这篇文章就能完全学会亚马逊云科技一个经典的服务开发架构方案。 我将每天介绍一个基于亚马逊云科…...

力扣315.计算右侧小于当前元素的个数

力扣315.计算右侧小于当前元素的个数 离散化 树状数组 const int N 100010;int tr[N],n;class Solution {public:vector<int> countSmaller(vector<int>& nums) {n nums.size();vector<int> tmp(nums);vector<int> res(n);memset(tr,0,sizeo…...

websocket,css动画和css-position、display、区别

一、websocket codereturn {// 用于存储 WebSocket 返回的状态数据statusList: [],},mounted() {this.setupWebSocket();this.startBlinking();},methods: {setupWebSocket() {// 创建 WebSocket 连接const socket = new WebSocket(ws://xxx.xxx:xxx/xxx);// WebSocket 连接成功…...

前端获取视频文件宽高信息和视频时长

安装 yarn add video-metadata-thumbnails | npm install video-metadata-thumbnails引入依赖包 import { getMetadata } from video-metadata-thumbnails使用 if (file.name.includes(mp4)) {if (file) {try {console.log(file)// 获取视频的元数据const metadata await …...

【区块链+医疗健康】基于区块链的药品类监管应用管理系统 | FISCO BCOS应用案例

退热类药品的购药信息及政企互动信息等各项数据的安全性、保密性、真实性&#xff0c;不仅影响着监管部门的科学监管、 有效监管&#xff0c;也影响着企业的经营安全、诚信口碑&#xff0c;是区域药品安全监管工作进展的直观体现。 江苏数予科技有限公司构建基于区块链的药品类…...

MySQL4多表查询 内连接

多表查询 数据准备 CREATE DATABASE db4; USE db4; -- 创建部门表 create table if not exists dept(deptno varchar(20) primary key , -- 部门号name varchar(20) -- 部门名字 );-- 创建员工表 create table if not exists emp(eid varchar(20) primary key , -- 员工编号…...

Java -数组

1.一维数组 1.1数组定义 public class Main {public static void main(String[] args) throws Exception {int[] a new int[10];float[] f new float[10];double[] d new double[10];char[] c new char[10];} } 1.2 初始化 public class Main {public static void main(S…...

.prettierrc.js 有什么用

.prettierrc.js 是 Prettier 代码格式化工具的配置文件。 1. 作用 Prettier 是一个用于统一代码风格的工具&#xff0c;它可以使代码更具可读性和一致性。.prettierrc.js 文件用于自定义 Prettier 的格式化规则。 通过配置 .prettierrc.js&#xff0c;团队中的开发者可以遵循…...

haproxy七层代理

一.haproxy的基本部署 1.RS上装nginx [rootwebserver1 ~]# dnf install nginx -y 2.再RS上写入测试信息 [rootwebserver1 ~]# echo webserver1 - 172.25.254.10 > /usr/share/nginx/html/index.html [rootwebserver1 ~]# systemctl enable --now nginx [rootwebserver…...

<数据集>柑橘缺陷识别数据集<目标检测>

数据集格式&#xff1a;VOCYOLO格式 图片数量&#xff1a;1290张 标注数量(xml文件个数)&#xff1a;1290 标注数量(txt文件个数)&#xff1a;1290 标注类别数&#xff1a;4 标注类别名称&#xff1a;[Orange-Green-Black-Spot, Orange-Black-Spot, Orange-Canker, Orange…...

Go开发后端和Vue3开发前端的前后端分离框架中自己手戳一个OA流程审批、工作流引擎给新时代一个漂亮便捷的工作流引擎

前言 在软件项目开发中&#xff0c;我们都会接触到流程审批的需要业务&#xff0c;我们以往用的最多就是如下图这种流程编辑引擎插件&#xff1a; 以上截图中的流程工具是不是大家常见的呀&#xff01;感觉很丑拿不出手呀&#xff01;在当前行业内卷及竞争激烈情况下&#xff…...

深入理解 toDto 与 toEntity:结合 Eladmin 框架的最佳实践

在现代软件开发中&#xff0c;尤其是后端开发中&#xff0c;数据传输对象&#xff08;DTO&#xff09;和实体对象的转换是一个常见且重要的操作。理解和正确实现这种转换不仅能提高代码的可维护性&#xff0c;还能提升应用的性能和安全性。本文将深入探讨 toDto 和 toEntity 方…...

基于区块链的供应链应用开发

区块链的供应链溯源应用开发 一 、环境准备 (1)更新镜像源 apt update(2)安装(openssl、jdk、git) apt -y install openssl default-jdk git(3)配置JAVA_HOME环境变量 echo “export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64/” >> /etc/profilesource /etc…...

获取GORM执行时的sql字符串

示例&#xff1a; import "log" func GetDetail(tx *gorm.DB,id int)(data any,err error){var query tx.Session(&gorm.Session{DryRun: true})err query.Where("id ?", id).First(&res).Errorif err!nil{zap.L().Error("get detail er…...

Linux系统使用Docker安装RStudio服务并实现任意浏览器远程访问

文章目录 前言1. 安装RStudio Server2. 本地访问3. Linux 安装cpolar4. 配置RStudio server公网访问地址5. 公网远程访问RStudio6. 固定RStudio公网地址 前言 RStudio Server 使你能够在 Linux 服务器上运行你所熟悉和喜爱的 RStudio IDE&#xff0c;并通过 Web 浏览器进行访问…...

【原创】springboot+mysql法律咨询网设计与实现

个人主页&#xff1a;程序猿小小杨 个人简介&#xff1a;从事开发多年&#xff0c;Java、Php、Python、前端开发均有涉猎 博客内容&#xff1a;Java项目实战、项目演示、技术分享 文末有作者名片&#xff0c;希望和大家一起共同进步&#xff0c;你只管努力&#xff0c;剩下的交…...

Vue 应用实例的关键方法与配置案例二

目录 createApp createSSRApp app.mount app.unmount app.component app.directive Vue3.X自定义全局指令 Vue2.X自定义全局指令 app.use app.mixin 非 VIP 用户能够免费下载博文资源 createApp 详见上一章节:Vue 应用实例的关键方法与配置案例一-CSDN博客 createSS…...

Java面试题--JVM大厂篇之破解 JVM 性能瓶颈:实战优化策略大全

目录 引言: 正文: 1. 常见的JVM性能问题 频繁的GC导致应用暂停 内存泄漏导致的内存不足 线程争用导致的CPU利用率过高 类加载问题导致的启动时间过长 2. 优化策略大全 2.1 代码层面的优化 2.1.1 避免不必要的对象创建 2.1.2 优化数据结构的选择 2.1.3 使用并发工具…...

Apache Curator 创建节点时,如果节点存储就会抛出异常吗?

在Apache Curator中&#xff0c;创建节点时&#xff0c;如果该节点已经存在&#xff0c;并且你的代码没有正确处理这种情况&#xff0c;那么会抛出NodeExistsException异常。这是ZooKeeper客户端库&#xff08;包括Curator&#xff09;的常见行为&#xff0c;因为它需要确保Zoo…...

深入解析gbplanner_ros:基于图的自主探索路径规划算法在复杂地下环境中的应用

1. 什么是gbplanner_ros&#xff1f; 如果你正在研究机器人自主探索技术&#xff0c;特别是针对地下矿洞这类复杂环境&#xff0c;那么gbplanner_ros这个基于图的路径规划算法可能会引起你的兴趣。我第一次接触这个算法是在一个地下管道巡检机器人项目中&#xff0c;当时我们尝…...

3步掌控微信数据主权:从聊天记录备份到社交价值挖掘的完整指南

3步掌控微信数据主权&#xff1a;从聊天记录备份到社交价值挖掘的完整指南 【免费下载链接】WeChatMsg 提取微信聊天记录&#xff0c;将其导出成HTML、Word、CSV文档永久保存&#xff0c;对聊天记录进行分析生成年度聊天报告 项目地址: https://gitcode.com/GitHub_Trending/…...

专业级PDF自动化解决方案:如何构建高效文档工作流

专业级PDF自动化解决方案&#xff1a;如何构建高效文档工作流 【免费下载链接】clawPDF Open Source Virtual (Network) Printer for Windows that allows you to create PDFs, OCR text, and print images, with advanced features usually available only in enterprise solu…...

从《糖豆人》到《Among Us》:拆解Unity NetCode中NetworkTransform如何塑造不同的联机手感

从《糖豆人》到《Among Us》&#xff1a;NetworkTransform如何定义联机游戏的灵魂手感 当你在《糖豆人》的旋转平台上与对手挤作一团时&#xff0c;那种略带延迟的物理碰撞反馈&#xff1b;或是《Among Us》中看着队友角色突然"瞬移"到另一个房间的诡异同步——这些…...

开发实战:asp.net core + ef core 实现动态可扩展的分页方案

统一请求参数先定义一个公共的 QueryParameters 解决这个问题&#xff1a;public class QueryParameters{private const int MaxPageSize 100;private int _pageSize 10;public int PageNumber { get; set; } 1;// 限制最大值&#xff0c;防止前端传一个很大数值把数据库搞崩…...

百度网盘直链解析技术:突破下载限制的Python解决方案

百度网盘直链解析技术&#xff1a;突破下载限制的Python解决方案 【免费下载链接】baidu-wangpan-parse 获取百度网盘分享文件的下载地址 项目地址: https://gitcode.com/gh_mirrors/ba/baidu-wangpan-parse 在数字资源共享日益频繁的今天&#xff0c;百度网盘作为国内主…...

MATLAB/Simulink三相四桥臂逆变器仿真模型:电压外环电流内环控制策略下的负载平衡与...

matlab/simulink三相四桥臂逆变器仿真模型 采用的是电压外环电流内环控制策略&#xff0c;交流测可以接不平衡负载&#xff0c;在负载不平衡的情况下依然可以保持输出电压对称。 直流侧输入电压范围450V~2000V均可。 交流测输出电压为380/220V&#xff0c;不平衡负载和平衡负载…...

攻克高并发场景:基于快马平台生成黑马点评秒杀与缓存实战代码

今天想和大家分享一个实战项目经验——如何用InsCode(快马)平台快速搭建高并发场景下的黑马点评系统核心模块。这个项目最吸引我的地方在于&#xff0c;它完美复现了电商系统中那些让人头疼的高并发场景&#xff0c;比如秒杀、缓存一致性等问题。 秒杀功能的核心逻辑 优惠券秒…...

leetcode 189

找到了&#xff0c;这题和高级搜索树里面的就地循环移位是一个题。实际上就是一个经典问题&#xff0c;我记得在哪里&#xff0c;却不知道怎么解决。好像也知道一点&#xff0c;就是反转&#xff0c;然后再反转。利用空间局部性&#xff0c;把缓存的作用发挥到极致。注意这里的…...

一次性拖鞋自动下料系统设计超声波热熔裁剪机设计【论文+CAD图纸+solidworks三维+开题报告+任务书+实习调研报告+其它相关资料】

一次性拖鞋自动下料系统与超声波热熔裁剪机的设计&#xff0c;聚焦于提升拖鞋制造环节的效率与精度。传统拖鞋生产中&#xff0c;人工下料易受操作误差影响&#xff0c;导致材料浪费与产品尺寸偏差&#xff1b;而普通裁剪方式可能因热熔不充分&#xff0c;出现边缘毛刺或连接不…...