很久没有写安卓了,复习复习。用的是官方案例,详见opencv-Android-sdk

// 定义包名,表示该类的组织路径
package org.opencv.samples.tutorial1;// 导入所需的OpenCV和Android类库
import org.opencv.android.CameraActivity;  // OpenCV相机活动基类
import org.opencv.android.CameraBridgeViewBase.CvCameraViewFrame;  // 相机帧数据
import org.opencv.android.OpenCVLoader;  // OpenCV加载器
import org.opencv.core.Mat;  // OpenCV矩阵类,用于存储图像数据
import org.opencv.android.CameraBridgeViewBase;  // 相机视图基类
import org.opencv.android.CameraBridgeViewBase.CvCameraViewListener2;  // 相机监听接口
import org.opencv.android.Utils;  // OpenCV工具类
import org.opencv.core.Core;  // OpenCV核心功能
import org.opencv.imgproc.Imgproc;  // 图像处理模块
import org.opencv.photo.Photo;  // 照片处理模块
import org.opencv.core.*;  // OpenCV核心模块// 导入Android相关类库
import android.os.Bundle;  // 用于保存Activity状态
import android.util.Log;  // 日志工具
import android.view.SurfaceView;  // 表面视图
import android.view.WindowManager;  // 窗口管理
import android.widget.Toast;  // 提示消息
import android.widget.Button;  // 按钮控件
import android.view.View;  // 视图基类
import android.os.Environment;  // 环境信息
import android.graphics.Bitmap;  // 位图类// 导入Java工具类
import java.util.Collections;  // 集合工具
import java.util.ArrayList;  // 动态数组
import java.util.List;  // 列表接口
import java.io.File;  // 文件类
import java.io.FileOutputStream;  // 文件输出流
import java.text.SimpleDateFormat;  // 日期格式化
import java.util.Date;  // 日期类

Tutorial1Activity 类

定义

public class Tutorial1Activity extends CameraActivity implements CvCameraViewListener2

继承自 CameraActivity ( 是Activity 基类,它封装了对摄像头的基本处理逻辑,比如打开摄像头、获取帧数据等。)

接口声明

OpenCV 摄像头帧回调接口 CvCameraViewListener2。

implements CvCameraViewListener2

表示这个类 实现了 接口 CvCameraViewListener2,必须实现该接口的全部方法

这个接口是 OpenCV 提供的,用于处理来自摄像头的数据帧。它有几个关键方法:

public interface CvCameraViewListener2 {void onCameraViewStarted(int width, int height);void onCameraViewStopped();Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame);
}
方法作用
onCameraViewStarted()摄像头启动时初始化 Mat、变量等
onCameraViewStopped()摄像头停止时释放资源
onCameraFrame()每帧图像自动调用,可以处理图像

📌 各方法说明:

onCameraViewStarted(int width, int height):摄像头视图开始时调用。

onCameraViewStopped():摄像头视图停止时调用。

onCameraFrame(CvCameraViewFrame inputFrame):每帧图像采集时调用,可以在这里进行图像处理(如边缘检测、滤波等),返回 Mat 类型图像结果用于渲染显示。

构造函数

 // 构造函数public Tutorial1Activity() {// 打印日志,记录实例化信息Log.i(TAG, "Instantiated new " + this.getClass());}

定义

    // 定义日志标签常量定义一个日志标签(log tag),用于在 AndroidLogcat 控制台中打印日志。便于调试、排查错误,推荐每个类定义一个 TAGprivate static final String TAG = "OCVSample::Activity";// 声明相机视图对象声明一个 OpenCV 的摄像头视图控件,它负责打开摄像头、采集图像帧、并把图像送入 onCameraFrame() 回调处理。封装了摄像头的打开、预览、帧捕获、图像格式转换等功能。CameraBridgeViewBaseOpenCV for Android 提供的一个抽象类,常用的子类是 JavaCameraViewprivate CameraBridgeViewBase mOpenCvCameraView;// 声明拍照按钮在 onCreate 中设置利用 setOnClickListener 触发private Button mCaptureButton;// 声明存储RGBA图像的矩阵onCameraFrame() 回调函数中,OpenCV 会将摄像头捕获的帧传递进来private Mat mRgba;// HDR相关声明private Button mHdrButton;  // HDR按钮private boolean mIsCapturingHDR = false;  // HDR拍摄标志位private List<Mat> mExposureSequence = new ArrayList<>();  // 存储不同曝光图像的列表private static final float[] EXPOSURE_VALUES = {0.5f, 1.0f, 2.0f};  // 定义三种曝光值

函数解析

在 Android 中,Activity 有一个完整的生命周期管理,典型调用顺序如下:

onCreate() → 创建视图和变量

onStart() → Activity 对用户可见

onResume() → Activity 可交互(获取焦点)

onPause() → 准备进入后台

onStop() → Activity 不再可见

onDestroy() → Activity 被销毁

Activity 的构造函数 onCreate

系统会先调用隐藏的构造函数,然后调用 onCreate()。 当该 Activity 第一次被创建时(即启动时),系统会自动调用它。到 onCreate() 时,系统已经准备好了界面容器、上下文环境(Context)、资源引用、生命周期管理器。
这时才能用 findViewById方法

在 onCreate() 中,通常执行以下操作:

  1. 设置界面布局
setContentView(R.layout.activity_main);

加载 XML 中定义的 UI 界面。

  1. 初始化 UI 控件和变量
mOpenCvCameraView = findViewById(R.id.java_camera_view);
mCaptureButton = findViewById(R.id.capture_button);

完成变量与界面元素的绑定,准备用户交互。

  1. 设置控件监听器
mCaptureButton.setOnClickListener(v -> captureImage());

为按钮或其他 UI 元件设置回调函数。

  1. 初始化 OpenCV 或其他第三方库
OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION, this, mLoaderCallback);

加载 OpenCV 库并处理初始化回调。

// Activity创建时的回调方法
@Override 对父类 Activity 中的 onCreate 方法的重写。
Bundle savedInstanceState:
是一个用于存储界面状态的数据结构。
当 Activity 被意外销毁后(如屏幕旋转、被系统回收等),可以通过它恢复先前的状态。public void onCreate(Bundle savedInstanceState) {// 调用父类onCreate方法super.onCreate(savedInstanceState);// 打印日志Log.i(TAG, "called onCreate");// 初始化OpenCV本地库if (OpenCVLoader.initLocal()) {// 初始化成功日志Log.i(TAG, "OpenCV loaded successfully");} else {// 初始化失败日志Log.e(TAG, "OpenCV initialization failed!");// 显示初始化失败提示(Toast.makeText(this, "OpenCV initialization failed!", Toast.LENGTH_LONG)).show();return;}// 设置窗口标志,保持屏幕常亮getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);// 设置布局文件setContentView(R.layout.tutorial1_surface_view);// 获取相机视图引用XML 布局文件中声明的 OpenCV 摄像头预览控件绑定到 Java 代码中的变量 mOpenCvCameraView 上,以便后续调用方法控制摄像头。
强制类型转换,因为 findViewById() 返回的是通用类型 View,而你希望将它当作 CameraBridgeViewBase 来使用。
CameraBridgeViewBaseOpenCV 提供的抽象基类,定义了摄像头启动、停止、帧获取等功能。
JavaCameraView 是它的子类,真正实现了预览逻辑。mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.tutorial1_activity_java_surface_view);// 获取拍照按钮引用mCaptureButton = (Button) findViewById(R.id.capture_button);// 获取HDR按钮引用mHdrButton = (Button) findViewById(R.id.hdr_button);// 设置相机视图可见性mOpenCvCameraView.setVisibility(SurfaceView.VISIBLE);// 设置相机视图监听器mOpenCvCameraView.setCvCameraViewListener(this);// 设置拍照按钮点击监听器mCaptureButton.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {// 检查当前帧是否有效if (mRgba != null && !mRgba.empty()) {// 调用保存图像方法saveImage(mRgba);}}});// 设置HDR按钮点击监听器mHdrButton.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {// 设置HDR拍摄标志mIsCapturingHDR = true;// 清空曝光序列mExposureSequence.clear();// 显示提示信息Toast.makeText(Tutorial1Activity.this, "准备HDR拍摄,请保持手机稳定...",Toast.LENGTH_SHORT).show();}});}

CameraBridgeViewBase 是什么?
虽然 CameraBridgeViewBase 本质上是一个“视图组件”(View),但它不仅仅是用来显示摄像头图像,还内置了摄像头控制逻辑、帧采集机制和 OpenCV 回调接口对接。

它是 OpenCV for Android 提供的一个抽象类,负责:

功能说明
控制摄像头启动/停止封装了打开摄像头、释放摄像头资源的流程
帧采集循环自动开启后台线程采集图像帧
图像格式转换将 NV21/YUV 等图像转换为 OpenCV 可处理的 Mat 类型
接入回调让开发者通过接口拿到每一帧图像进行处理

帧采集 + 回调的完整机制

方法功能
setCvCameraViewListener(this)设置帧数据监听器,接收每一帧图像
enableView()内部会打开摄像头,启动采集线程,开始不断生成帧

OpenCV 内部怎么做的?

OpenCV 封装了以下逻辑:

  • 打开摄像头(通过 Camera / Camera2 API)

    后台线程循环采集图像帧(YUV 或 RGBA)

    转换为 Mat 类型(OpenCV 可处理格式)

    调用你实现的接口方法:

public Mat onCameraFrame(CvCameraViewFrame inputFrame) {// 每帧图像都走这里,你可以处理它return inputFrame.rgba(); // 或处理后返回
}

对应

你的代码↓
CameraBridgeViewBase↓
JavaCameraView / NativeCameraView↓
系统 Camera API↓
图像帧采集 → 自动转换为 Mat → 回调 onCameraFrame()
    // Activity暂停时的回调方法@Overridepublic void onPause() {// 调用父类方法super.onPause();// 如果相机视图存在,则禁用视图if (mOpenCvCameraView != null)mOpenCvCameraView.disableView();}// Activity恢复时的回调方法@Overridepublic void onResume() {// 调用父类方法super.onResume();// 如果相机视图存在,则启用视图if (mOpenCvCameraView != null)mOpenCvCameraView.enableView();}// 获取相机视图列表的方法@Overrideprotected List<? extends CameraBridgeViewBase> getCameraViewList() {// 返回包含单个相机视图的不可变列表return Collections.singletonList(mOpenCvCameraView);}// Activity销毁时的回调方法@Overridepublic void onDestroy() {// 调用父类方法super.onDestroy();// 如果相机视图存在,则禁用视图if (mOpenCvCameraView != null)mOpenCvCameraView.disableView();}// 相机视图启动时的回调方法@Overridepublic void onCameraViewStarted(int width, int height) {// 初始化RGBA矩阵mRgba = new Mat();}// 相机视图停止时的回调方法@Overridepublic void onCameraViewStopped() {// 如果RGBA矩阵存在,则释放资源if (mRgba != null) {mRgba.release();}}// 处理相机帧数据的回调方法@Overridepublic Mat onCameraFrame(CvCameraViewFrame inputFrame) {// 获取当前帧的RGBA数据mRgba = inputFrame.rgba();// 返回处理后的帧return mRgba;}

保存文件

// 保存图像到文件的方法private void saveImage(Mat mat) {// 创建与Mat相同尺寸的Bitmap对象Bitmap bmp = Bitmap.createBitmap(mat.cols(), mat.rows(), Bitmap.Config.ARGB_8888);// 将Mat转换为BitmapUtils.matToBitmap(mat, bmp);// 创建时间戳格式String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());// 生成文件名String imageFileName = "IMG_" + timeStamp + ".jpg";// 获取公共图片目录File storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);// 创建文件对象File imageFile = new File(storageDir, imageFileName);try {// 创建文件输出流FileOutputStream fos = new FileOutputStream(imageFile);// 压缩Bitmap为JPEG格式并写入文件bmp.compress(Bitmap.CompressFormat.JPEG, 100, fos);// 关闭输出流fos.close();// 显示保存成功提示Toast.makeText(this, "照片已保存: " + imageFile.getAbsolutePath(),Toast.LENGTH_LONG).show();} catch (Exception e) {// 记录保存失败日志Log.e(TAG, "保存照片失败", e);// 显示保存失败提示Toast.makeText(this, "保存照片失败", Toast.LENGTH_SHORT).show();}}

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

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

相关文章

Web中间件性能调优指南:线程池、长连接与负载均衡的最佳实践

目录 引言一、Web容器线程池配置不当1.1 线程池参数的核心作用与影响1.2 线程池大小计算模型1.3 动态调优实践 二、Keep-Alive机制配置缺陷2.1 Keep-Alive的工作原理2.2 典型配置问题与影响2.3 优化配置建议 三、负载均衡策略缺失3.1 负载均衡的核心价值3.2 主流负载均衡算法对…

15个AI模拟面试平台 和 简历修改 / 真人面试平台

对15个AI模拟面试平台的详细分析&#xff0c;每个平台都将按照统一的框架进行评估。 补充重要的&#xff1a; 【1】AMA interview 听说最好&#xff0c;最贵 1. Final Round AI 网址: https://www.finalroundai.com/ 功能深度剖析: Final Round AI 提供了一套全面的求职工具…

开始使用 Elastic AI Assistant for Observability 和阿里 Qwen3

这篇文章是继之前的文章 “在本地电脑中部署阿里 Qwen3 大模型及连接到 Elasticsearch” 的续篇。如果你还没有部署好自己的 Qwen3&#xff0c;那么请阅读之前的那篇文章来安装好环境&#xff0c;然后再继续今天练习。在今天的文章中&#xff0c;我们将展示如何结合 Qwn3 和 El…

稳定币技术全解:从货币锚定机制到区块链金融基础设施

引言&#xff1a;稳定币的技术定位 根据国际清算银行&#xff08;BIS&#xff09;2025年定义&#xff1a;稳定币是以法定资产或算法机制维持价值稳定的区块链代币&#xff0c;其本质是传统金融与加密技术的接口层。 核心价值&#xff1a;解决加密货币波动性问题 → 成为DeFi生态…

syncthing忘记密码怎么办(Mac版)?

一、问题描述 syncthing安装在Mac端&#xff0c;更改原同步文件夹的路径&#xff0c;需要重新设计同步文件&#xff0c;设置了密码且忘记密码。未看见忘记密码的选项。 网上查询解决方案&#xff0c;发现只能通过修改配置文件才能继续正常访问。但是并没有在建议路径中找到配置…

半导体FAB中的服务器硬件故障监控与预防全方案:从预警到零宕机实战

&#x1f4ca; 服务器硬件故障监控与预防全方案&#xff1a;从预警到零宕机实战 关键词&#xff1a;SMART监控 RAID预警 IPMI传感器 性能基线 Prometheus Zabbix 高可用架构 一、硬件故障前的7大预警信号&#xff08;附关联工具&#xff09; 故障类型关键指标监控工具预警阈值…

一分钟了解Transformer

一分钟了解Transformer A Minute to Know About Transformer By JacksonML 1. Transformer是什么&#xff1f; Transformer模型是一种神经网络&#xff0c;它通过学习上下文及其含义&#xff0c;跟踪序列数据中&#xff08;如本句中的单词&#xff09;中的关系。Transforme…

【Ubuntu学习】嵌入式编译工具链熟悉与游戏移植

目录 一、Ubuntu 系统编译 MININIM 源码 1. 环境准备与依赖配置 2. 编译 Allegro5.2.5 引擎 ​编辑 3. 编译 MININIM 源码 4. 故障解决 5. 打包与迁移 二、嵌入式平台编译实践 1. 树莓派 3B 编译 MININIM 2. Android 平台交叉编译 三、树莓派 3B 流水灯实验&#xf…

川翔云电脑全新上线:三维行业高效云端算力新选择

一、核心定位与优势 云端虚拟工作站服务 依托云端高性能 CPU/GPU 集群&#xff0c;提供远程桌面服务&#xff0c;支持普通设备运行专业软件。 按需付费模式&#xff1a;无需采购高端硬件&#xff0c;大幅降低成本投入。生态协同优势&#xff1a;与渲染 101 同属母公司&#…

百面Bert

百面Bert Q1. Bert与Transformer有什么关系 Bert是基于Transformer架构中的Encoder进行搭建的。 具体来说&#xff0c;Bert的核心组件是几个Encoder layer的堆叠。Encoder layer中&#xff0c;也是两个子层&#xff0c;分别是注意力层和intermediate层&#xff08;Bert中的叫…

Docker Compose与私有仓库部署

目录 一. Docker 重启策略 二. Docker Compose工具的应用 1. 什么是 Docker compose 2. Docker compose 的安装 3. 编辑文件格式及编写注意事项 4. docker-compose的基本用法 三. Harbor私有仓库 1. 什么是Harbor 2. Harbor 的优势 3. Harbor 的构成 四. 部署Harbor…

数字隔离器,如何扛起现代智能家电的电气安全“大旗”

随着现代社会生活节奏的不断加速&#xff0c;人们对于属于自己的休闲时间愈发珍视&#xff0c;而智能家居作为提升人类居家幸福感与舒适度的现代化产物&#xff0c;不仅能有效满足人们对高品质生活的追求&#xff0c;还能推动产业升级与经济增长&#xff0c;引导智能家电设备从…

mybatis3调用瀚高procedure报错(APP)

文章目录 环境文档用途详细信息 环境 系统平台&#xff1a;Linux x86-64 Red Hat Enterprise Linux 7 版本&#xff1a;4.5 文档用途 mybatis3调用瀚高procedure报错&#xff08;错误信息&#xff1a;调用过程请使用CALL&#xff09;的解决方案。 详细信息 客户项目中使用…

96道Docker 容器高频题整理(附答案背诵版)

简述什么是 Docker 容器&#xff1f; Docker容器是一个开源的应用容器引擎&#xff0c;它让开发者可以将他们的应用以及依赖包打包到一个可移植的容器中&#xff0c;然后发布到任何安装了Docker引擎的服务器上&#xff0c;包括流行的Linux机器、Windows机器等。Docker容器利用…

成都芯谷金融中心·文化科技园打造文化科技高地

成都芯谷金融中心正式启动运营&#xff0c;标志着双流区集成电路产业生态圈的关键拼图落位。该项目以"文化科技金融"融合发展为核心理念&#xff0c;旨在构筑服务区域实体经济的创新引擎。 核心战略定位与区域价值 产业赋能枢纽&#xff1a;深度聚焦集成电路、新型…

IntelliJ IDEA 加速优化指南

IntelliJ IDEA 加速优化指南 IntelliJ IDEA 是一款功能强大的 IDE&#xff0c;但随着项目规模增大和长期使用&#xff0c;可能会出现性能下降的情况。以下是一些有效的加速优化方法&#xff1a; 1. 基础配置优化 内存分配调整 修改 idea.vmoptions 文件 (位置&#xff1a;H…

基于YOLO的智能车辆检测与记录系统

基于YOLO的智能车辆检测与记录系统 摘要 本报告总结了智能车辆检测系统的开发工作&#xff0c;主要包括车辆数据标注、YOLO模型训练及QT交互系统搭建三部分。通过使用专业标注工具完成车辆目标数据集的标注与预处理&#xff0c;基于YOLO模型构建车辆检测算法并优化训练流程&a…

网络调试的艺术:利用浏览器Network工具优化你的网站

&#x1f9ed; General&#xff08;通用信息&#xff09; General 部分通常包含请求的基本信息&#xff0c;如请求方法、URL、协议版本等 字段名称描述常见值示例Request URL请求的完整地址&#xff08;包括协议、域名、路径、查询参数&#xff09;https://example.com/api/d…

Mongodb数据库应用

目录 什么是mongodb 主要特点 MongoDB 概念解析 完整术语列表 MongoDB 安装 MongoDB Shell 安装 MongoDB Shell 验证 MongoDB Shell 数据库管理 查看数据库列表 创建数据库 实例 删除数据库 实例 默认数据库 系统内置数据库 集合管理 查看集合 创建集合 实…

以太网基础与 VLAN 配置实验

以太网是一种基于CSMA/CD(Carrier Sense Multiple Access/Collision Detection)的共享通讯介质的数据网络通讯技术。当主机数目较多时会导致冲突严重、广播泛滥、性能显著下降甚至造成网络不可用等问题。通过交换机实现 LAN 互连虽然可以解决冲突严重的问题&#xff0c;但仍然不…