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

鸿蒙实战开发Camera组件:【相机】

相机组件支持相机业务的开发,开发者可以通过已开放的接口实现相机硬件的访问、操作和新功能开发,最常见的操作如:预览、拍照和录像等。

基本概念

  • 拍照

    此功能用于拍摄采集照片。

  • 预览

    此功能用于在开启相机后,在缓冲区内重复采集摄像帧,支持在拍照或录像前进行摄像帧预览显示。

  • 录像

    此功能用于在开始录像后和结束录像前的时间段内,在缓冲区内重复采集摄像帧,支持视频录制。

图 1 相机组件架构图

目录

仓目录结构如下:

/foundation/multimedia/camera_framework   # 相机组件业务代码
├── frameworks                           # 框架代码
│   ├── native                           # 内部接口实现
│   │   ├── camera                       # 相机框架实现
│   │   └── metadata                     # 元数据实现
│   └── js                               # 外部接口实现
│       └── camera_napi                  # 相机NAPI实现
├── interfaces                           # 接口代码
│   ├── inner_api                        # 内部接口
│   └── kits                             # 外部接口
├── LICENSE                              # 许可证文件
├── ohos.build                           # 构建文件
├── sa_profile                           # 服务配置文件
└── services                             # 服务代码├── camera_service                   # 相机服务实现└── etc                              # 相机服务配置

使用说明

拍照

拍照的步骤:

  1. 创建缓冲区消费者端监听器(CaptureSurfaceListener)以保存图像。

    class CaptureSurfaceListener : public IBufferConsumerListener {
    public:int32_t mode_;sptr<Surface> surface_;void OnBufferAvailable() override{int32_t flushFence = 0;int64_t timestamp = 0;OHOS::Rect damage; // initialize the damageOHOS::sptr<OHOS::SurfaceBuffer> buffer = nullptr;surface_->AcquireBuffer(buffer, flushFence, timestamp, damage);if (buffer != nullptr) {void* addr = buffer->GetVirAddr();int32_t size = buffer->GetSize();// Save the buffer(addr) to a file.surface_->ReleaseBuffer(buffer, -1);}}
    };
    
  2. 获取相机管理器实例并获取相机对象列表。

    sptr<CameraManager> camManagerObj = CameraManager::GetInstance();
    std::vector<sptr<CameraInfo>> cameraObjList = camManagerObj->GetCameras();
    
  3. 使用相机对象创建相机输入来打开相机。

    sptr<CaptureInput> cameraInput = camManagerObj->CreateCameraInput(cameraObjList[0]);
    
  4. 创建采集会话。

    sptr<CaptureSession> captureSession = camManagerObj->CreateCaptureSession();
    
  5. 开始配置采集会话。

    int32_t result = captureSession->BeginConfig();
    
  6. 将相机输入添加到采集会话。

    result = captureSession->AddInput(cameraInput);
    
  7. 创建消费者 Surface 并注册监听器以监听缓冲区更新。拍照的宽和高可以配置为所支持的 1280x960 分辨率。

    sptr<Surface> photoSurface = Surface::CreateSurfaceAsConsumer();
    int32_t photoWidth = 1280;
    int32_t photoHeight = 960;
    photoSurface->SetDefaultWidthAndHeight(photoWidth, photoHeight);
    photoSurface->SetUserData(CameraManager::surfaceFormat, std::to_string(OHOS_CAMERA_FORMAT_JPEG));
    sptr<CaptureSurfaceListener> capturelistener = new(std::nothrow) CaptureSurfaceListener();
    capturelistener->mode_ = MODE_PHOTO;
    capturelistener->surface_ = photoSurface;
    photoSurface->RegisterConsumerListener((sptr<IBufferConsumerListener> &)capturelistener);
    
  8. 使用上面创建的 Surface 创建拍照输出。

    sptr<CaptureOutput> photoOutput = camManagerObj->CreatePhotoOutput(photoSurface);
    
  9. 将拍照输出添加到采集会话。

    result = captureSession->AddOutput(photoOutput);
    
  10. 将配置提交到采集会话。

    result = captureSession->CommitConfig();
    
  11. 拍摄照片。

    result = ((sptr<PhotoOutput> &)photoOutput)->Capture();
    
  12. 释放采集会话资源。

    captureSession->Release();
    
  13. 释放相机输入关闭相机。

    cameraInput->Release();
    

开始和停止预览

开始和停止预览的步骤:

  1. 获取相机管理器实例并获取相机对象列表。

    sptr<CameraManager> camManagerObj = CameraManager::GetInstance();
    std::vector<sptr<CameraInfo>> cameraObjList = camManagerObj->GetCameras();
    
  2. 使用相机对象创建相机输入来打开相机。

    sptr<CaptureInput> cameraInput = camManagerObj->CreateCameraInput(cameraObjList[0]);
    
  3. 创建采集会话。

    sptr<CaptureSession> captureSession = camManagerObj->CreateCaptureSession();
    
  4. 开始配置采集会话。

    int32_t result = captureSession->BeginConfig();
    
  5. 将相机输入添加到采集会话。

    result = captureSession->AddInput(cameraInput);
    
  6. 使用从窗口管理器获得的 Surface 创建预览输出用以在显示上渲染。预览的宽和高可以配置为所支持的 640x480 或 832x480 分辨率,如果想保存到文件,可以按照拍照流程提到步骤,创建 Surface,注册监听器以监听缓冲区更新。

    int32_t previewWidth = 640;
    int32_t previewHeight = 480;
    previewSurface->SetUserData(CameraManager::surfaceFormat, std::to_string(OHOS_CAMERA_FORMAT_YCRCB_420_SP));
    sptr<CaptureOutput> previewOutput = camManagerObj->CreateCustomPreviewOutput(previewSurface, previewWidth, previewHeight);
    
  7. 将预览输出添加到采集会话。

    result = captureSession->AddOutput(previewOutput);
    
  8. 将配置提交到采集会话。

    result = captureSession->CommitConfig();
    
  9. 开始预览。

    result = captureSession->Start();
    
  10. 需要时停止预览。

    result = captureSession->Stop();
    
  11. 释放采集会话资源。

    captureSession->Release();
    
  12. 释放相机输入关闭相机。

    cameraInput->Release();
    

视频录像

视频录像的步骤:

  1. 获取相机管理器实例并获取相机对象列表。

    sptr<CameraManager> camManagerObj = CameraManager::GetInstance();
    std::vector<sptr<CameraInfo>> cameraObjList = camManagerObj->GetCameras();
    
  2. 使用相机对象创建相机输入来打开相机。

    sptr<CaptureInput> cameraInput = camManagerObj->CreateCameraInput(cameraObjList[0]);
    
  3. 创建采集会话。

    sptr<CaptureSession> captureSession = camManagerObj->CreateCaptureSession();
    
  4. 开始配置采集会话。

    int32_t result = captureSession->BeginConfig();
    
  5. 将相机输入添加到采集会话。

    result = captureSession->AddInput(cameraInput);
    
  6. 通过 Surface 创建一个视频输出,来与音频合成并保存到文件,Surface 通过 Recoder 获取。如果想仅保存视频缓冲数据到文件里,可以按照拍照流程提到步骤,创建 Surface,注册监听器以监听缓冲区更新。录像的分辨率可以在录制器内配置为所支持的 1280x720 或 640x360 分辨率。

    videoSurface->SetUserData(CameraManager::surfaceFormat, std::to_string(OHOS_CAMERA_FORMAT_YCRCB_420_SP));
    sptr<CaptureOutput> videoOutput = camManagerObj->CreateVideoOutput(videoSurface);
    
  7. 将视频输出添加到采集会话。

    result = captureSession->AddOutput(videoOutput);
    
  8. 将配置提交到采集会话。

    result = captureSession->CommitConfig();
    
  9. 开始视频录制。

    result = ((sptr<VideoOutput> &)videoOutput)->Start();
    
  10. 需要时停止录制。

    result = ((sptr<VideoOutput> &)videoOutput)->Stop();
    
  11. 释放采集会话的资源。

    captureSession->Release();
    
  12. 释放相机输入关闭相机。

    cameraInput->Release();
    

切换多个照相机设备

以下演示如何切换多个照相机设备。最初在采集会话中有一个视频输出(video output)。如果用户想要切换其他 照相机,现存的相机输入和输出需要先移除并加入新的相机输入和输出(示例中使用的是photo output)。

  1. 获取相机管理器实例并获取相机对象列表。

    sptr<CameraManager> camManagerObj = CameraManager::GetInstance();
    std::vector<sptr<CameraInfo>> cameraObjList = camManagerObj->GetCameras();
    
  2. 使用相机对象创建相机输入来打开相机。

    sptr<CaptureInput> cameraInput = camManagerObj->CreateCameraInput(cameraObjList[0]);
    
  3. 创建采集会话。

    sptr<CaptureSession> captureSession = camManagerObj->CreateCaptureSession();
    
  4. 开始配置采集会话。

    int32_t result = captureSession->BeginConfig()
    
  5. 将相机输入添加到采集会话。

    result = captureSession->AddInput(cameraInput);
    
  6. 通过Surface创建一个视频输出。

    sptr<CaptureOutput> videoOutput = camManagerObj->CreateVideoOutput(videoSurface);
    
  7. 将视频输出添加到采集会话。

    result = captureSession->AddOutput(videoOutput);
    
  8. 将配置提交到采集会话。

    result = captureSession->CommitConfig();
    
  9. 开始录制视频。

    result = ((sptr<VideoOutput> &)videoOutput)->Start();
    
  10. 需要时停止录制。

    result = ((sptr<VideoOutput> &)videoOutput)->Stop();
    
  11. 重新配置会话并移除相机输入和输出。

    int32_t result = captureSession->BeginConfig();
    
  12. 在新的会话配置中移除相机输入。

    int32_t result = captureSession->RemoveInput(cameraInput);
    
  13. 同样移除相机输出。

    int32_t result = captureSession->RemoveOutut(videoOutput);
    
  14. 创建新的相机输入,并把它添加到采集会话。

    sptr<CaptureInput> cameraInput2 = camManagerObj->CreateCameraInput(cameraObjList[1]);
    result = captureSession->AddInput(cameraInput2);
    
  15. 创建拍照输出,成功创建后将拍照输出添加到采集会话。创建消费者 Surface 并注册监听器以监听新的拍照输出缓冲区更新。这个 Surface 用于新创建的拍照输出。

    // Get the surface
    sptr<Surface> photoSurface = Surface::CreateSurfaceAsConsumer();
    int32_t photoWidth = 1280;
    int32_t photoHeight = 960;
    photoSurface->SetDefaultWidthAndHeight(photoWidth, photoHeight);
    photoSurface->SetUserData(CameraManager::surfaceFormat, std::to_string(OHOS_CAMERA_FORMAT_JPEG));
    sptr<CaptureSurfaceListener> capturelistener = new(std::nothrow) CaptureSurfaceListener();
    capturelistener->mode_ = MODE_PHOTO;
    capturelistener->surface_ = photoSurface;
    photoSurface->RegisterConsumerListener((sptr<IBufferConsumerListener> &)capturelistener);// Create the Photo Output
    sptr<CaptureOutput> photoOutput = camManagerObj->CreatePhotoOutput(photoSurface);// Add the output to the capture session
    result = captureSession->AddOutput(photoOutput);
    
  16. 将配置提交到采集会话。

    result = captureSession->CommitConfig();
    
  17. 释放被移出会话的相机输入。

    cameraInput->Release();
    
  18. 拍摄照片。

    result = ((sptr<PhotoOutput> &)photoOutput)->Capture();
    
  19. 释放采集会话资源。

    captureSession->Release();
    
  20. 释放相机输入关闭相机。

    cameraInput2->Release();
    

设置闪光灯

拍照和录像前可以在相机输入里设置闪光灯。

  1. 在照相中设置闪光灯。

    cameraInput->LockForControl();
    cameraInput->SetFlashMode(OHOS_CAMERA_FLASH_MODE_OPEN);
    cameraInput->UnlockForControl();
    
  2. 在录像中设置闪光灯。

    cameraInput->LockForControl();
    cameraInput->SetFlashMode(OHOS_CAMERA_FLASH_MODE_ALWAYS_OPEN);
    cameraInput->UnlockForControl();
    
  3. 关闭闪光灯。

    cameraInput->LockForControl();
    cameraInput->SetFlashMode(OHOS_CAMERA_FLASH_MODE_CLOSE);
    cameraInput->UnlockForControl();
    

    鸿蒙OpenHarmony知识已更新←前往

765e5079845b5bb77f2aa30a2da70670.jpeg

相关文章:

鸿蒙实战开发Camera组件:【相机】

相机组件支持相机业务的开发&#xff0c;开发者可以通过已开放的接口实现相机硬件的访问、操作和新功能开发&#xff0c;最常见的操作如&#xff1a;预览、拍照和录像等。 基本概念 拍照 此功能用于拍摄采集照片。 预览 此功能用于在开启相机后&#xff0c;在缓冲区内重复采集…...

政安晨:【深度学习处理实践】(三)—— 处理时间序列的数据准备

在深度学习中&#xff0c;对时间序列的处理主要涉及到以下几个方面&#xff1a; 序列建模&#xff1a;深度学习可以用于对时间序列进行建模。常用的模型包括循环神经网络&#xff08;Recurrent Neural Networks, RNN&#xff09;和长短期记忆网络&#xff08;Long Short-Term M…...

PCL不同格式点云读取速度(Binary和ASCII )

首先说明一点&#xff1a;Binary(二进制)格式点云文件进行读取时要比Ascll码格式点云读取时要快的多&#xff0c;尤其是对于大型的点云文件&#xff0c;如几百万、甚至几千万个点云的情况下。 今天遇到了一种情况&#xff0c;在写项目的时候进行点云读取&#xff0c;读取的时候…...

Neo4J图数据库入门示例

前言 - Neo4j和MySQL的区别 Neo4j 和 MySQL 是两种不同类型的数据库&#xff0c;它们在数据模型、用途、性能和查询语言等方面有着显著的区别。以下是它们的主要区别&#xff1a; 数据模型&#xff1a; Neo4j 是一种图数据库&#xff0c;它使用图数据模型来存储和查询数据。在…...

牛客每日一题之 二维前缀和

题目介绍&#xff1a; 题目链接&#xff1a;【模板】二维前缀和_牛客题霸_牛客网 先举两个简单的例子&#xff0c;来帮大家理解题目&#xff0c;注意理解二维前缀和要先要一维前缀和的基础&#xff0c;不了解的可以看我上一篇博客。 若x11&#xff0c;y11, x23, y2 3,这是要…...

动态规划 Leetcode 70 爬楼梯

爬楼梯 Leetcode 70 学习记录自代码随想录 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢&#xff1f; 示例 1&#xff1a; 输入&#xff1a;n 2 输出&#xff1a;2 解释&#xff1a;有两种方法可以爬到…...

(未解决)macOS matplotlib 中文是方框

reference&#xff1a; Mac OS系统下实现python matplotlib包绘图显示中文(亲测有效)_mac plt 中文值-CSDN博客 module ‘matplotlib.font_manager‘ has no attribute ‘_rebuild‘解决方法_font_manager未解析-CSDN博客 # 问题描述&#xff08;笑死 显而易见 # solve 找到…...

深入探讨C#中的递归算法

一、什么是递归算法&#xff1f; 递归是指一个函数或方法在执行过程中调用自身的情况。递归算法是编程中常见的一种解决问题的方法。它将一个问题分解成一个或多个与原问题相似但规模更小的子问题&#xff0c;然后通过解决这些子问题来解决原问题。递归算法通常用于解决重复性的…...

三款顶级开源RAG (检索增强生成)工具:Verba、Unstructured 和 Neum

三款顶级开源RAG (检索增强生成)工具&#xff1a;Verba、Unstructured 和 Neum 概述 随着企业对话式数据处理需求的提升&#xff0c;面临的挑战是数据隐私性和缺乏企业级解决方案。虽然类似LangChain能在短时间内构建RAG应用&#xff0c;但忽视了文档解析、多来源数据ETL、批量…...

VC++、MFC中操作excel时,CRange中get_EntireRow()和get_EntireColumn()函数的用法及区别是什么?

在VC和MFC中操作Excel时&#xff0c;通过COM接口与Excel交互时&#xff0c;CRange 对象&#xff08;或更准确地说是 Excel::Range 对象&#xff09;代表一个单元格范围。CRange 类提供了一系列方法来获取或操作这个范围内的单元格。其中&#xff0c;get_EntireRow() 和 get_Ent…...

npm 操作报错记录1- uninstall 卸载失效

npm 操作报错记录1- uninstall 卸载失效 1、问题描述 安装了包 vue/cli-plugin-eslint4.5.0 vue/eslint-config-prettier9.0.0 但是没有使用 -d &#xff0c;所以想重新安装&#xff0c;就使用 uninstall 命令卸载&#xff0c;结果卸载了没反应&#xff0c;也没有报错&#xf…...

openCV保存图像

保存图像 //保存为png透明通道vector<int>opts;opts.push_back(IMWRITE_PAM_FORMAT_RGB_ALPHA);imwrite("D:/img_bgra.png", img, opts);//保存为单通道灰度图像img cv::imread(imagePath.toStdString(), IMREAD_GRAYSCALE);vector<int> opts_gray;opts…...

mac 配置.bash_profile不生效问题

1、问题描述 mac系统中配置了环境变量只能在当前终端生效&#xff0c;切换了终端就无效了&#xff0c;查了下问题所在。mac系统会预装一个终极shell - zsh&#xff0c;环境变量读取在 .zshrc 文件下。 2、解决方案 1、切换终端到bash 切换终端到bash chsh -s /bin/bash 切换终端…...

【Cesium for Supermap】S3MTiles图层box裁剪

效果图&#xff1a; 代码&#xff1a; let viewer new Cesium.Viewer(cesiumContainer);// 添加SuperMap iServer发布的S3M缓存服务let promise viewer.scene.addS3MTilesLayerByScp("http://www.supermapol.com/realspace/services/3D-BIMbuilding/rest/realspace/data…...

PAT部分题目相关知识点——python

python中的整除 在Python中&#xff0c;整除&#xff08;也称为地板除&#xff09;可以使用**//**运算符来实现。当使用//运算符时&#xff0c;结果将是一个整数&#xff0c;它表示除法运算的整数部分&#xff0c;舍去任何小数部分。 示例&#xff1a; # 使用整除运算符 // …...

Redis核心数据结构之字典(二)

字典 解决键冲突 当有两个或以上数量的键被分配到了一个哈希表数组的同一个索引上面&#xff0c;我们称这些键发生了冲突(collision)。 Redis的哈希表使用链地址法(separate chaining)来解决键冲突&#xff0c;每个哈希表节点都有一个next指针&#xff0c;多个哈希表节点可以…...

拯救行动(BFS)

公主被恶人抓走&#xff0c;被关押在牢房的某个地方。牢房用 N \times M (N, M \le 200)NM(N,M≤200) 的矩阵来表示。矩阵中的每项可以代表道路&#xff08;&#xff09;、墙壁&#xff08;#&#xff09;、和守卫&#xff08;x&#xff09;。 英勇的骑士&#xff08;r&#xf…...

985硕的4家大厂实习与校招经历专题分享(part2)

我的个人经历&#xff1a; 985硕士24届毕业生&#xff0c;实验室方向:CV深度学习 就业&#xff1a;工程-java后端 关注大模型相关技术发展 校招offer: 阿里巴巴 字节跳动 等10 研究生期间独立发了一篇二区SCI 实习经历:字节 阿里 京东 B站 &#xff08;只看大厂&#xff0c;面试…...

【NR技术】 3GPP支持无人机的关键技术以及场景

1 背景 人们对使用蜂窝连接来支持无人机系统(UAS)的兴趣浓厚&#xff0c;3GPP生态系统为UAS的运行提供了极好的好处。无处不在的覆盖范围、高可靠性和QoS、强大的安全性和无缝移动性是支持UAS指挥和控制功能的关键因素。与此同时&#xff0c;监管机构正在调查安全和性能标准以及…...

【译】WordPress Bricks主题安全漏洞曝光,25,000个安装受影响

WordPress的Bricks主题存在一个严重的安全漏洞&#xff0c;恶意威胁行为者正在积极利用该漏洞在易受攻击的安装上运行任意PHP代码。 该漏洞被跟踪为CVE-2024-25600&#xff08;CVSS评分&#xff1a;9.8&#xff09;&#xff0c;使未经身份验证的攻击者能够实现远程代码执行。它…...

JavaSec-RCE

简介 RCE(Remote Code Execution)&#xff0c;可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景&#xff1a;Groovy代码注入 Groovy是一种基于JVM的动态语言&#xff0c;语法简洁&#xff0c;支持闭包、动态类型和Java互操作性&#xff0c…...

conda相比python好处

Conda 作为 Python 的环境和包管理工具&#xff0c;相比原生 Python 生态&#xff08;如 pip 虚拟环境&#xff09;有许多独特优势&#xff0c;尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处&#xff1a; 一、一站式环境管理&#xff1a…...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》

在注意力分散、内容高度同质化的时代&#xff0c;情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现&#xff0c;消费者对内容的“有感”程度&#xff0c;正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中&#xff0…...

爬虫基础学习day2

# 爬虫设计领域 工商&#xff1a;企查查、天眼查短视频&#xff1a;抖音、快手、西瓜 ---> 飞瓜电商&#xff1a;京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空&#xff1a;抓取所有航空公司价格 ---> 去哪儿自媒体&#xff1a;采集自媒体数据进…...

Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理

引言 Bitmap&#xff08;位图&#xff09;是Android应用内存占用的“头号杀手”。一张1080P&#xff08;1920x1080&#xff09;的图片以ARGB_8888格式加载时&#xff0c;内存占用高达8MB&#xff08;192010804字节&#xff09;。据统计&#xff0c;超过60%的应用OOM崩溃与Bitm…...

Kafka入门-生产者

生产者 生产者发送流程&#xff1a; 延迟时间为0ms时&#xff0c;也就意味着每当有数据就会直接发送 异步发送API 异步发送和同步发送的不同在于&#xff1a;异步发送不需要等待结果&#xff0c;同步发送必须等待结果才能进行下一步发送。 普通异步发送 首先导入所需的k…...

华为OD机考-机房布局

import java.util.*;public class DemoTest5 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseSystem.out.println(solve(in.nextLine()));}}priv…...

scikit-learn机器学习

# 同时添加如下代码, 这样每次环境(kernel)启动的时候只要运行下方代码即可: # Also add the following code, # so that every time the environment (kernel) starts, # just run the following code: import sys sys.path.append(/home/aistudio/external-libraries)机…...

MySQL 部分重点知识篇

一、数据库对象 1. 主键 定义 &#xff1a;主键是用于唯一标识表中每一行记录的字段或字段组合。它具有唯一性和非空性特点。 作用 &#xff1a;确保数据的完整性&#xff0c;便于数据的查询和管理。 示例 &#xff1a;在学生信息表中&#xff0c;学号可以作为主键&#xff…...

Spring AI Chat Memory 实战指南:Local 与 JDBC 存储集成

一个面向 Java 开发者的 Sring-Ai 示例工程项目&#xff0c;该项目是一个 Spring AI 快速入门的样例工程项目&#xff0c;旨在通过一些小的案例展示 Spring AI 框架的核心功能和使用方法。 项目采用模块化设计&#xff0c;每个模块都专注于特定的功能领域&#xff0c;便于学习和…...