Android利用SurfaceView显示Camera图像爬坑记(二)

Android 摄像头预览 ---- SurfaceView 和 Camera 由于,SurfaceView 的 UI 就可以在一个独立的线程中进行绘制,不会占用主线程资源(SurfaceView 一方面可以实现复杂而高效的 UI,另一方面又不会导致用户输入得不到及时响应)。由于surface可能被销毁,它只在 SurfaceHolder.Callback.surfaceCreated() 和 SurfaceHolder.Callback.surfaceDestroyed()之间有效,所以要确保渲染线程访问的是合法有效的Surface。渲染线程所要访问的各种变量应该作同步处理。 阅读详情

前言
在这里插入图片描述

前一章《[Android利用SurfaceView显示Camera图像爬坑记(一)我们已经实现了利用SurfaceView将Camera中的实时帧图像显示出来了,我们做这个的主要目录是想把每一帧的数据取出后通过OpenCV图像处理后,再实时显示出处理后的图像。

要实现这个情况,我们首先要把Camera的实时数据存成Bitbmp的图像然后通过自己的处理显示出来,接下来我们就看看怎么样把Camera的实时图像都通过Bitbmp的方式显示出来。

代码实现

我们还是接上一篇的代码接着开始,还记得上一篇中我们的VaccaeSurfaceView类中定义了Camera的回调方法吗?

我们在程序运行后的LogCat里面可以查看到日志,输入的Log里面会不停的发送good字符串,如下图

上面就说明了我们的回调方法已经成功了,想到我们自己把图像处理显示出来,就可以在这个回调的方法中进行图片的处理。

这里简单介绍一下代码中的synchronized(this),当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。

简单的说就是我们获取的每一帧图像都会在这个代码里面处理完成了才处理下一帧图像。当然这里也可以用AnsycTask来进行实现。

实现原理及核心代码

我们在图像上按获取到的图片Bitbmp通过我们创建的SurfaceHolder来生成Canavas,然后在这个Canavas中能过drawBitbmp的方法绘制图片即可。

回调函数的代码

    private Camera.PreviewCallback previewCallback=new Camera.PreviewCallback() {
        @Override
        public void onPreviewFrame(byte[] bytes, Camera camera) {
            synchronized (this) {
                Log.i("frame", "good");
                int width=camera.getParameters().getPreviewSize().width;
                int height=camera.getParameters().getPreviewSize().height;
                Canvas canvas=holder.lockCanvas();
                if (canvas != null) {
                    canvas.drawColor(0, android.graphics.PorterDuff.Mode.CLEAR);
                    Bitmap cacheBitmap=nv21ToBitmap(bytes, width, height);
                    canvas.drawBitmap(cacheBitmap, 0, 0, null);
                    holder.unlockCanvasAndPost(canvas);
                }
            }
        }
    };

上图中对图像有一个nv21toBitmap的方法,就是用来生成图像的,我们看一下这个方法。

nv21ToBitmap

    //输出图像
    private static Bitmap nv21ToBitmap(byte[] nv21, int width, int height) {
        Bitmap bitmap=null;
        try {
            YuvImage image=new YuvImage(nv21, ImageFormat.NV21, width, height, null);
            ByteArrayOutputStream stream=new ByteArrayOutputStream();
            image.compressToJpeg(new Rect(0, 0, width, height), 80, stream);
            //将rawImage转换成bitmap
            BitmapFactory.Options options=new BitmapFactory.Options();
            options.inPreferredConfig=Bitmap.Config.ARGB_8888;
            bitmap=BitmapFactory.decodeByteArray(stream.toByteArray(), 0, stream.size(), options);

            stream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return bitmap;
    }

到目前为止看来我们已经完成了,接下来我们运行程序,程序中倒是一直在正常运行,不过我们看了一下LogCat中的记录,发现一直报错

在网上查找了一下原因,可能是camera.setPreviewDisplay(holder)这句有问题,相机一直在用这个holder像surfaceview输出图像,后面程序中再使用surfaceholder来绘制新的图片,就会冲突,然后报错。

找了找解决办法,发现可以用SurfaceTexture来代替实现这个图像的绘制,那我们按这个方法来试试

首先定义一个SurfaceTexture

然后在VaccaeSurfaceView构造函数中实例化这个SurfaceTexture

最后在StartCamera的方法加加入setPreviewTexture,并且屏蔽原来的seetPreviewDisplay的方法

接下来我们运行程序后,发现每一帧也都显示出来了,不过图像的方向不对,如下图

解决这个问题也比较简单,我们把我们的nv21ToBitmap处理图片的方法改造一下,让其直接也旋转90度即可。

nv21ToBitmap

    private static Bitmap nv21ToBitmap(byte[] nv21, int width, int height) {
        Bitmap bitmap=null;
        try {
            YuvImage image=new YuvImage(nv21, ImageFormat.NV21, width, height, null);
            ByteArrayOutputStream stream=new ByteArrayOutputStream();
            image.compressToJpeg(new Rect(0, 0, width, height), 80, stream);
            //将rawImage转换成bitmap
            BitmapFactory.Options options=new BitmapFactory.Options();
            options.inPreferredConfig=Bitmap.Config.ARGB_8888;
            bitmap=BitmapFactory.decodeByteArray(stream.toByteArray(), 0, stream.size(), options);

            //加入图像旋转
            Matrix m=new Matrix();
            m.postRotate(90);
            bitmap=Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(),
                    m, true);

            stream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return bitmap;
    }

我们重新运行程序的视频效果

上面视频可以看到,我们的图像已经正常了,但是图像显示出来的大小和我们的界面布局不一致,我们下一篇就针对这个问题来看看怎么处理。

最后

更多Android 学习资料可以扫码免费领取!

《Android编程入门指南》+Android基础课程资料包

内容概要:Android编程入门指南、Android基础课程资料包;

内容特点:条理清晰,含图像化表示更加易懂;

完整文档领取方式👇

# **《Android编程入门指南》**

目录

img

第一章 Java语言基础从入门到熟悉

​ ● Java综述

​ ● Java基础

​ ● class

​ ● 面向对象

​ ● 容器

​ ● 多线程

​ ● IO

​ ● 正则表达式

​ ● 日历

​ ● 注解使用与简单说明

​ ● Java使用加密算法

img

第二章 Kotlin语言基础从入门到熟悉

​ ● Kotlin系列简介

​ ● 新建项目

​ ● 概念介绍

​ ● 常用写法

​ ● lambda

​ ● 高阶函数

​ ● 扩展函数

​ ● 协程

img

第三章 Android 技术栈从入门到熟悉

​ ● 开始

​ ● Activity

​ ● Service 服务

​ ● Broadcast 广播机制

​ ● Fragment

​ ● res应用资源

​ ● 权限

​ ● TextView 显示文字

​ ● EditText 用户输入

​ ● Button 按钮

​ ● ImageView 图片显示

​ ● Layout布局

​ ● DrawerLayout侧滑栏

​ ● RecyclerView 显示列表

​ ● 多线程

​ ● IO 操作

​ ● 存储

​ ● NetWork 网络

​ ● ProgressBar进度条

​ ● View

​ ● 自定义View

​ ● 动画

​ ● WebView

​ ● StatusBar

​ ● Camera相机

​ ● Media

​ ● Bluetooth 蓝牙

​ ● WiFi连接

​ ● 获取手机当前角度

​ ● launcher

​ ● AIDL

​ ● zip

​ ● Binder

​ ● Notification 通知

​ ● PackageManager

​ ● RTFSC

​ ● 设计模式

​ ● 第三方库

​ ● Android Studio

​ ● 模块化

​ ● Gradle

​ ● NDK

​ ● 调试

img

第四章 Android Jetpack 全家桶全面学习

Android Camera系列(一):SurfaceView+Camera 本文介绍了Camera+SurfaceView的基本操作及关键代码,但是你如果看github中代码会发现和文中出入很大。其原因在于文章我想用一种简单的方式让没有做过自定义Camera的人也能明白。而github中的项目我已经进行了多次重构、抽象。其中包括对Camera的抽象,定义ICameraManager接口。对预览的View的重构,定义BaseCameraView接口,以及预览视图的众多超类。 阅读详情

相关推荐

FFmpeg保存camera yuv数据帧为jpeg图片

说明: 由于android原生的YuvImage.compressToJpeg()可能存在内存泄漏的情况,此处使用ffmpeg将yuv数据帧直接保存为jpeg图片。 输入:yuv数据,由camera采集的nv21数据 输出:jpeg图片 由于此处采样的是nv21数据,而最终保存的是YUVJ420P,因而需要对数据进行转换;若是输入为其它格式,则做相应的转换。 具体如下: 1.yuv帧转jpg图片: /** * @param dt 数据帧 * @param w 图片width * @param h 图片hei

dodo128的博客 2257

CameraSurfaceView——Android Camera使用详解

本篇文章将围绕自定义控件——CameraSurfaceView来阐述Android Camera(非Camera2,因为Camera2只适应5.0+的安卓系统,而目前5.0以下还是大部分,所以当前的主流还是Camera)的使用详解,首先先介绍下CameraSurfaceView,这是一个集拍照,录像,闪光灯,摄像头切换,前后台切换,自适应横竖屏于一体的SurfaceView,而我们平常使用Came

u012874222的博客 6528

Android Camera+SurfaceView实现自定义拍照

对Activity强制横屏,保证预览方向正确。使用OrientationEventListener监听设备方向,判断竖拍时,旋转照片后再保存,保证竖拍时预览图片和保存后的图片方向一致。       运行效果:                       代码: TestCameraActivity.java package com.example.testcamera;

u012964281的专栏 8097

Android利用SurfaceView显示Camera图像爬坑记(一)

前排

Misdirection_XG的博客 646

基于SurfaceView与Camera2 API的Android拍照功能实现

Android相机系统自诞生以来经历了多个版本的演进,其中最显著的技术跃迁之一便是从旧版CameraAPI(即 Camera1)过渡到功能更强大、控制粒度更精细的Camera2API。这一变革不仅提升了开发者对硬件底层能力的访问权限,也极大地增强了图像采集过程中的灵活性与可编程性。Camera2 API 于 Android 5.0(API Level 21)正式引入,采用基于“管道模型”的设计理念,将图像采集流程分解为多个可配置阶段,允许应用以近乎实时的方式干预曝光、对焦、帧率等关键参数。

weixin_29867767的博客 1106

神经算子:突破科学计算瓶颈的函数空间映射技术

神经算子(Neural Operators)是深度学习在科学计算领域的重要突破,它从根本上改变了处理连续物理问题的方式。与传统神经网络学习离散数据点映射不同,神经算子学习的是函数空间到函数空间的映射,这种范式转换使其具备离散化收敛性和超分辨率预测能力。在计算流体力学、天气预报等需要求解偏微分方程的场景中,神经算子能够在保持精度的同时将计算速度提升数个数量级。傅里叶神经算子(FNO)通过快速傅里叶变换实现高效计算,特别适合规则网格问题;而图神经算子(GNO)则擅长处理不规则网格和复杂几何形状。这种技术为参数敏

cuililai5127的博客 442

Android利用SurfaceView显示Camera图像爬坑记(四)

前言通过前面几篇,利用SurfaceView显示Camera的图像已经没什么问题了,接下来我们就要打磨一下细节,主要就是手机旋转的问题,考虑到我们会用横屏和竖屏的不同的情况。横竖屏问题用...

Vaccae的博客 709

Ubuntu桌面消失?可能是lightdm配置在捣鬼:详细解析/etc/lightdm.conf的优先级机制与实战修复

本文详细解析了Ubuntu系统因lightdm显示管理器配置错误导致桌面消失的问题。通过分析/etc/lightdm.conf的优先级加载机制,提供了从systemctl诊断、调试模式运行到实战修复配置语法错误(如缺失[Seat:*]组)的完整方案。文章还探讨了在系统无法启动时使用chroot或恢复模式进行高级救援,并对比了lightdm与gdm3在NVIDIA驱动环境下的不同表现,帮助用户高效恢复图形界面。

weixin_29313547的博客 420

Android利用SurfaceView显示Camera图像爬坑记(三)

前言前一章《Android利用SurfaceView显示Camera图像爬坑记(二)》我们已经利用SurfaceTexture通过生成的Bitmap图片用canvas画出显示,最后最后留...

Vaccae的博客 404

加速度计解算姿态角

姿态角(欧拉角) 欧拉角主要用于描述刚体在固定三维参考坐标系下由于绕三轴任意旋转而形成的姿态角,具体描述参看欧拉角说明 图中xyz为固定参考系坐标,XYZ为刚体自有坐标系 (假定右手定则,即大拇指指向某一轴正方向,握拳是其余手指的转动方向为姿态角变化的正方向),则定义 绕固定坐标系的z轴旋转:航向角yaw, 转动 y 角度 绕固定坐标系的y轴旋转:俯仰角pitch,转动p 角度 绕固定坐标系的x轴旋转:横滚角roll, 转动r 角度 可以看出欧拉角或者姿态角是相对各个轴的角度偏移,再假定旋转的顺规为Z

卢平光的博客 1万+

fluent linux运行算例,Fluent算例精选|03利用VOF和蒸发-冷凝模型

通过学习本算例您将获得?1、学会基本的VOF模型设置流程2、学会利用蒸发-冷凝模型来模拟传热沸腾目录1摘要42传热沸腾模型介绍43前处理44求解设置54.1启动Fluent54.2网格缩放64.3求解器设置74.4多相流模型设置84.5能量方程求解设置94.6紊流模型设置104.7添加材料114.8多相流中相设置124.9操作条件设置144.10边界条件设置154.10.1heatsource边界...

weixin_33278819的博客 3186

Android利用SurfaceView显示Camera图像爬坑记(六) -- 用OpenCV进行Canny边缘检测

前言上一篇《Android利用SurfaceView显示Camera图像爬坑记(五) -- 在现有项目中加入NDK配置》中我们已经把NDK加入到SurfaceView实时图像显示了,这一...

Vaccae的博客 412

【win11 cuda12.0安装tensorflow-gpu】

win11 cuda 12.0 安装 tensorflow-gpu

weixin_36299320的博客 3009

Android Camera SurfaceView 获取预览数据

简介 Android 调用相机拍照,相信大家已经很熟悉了,通过Intent指定Action和Category,再通过startActivityForResult()获取到拍照的回调,这样获取的是系统相机,我们只能得到它拍摄的图片,再进行后续处理。有些功能,比如视频直播,美颜相机,需要对相机预览的图像进行处理,这时候我们就需要通过Android的相机Camera来进行操作。文章主要...

renlei0012的博客 6171

迪文屏【0】——从零搭建工程:图片显示、文本变量配置与串口数据交互实战

本文以迪文屏T5L系列为例,详细介绍了从零搭建HMI工程的完整流程。内容涵盖硬件软件准备、DGUS工程创建、背景图片显示、文本变量配置,并重点演示了如何通过串口指令实时修改屏幕数据变量,实现动态交互。旨在帮助开发者快速掌握迪文屏开发的核心步骤与数据交互方法。

alpha的博客 349

小论文/大论文必备 | RT-DETR目标检测、数据集增强 | 引入多种数据集增强方法,支持图像和标签同步扩充增强,助力小论文和大论文实验涨点策略,平均提升模型mAP约1-2个百分点

RT-DETR目标检测数据增强策略研究 ,本文针对RT-DETR目标检测模型提出9种数据增强方法,包括几何变换(水平/垂直翻转、中心裁剪)、光照调整(亮度、对比度)和噪声添加(高斯/椒盐噪声)等。所有增强操作均保持图像与标签同步变换,确保训练数据的准确性。实验表明,该策略可提升模型mAP 1-2个百分点,对小目标检测效果尤为显著。文中提供了完整的Python实现代码,支持批量处理图像和标签文件,并详细说明了各增强方法的功能特点。该方法通过提升数据多样性,有效增强了模型在复杂场景下的鲁棒性和泛化能力。

Ai缝合怪、助力小伙伴高效发论文 460

Android Camera开发避坑指南:SurfaceView预览的正确打开方式

本文深入探讨了Android Camera开发中SurfaceView预览的核心机制与常见问题。针对生命周期管理、预览尺寸适配、画面方向校正等关键难点,提供了经过实战检验的健壮实现方案与性能优化建议,帮助开发者避免黑屏、拉伸等典型问题,实现稳定高效的相机预览功能。

2w3e4r5t6y的博客 893

SAP Business Technology Platform 支持的技术栈

SAP Business Technology Platform(简称 BTP)是 SAP 提供的一个综合技术平台,旨在帮助企业实现业务转型和创新。BTP 融合了数据库管理、应用开发、集成、分析和智能技术,为企业提供从基础架构到端到端应用的全面服务。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 1567

Android Camera SurfaceView

这个类图以camera预览为场景。从类图中可以看出, SurfaceView继承自(is-a)View SurfaceView中有一个SurfaceHolder,可以通过getHolder得到这个holder,这个holder有一个方法addCallback(Callback callback),可以向这个类中注册一个Callback(MainActivity),并且SurfaceHold...

1006

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

Android 分别使用 SurfaceView 和 TextureView 来预览 Camera,获取NV21数据

本文目的 使用 Camera API 进行视频的采集,分别使用 SurfaceView、TextureView 来预览 Camera 数据,取到 NV21 的数据回调 准备工作 添加相机权限 <uses-permission android:name="android.permission.CAMERA" /> 注意:camera预览回调中默认使用NV21格式 UI 准备 &...

LiPine的专栏 4119

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

解决SurfaceView预览Camera拉伸问题

在android中实现录制视频时,都会要求实现一个视频预览的功能(一般都是全屏预览),实现方式就是用SurfaceView来实时显示Camera传递过来的图像。 但是我们都知道,android手机的屏幕尺寸千奇百怪,使用默认的预览尺寸,部分手机会导致SurfaceView显示时图像拉长,整个人的脸看起来比驴脸还长;如果设置Camera的预览尺寸为屏幕尺寸,那么如果刚好Camera不兼容这个尺寸,

乌龟赛跑 1万+

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

Android Camera APP preview buffer 总体流程

Camera sensor获取自然图像(图像代表着image data buffer)通过ISP处理之后到显示器显示,这个过程代表着buffer从camera到display的传输,也是camera module中一个重要的流程,在此博客中和大家分享。

chinamaoge的博客 2459

hardware.Camera及SurfaceView

使用Camera进行拍照,在预览图上有边框,拍摄的图片是边框中的部分。 原理:Camera实现拍照,必须使用一个SurfaceView做为屏幕,用来显示预览图片。而边框可以使用另一个Surfaceview,两个SurfaceView采用帧布局。把底部的SurfaceView设置为Camera的预览区域,顶部是用来进行边框显示。 图为: 布局为: <LinearLayout xmln

飞鸟 1294

Android利用SurfaceView显示Camera图像爬坑记(五) -- 在现有项目中加入NDK配置

前言前面几章我们已经把SurfaceView加载Camera实现实时帧显示图像完成了,我也说过,我们加载实时图像是为了对接OpenCV进行图像处理所以才生成的Bitmap图像。《Open...

Vaccae的博客 322
上一篇: Android利用SurfaceView显示Camera图像爬坑记(一)
下一篇: 关于大厂Android开发岗面试,需要准备些什么!【附大厂面试真题】
网络安全-XG
博客等级 码龄5年 1万+粉丝 2752原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值