Android Camera2采集摄像头原始数据
作者:HBStream 发布时间:2021-06-23 22:55:53
最近研究了一下android摄像头开发相关的技术,也看了Google提供的Camera2Basic调用示例,以及网上一部分代码,但都是在TextureView等预览基础上实现,而我想要做的是在不预览的情况下,能获取到摄像头原始数据流,并由自己来决定是否绘制显示。经过一番折腾,初步实现了自己的目的—CamCap程序。
需求分析
其实主要就是在不预览的情况下获取到摄像头原始数据,目的嘛,一是为了灵活性,方便随时开启关闭预览,二是为了以后可以直接对数据进行处理,三是为了其他程序开发做一些准备。于是实现一下几个功能:
获取摄像头数据,并手动绘制图像 随时开启/关闭预览 随时保存当前摄像头图像,即使在关闭预览情况下 Android Camera2接口
查阅了一些资料,Android Java层由于从API21开始,已经废弃原Camera接口,所以这里采用Camera2接口。相比Camera接口来说,第二代摄像头接口,调用复杂多了,但是灵活性也更高了,通过Google的Camera2Basic例子可以很清楚的了解到使用方式。这里把CamCap程序中的Camera2的调用顺序整理如下:
和其他程序一样,通过ImageReader来获取到CameraCaptureSession传递出来的数据,与Google例子不同的是,我取消了把TextureView的传递,改为单独以ImageReader来获取图像流,并设置为YUV_420_888格式,以拿到原始数据。
打开摄像头
摄像头打开后,创建对话
调用libyuv做RGB之间的数据转换
获取到YUV数据之后,就可以在UI界面上进行绘制了,通过简单了解,可以通过OpenGLES来绘制,也可以转为Bitmap直接在TextureView上绘制。这里为了简单,选择了后者。然而后来发现,android.graphics.Bitmap并不支持直接将YUV数据存入,只能转为RGB数据格式,才能存入Bitmap,进而在TextureView上绘制。YUV转换RGB,之前在C++上应用过很多次了,可以把现有代码修改一下放到java里运行,不过考虑到性能问题,决定还是使用libyuv。libyuv是一款以c/c++为基础的,专做YUV与RGB格式转换的开源项目,性能非常高。
使用libyuv,需要通过NDK交叉编译,并通过JNI来调用。libyuv编译起来也很简单,首先下载libyuv源码,代码地址是:https://chromium.googlesource.com/libyuv/libyuv 。然后确保NDK已经安装(这个直接在AndroidStudio中就能安装好),之后把NDK目录添加到环境变量。最后,进入libyuv目录,调用ndk-build即可。libyuv项目里已经写好了Android.mk,所以,直接编译就行了(我是在Windows上)。
注意!编译的时候遇到JPEG库没有指定的问题,如果不想依赖libjpeg,可以修改Android.mk,删除JPEG库相关编译项就可以解决。
在AndroidStudio上建立c++文件,封装libyuv接口,然后按照JNI规范暴露接口,同时在Java层封装类来调用native方法。
绘制图像
在绘制图像的时候,有个坑,那就是图像的旋转,这个是由于手机上的摄像头传感器的视野坐标,一般都是旋转了90度或270度的,所以,需要把摄像头采集到的画面,进行旋转,才能还原出正确的视野画面。传感器旋转方向通过以下值获得,
CameraManager.getCameraCharacteristics(camid).get(CameraCharacteristics.SENSOR_ORIENTATION)
根据这个值,构建Matrix将Bitmap进行旋转
Matrix构建代码如下:
与上面代码中类似,通过TextureView.lockCanvas(),获取到Canvas,调用drawBitmap()将图像写入,即可完成绘制。
运行截图
开启预览时的4:3画面和16:9画面
关闭预览,同时可以继续拍照
来源:https://www.cnblogs.com/haibindev/p/8408598.html


猜你喜欢
- 本文主要为大家整理Java常见的面试题,供大家参考,具体内容如下1. Java中sleep和wait的区别① 这两个方法来自不同
- tokentoken的意思是“令牌”,是用户身份的验证方式,最简单的token组成:uid(用户唯一的身份标识)、time(当前时间的时间戳
- spring中实例化bean无效在做Struts2和Spring整合时遇到Spring实例化无效的情况,Action中代码如下public
- 先上ListView滑动改变标题栏背景渐变效果图,透明转变成不透明效果:图1:图2:图3:图4:我用的是小米Note手机,状态栏高度是55p
- 我遇到一个重复性操作,为了能偷懒发现idea的功能还比较实用纵列选择:Alt+鼠标左键大小写转换:Ctrl+Shirt+u使用小技巧:像这样
- 所谓c#图片处理高级应,多数是基于.net framework类库完成using system;using system.collectio
- 最近在学习springmvc,今天把springmvc 参数绑定给整理一下,也算个学习笔记吧!@RequestParam 绑定单个请求Req
- 一、Filefile是文件和目录路径名的抽象表示1.1 File的用法用法:File file = new File("路径名&q
- 路由做Android/iOS原生开发的时候,要打开一个新的页面,你得知道你的目标页面对象,然后初始化一个Intent或者ViewContro
- 登陆是系统最基础的功能之一。这么长时间了,一直在写业务,这个基础功能反而没怎么好好研究,都忘差不多了。今天没事儿就来撸一下。以目前在接触和学
- 本篇文章是直接下载最新的APK安装的方法,并不是增量下载该APk。想要实现一个android应用,自动更新下载APK软件的方法,我采取的是以
- 本篇文章主要介绍了java自动生成编号的实现,分享给大家,具体如下/** * 自动生成编号格式:yyMM+四位流水号 */ @Reques
- 一般使用@RequestBody接收的时候报400都是传入的json字符串和对应封装的对象不对应造成的首先要注意封装的对象中的字段类型有没有
- 本文介绍了C# 用什么方法将BitConverter.ToString产生字符串再转换回去,分享给大家,具体如下:byte[]
- C++中静态成员函数与静态成员变量(static )这篇介绍了静态成员函数与静态成员变量,是我的读书笔记,我希望它够简短但又比较全面,起到复
- 静默安装就是偷偷的把一个应用安装到手机上,就是屏蔽确认框,通过反射只能写个主要的代码,这个是在linux编译用到,因为静默安装需要调用系统服
- smoothstep另一种用法在之前OpenGL Shader-抗锯齿实现文章中所介绍的那样:为了抗锯齿效果可以用smoothstep函数对
- 四道Java基础题,你能对几道?一、==符的使用首先看一段比较有意思的代码Integer a = 1000,b=1000; Integer
- 这几天恰好和朋友谈起了递归,忽然发现不少朋友对于“尾递归”的概念比较模糊,网上搜索一番也没有发现讲解地完整详细的资料,于是写了这么一篇文章,
- 本文实例为大家分享了java金额数字转中文工具类的具体代码,供大家参考,具体内容如下java金额数字转中文工具类ConvertNum.jav