camera功能真的那么難用嗎

背景

????????Android開發工作過程中,經常需要用到camera相關能力,比如:人臉識別,ai識別,拍照預覽,攝像頭錄制等等需求。都需要使用到camera,且需要拿到camera的預覽數據。但是每次開發這塊代碼都比較繁瑣,一大堆的接口(尤其是camera2),用錯一個就容易出現意想不到的結果。所以這里我們將Android的camera做一次簡單易用的封裝,再也不用擔心API用錯了。

一、Camera的歷史

在封裝之前,我們先簡單了解下camera的發展歷史。目前Android有camera1和camera2兩個不同版本的API。且camera1已經逐漸被拋棄了。那她兩到底啥區別?

  • Camera1(2010年推出)
    • 簡單但僵化:采用同步阻塞模型,調用takePicture()時整個相機管線阻塞,導致延遲高、功耗大。
    • 有限控制:參數調整(如曝光、對焦)通過Camera.Parameters實現,僅支持基礎設置,無法精細控制。
    • 高延遲:拍照后需等待圖像處理完成才能繼續操作。
    • 資源浪費:預覽和拍照無法并行,導致CPU/GPU利用率低。
    • 硬件抽象層(HAL)簡單:無法適配多攝像頭、高幀率傳感器(>30fps)或RAW格式。
    • 功能缺失:不支持HDR+、人像模式等計算攝影需求。
    • 獨占式訪問:僅允許單應用占用相機,其他應用需等待釋放(如掃碼時無法同時視頻通話)。
  • Camera2(2014年推出,Android 5.0+)
    • 異步管道模型:引入CaptureRequestCaptureSession,支持非阻塞操作(如連拍、實時預覽并行處理)。
    • 精準控制:可獨立配置傳感器、閃光燈、處理算法(如手動調節ISO、快門速度)。
    • 零復制流水線:圖像數據直接傳遞到Surface(如TextureView),減少內存拷貝。
    • 批處理請求:單次提交多個CaptureRequest(如同時預覽+對焦+測光),提升幀率和能效比。
    • 標準化HAL接口:統一控制不同廠商的相機硬件(如雙攝、TOF傳感器)。
    • 高級功能支持:原生實現RAW拍攝、手動對焦軌跡、邏輯多攝像頭(融合多個傳感器數據)。
    • 并發共享機制:通過CameraManager協調多應用訪問(如后臺AR應用與前臺相機APP共存)。
特性Camera1Camera2
架構模型同步阻塞異步非阻塞管道
性能高延遲、低吞吐量低延遲、高吞吐量(支持4K/60fps)
硬件適配僅基礎單攝多攝/RAW/高幀率傳感器
功能擴展基礎拍照/錄像HDR+/手動模式/計算攝影
多應用支持獨占訪問并發共享

?二、封裝核心能力

工作場景下對camera最常用的核心能力:開啟攝像頭,切換攝像頭,預覽,關閉攝像頭,獲取攝像頭預覽數據。

所以我們要封裝的話就直接將這幾個能力抽象成對應的接口。

package com.qt.camera.baseimport android.graphics.SurfaceTexture
import android.hardware.Camera
import android.util.Range
import com.qt.camera.FUCameraConstants
import com.qt.camera.enumeration.FUCameraFacingEnum
import com.qt.camera.listener.OnFUCameraListener/**** DESC:Camera抽象類* Created on 2021/10/22* @author Jason Lu*/
abstract class FUAbstractCamera {/*** 前置相機id*/@Volatilevar mFrontCameraId = Camera.CameraInfo.CAMERA_FACING_FRONT/*** 后置相機id*/@Volatilevar mBackCameraId = Camera.CameraInfo.CAMERA_FACING_BACK/*** 曝光補償*/@Volatilevar mExposureCompensation = FUCameraConstants.EXPOSURE_COMPENSATION/*** 相機采集幀率模式* true:最大幀率輸出 false:最大可選范圍區間輸出*/@Volatilevar mIsHighestRate = false/*** 相機后置角度*/@Volatilevar mBackCameraOrientation = FUCameraConstants.BACK_CAMERA_ORIENTATION/*** 當前相機前置角度*/@Volatilevar mFrontCameraOrientation = FUCameraConstants.FRONT_CAMERA_ORIENTATION/*** 當前相機朝向*/@Volatilevar mCameraFacing = FUCameraFacingEnum.CAMERA_FRONT/*** 當前相機輸出分辨率-寬*/@Volatilevar mCameraWidth: Int = 1280/*** 當前相機輸出分辨率-高*/@Volatilevar mCameraHeight: Int = 720/*** 當前相機角度*/@Volatilevar mCameraOrientation = mFrontCameraOrientation/*** 當前相機綁定紋理 Id*/@Volatilevar mCameraTexId = 100/*** 當前相機綁定 SurfaceTexture*/@Volatilevar mSurfaceTexture: SurfaceTexture? = null/*** 用戶設置的相機綁定 SurfaceTexture*/@Volatilevar mCustomSurfaceTexture: SurfaceTexture? = null/*** 是否正在預覽狀態*/@Volatileprotected var mIsPreviewing = false/*** 是否只讀ImageReader流*/@Volatilevar onlyReadImage = false/*** 是否需要停止預覽*/@Volatileprotected var mIsNeedStopPreviewing = false/*** 事件回調*/@Volatileprotected var mCameraListener: OnFUCameraListener? = null/*** 自定義攝像頭幀率范圍* 針對camera2*/var mRangeFps: Range<Int>? = null/*** 綁定數據回調* @param listener OnFUCameraListener*/fun bindCameraListener(listener: OnFUCameraListener?) {this.mCameraListener = listener}/*** 資源釋放*/open fun release() {if (mIsPreviewing) {closeCamera()}mCameraListener = null}/*** 初始化相機*/abstract fun initCameraInfo()/*** 打開相機*/abstract fun openCamera()/*** 開啟預覽*/abstract fun startPreview()/*** 對焦* @param viewWidth Int* @param viewHeight Int* @param rawX Float* @param rawY Float* @param areaSize Int*/abstract fun handleFocus(viewWidth: Int, viewHeight: Int, rawX: Float, rawY: Float, areaSize: Int)/*** 獲取亮度* @return Float*/abstract fun getExposureCompensation(): Float/*** 設置亮度* @param value Float*/abstract fun setExposureCompensation(value: Float)/*** 分辨率變更處理* @param cameraWidth Int* @param cameraHeight Int*/abstract fun changeResolution(cameraWidth: Int, cameraHeight: Int)/*** 關閉相機* @param releaseSurface 是否釋放SurfaceTexture資源*/abstract fun closeCamera(releaseSurface:Boolean = true)/*** 切換相機前后置*/fun switchCamera(surfaceTexture: SurfaceTexture?) {closeCamera(mCustomSurfaceTexture == null || surfaceTexture !=null)//如果使用用戶自定義的surfaceTexture或者之前設置過surfaceTexture就releasemCameraFacing = if (mCameraFacing == FUCameraFacingEnum.CAMERA_FRONT) FUCameraFacingEnum.CAMERA_BACK else FUCameraFacingEnum.CAMERA_FRONTmCameraOrientation = if (mCameraFacing == FUCameraFacingEnum.CAMERA_FRONT) mFrontCameraOrientation else mBackCameraOrientationif(surfaceTexture!= null){mCustomSurfaceTexture = surfaceTexture}openCamera()}/*** 設置相機放大等級*/abstract fun setZoomRatio(zoomRatio: Float)}

核心能力抽象出來后,剩下要做的就是camera1和camera2分別實現了。具體的實現這里就不貼代碼了,給個github鏈接,各位自己下載直接用吧:GitHub - 279154451/Camera: Camera工具

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/84119.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/84119.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/84119.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

USART 串口通信全解析:原理、結構與代碼實戰

文章目錄 USARTUSART簡介USART框圖USART基本結構數據幀起始位偵測數據采樣波特率發生器串口發送數據 主要代碼串口接收數據與發送數據主要代碼 USART USART簡介 一、USART 的全稱與基本定義 英文全稱 USART&#xff1a;Universal Synchronous Asynchronous Receiver Transmi…

LeetCode 152. 乘積最大子數組 - 動態規劃解法詳解

文章目錄 問題描述解題思路動態規劃狀態定義狀態轉移方程完整代碼實現復雜度分析示例解析關鍵點說明總結問題描述 給定一個整數數組 nums,請找出數組中乘積最大的連續子數組(該子數組中至少包含一個數字),并返回該子數組對應的乘積。 示例: 輸入: [2,3,-2,4] 輸出: 6 解…

Python: 操作 Excel折疊

??Python 操作 Excel 折疊(分組)功能詳解(openpyxl & xlsxwriter 雙方案) 在處理 Excel 報表或數據分析時,我們常常希望通過 折疊(分組)功能 來提升表格的可讀性和組織性。本文將詳細介紹如何使用 Python 中的兩個主流 Excel 操作庫 —— openpyxl 和 xlsxwriter …

28、元組的遍歷

const_cast 只能用于指針或引用類型&#xff0c;而不能用于基本類型如 int。 在的代碼中&#xff0c;試圖將 i 轉換為 const_cast<int>(i)&#xff0c;這是不合法的。 可以使用模板函數來獲取元組中的元素&#xff0c;而不是使用 const_cast。以下是修正后的代碼&#x…

sendDefaultImpl call timeout(rocketmq)

rocketmq 連接異常 senddefaultimpl call timeout-騰訊云開發者社區-騰訊云 第一種情況&#xff1a; 修改broker 的配置如下&#xff0c;注意brokerIP1 這個配置必須有&#xff0c;不然 rocketmq-console 顯示依然是內網地址 caused by: org.apache.rocketmq.remoting.excep…

【仿生機器人】仿生機器人智能架構:從感知到個性的完整設計

仿生機器人智能架構&#xff1a;從感知到個性的完整設計 仿生機器人不僅需要模擬人類的外表&#xff0c;更需要具備類人的認知、情感和個性特征。本研究提出了一個綜合性的軟件架構&#xff0c;實現了從環境感知到情感生成、從實時交互到人格塑造的完整智能系統。該架構突破了…

Spring Boot微服務架構(十一):獨立部署是否拋棄了架構優勢?

Spring Boot 的獨立部署&#xff08;即打包為可執行 JAR/WAR 文件&#xff09;本身并不會直接喪失架構優勢&#xff0c;但其是否體現架構價值取決于具體應用場景和設計選擇。以下是關鍵分析&#xff1a; 一、獨立部署與架構優勢的關系 內嵌容器的優勢保留 Spring Boot 獨立部署…

HBuilderX安裝(uni-app和小程序開發)

下載HBuilderX 訪問官方網站&#xff1a;https://www.dcloud.io/hbuilderx.html 根據您的操作系統選擇合適版本&#xff1a; Windows版&#xff08;推薦下載標準版&#xff09; Windows系統安裝步驟 運行安裝程序&#xff1a; 雙擊下載的.exe安裝文件 如果出現安全提示&…

2025年6月3日面試總結

1. 面試官問一臺機器內存或者磁盤占用99% 再點一下就掛了&#xff0c;個人剛開始反應內存不足加內存&#xff0c;磁盤不足加磁盤&#xff0c;還有啥辦法&#xff0c;有些時候沒干過的事一定要大膽&#xff0c;敲命令都敲不成&#xff0c;只能換磁盤了和加內存了&#xff0c;要么…

從上下文學習和微調看語言模型的泛化:一項對照研究

大型語言模型表現出令人興奮的能力&#xff0c;但也可以從微調中表現出令人驚訝的狹窄泛化。例如&#xff0c;他們可能無法概括為簡單的關系反轉&#xff0c;或者無法根據訓練信息進行簡單的邏輯推理。這些未能從微調中概括出來的失敗可能會阻礙這些模型的實際應用。另一方面&a…

解決cocos 2dx/creator2.4在ios18下openURL無法調用的問題

由于ios18廢棄了舊的openURL接口&#xff0c;我們需要修改CCApplication-ios.mm文件的Application::openURL方法&#xff1a; //修復openURL在ios18下無法調用的問題 bool Application::openURL(const std::string &url) {// NSString* msg [NSString stringWithCString:…

Go 語言并發編程基礎:Goroutine 的創建與調度

Go 語言的并發模型是其最顯著的語言特性之一。Goroutine 是 Go 實現并發的核心機制&#xff0c;它比線程更輕量&#xff0c;調度效率極高。 本章將帶你了解 Goroutine 的基本概念、創建方式以及背后的調度機制。 一、什么是 Goroutine&#xff1f; Goroutine 是由 Go 運行時&a…

網頁繪制表格

說明&#xff1a; border"1"&#xff1a;設置表格邊框寬度為 1 像素&#xff08;可調整數值改變邊框粗細&#xff09;。cellspacing"0"&#xff1a;設置單元格間距為 0&#xff08;去除邊框間的空白間隙&#xff09;。<thead>&#xff1a;定義表頭區…

Python爬蟲實戰:研究Unirest庫相關技術

一、引言 在當今信息爆炸的時代,網絡數據的獲取與分析變得尤為重要。Python 作為一種功能強大且易于學習的編程語言,在網絡爬蟲領域有著廣泛的應用。Unirest 庫是一個輕量級的 HTTP 客戶端庫,它提供了簡潔的 API,使得發送 HTTP 請求變得更加容易。本論文將詳細分析如何使用…

二、【ESP32開發全棧指南:ESP32 GPIO深度使用】

GPIO&#xff08;通用輸入輸出&#xff09; 是ESP32最基礎卻最核心的功能。本文將帶你深入ESP32的GPIO操作&#xff0c;通過按鍵讀取和LED控制實現物理按鍵→ESP32→LED的完整信號鏈路。 一、ESP32 GPIO核心特性速覽 34個可編程GPIO&#xff08;部分引腳受限&#xff09;輸入模…

調用.net DLL讓CANoe自動識別串口號

1.前言 CANoe9.0用CAPL控制數控電源_canoe讀取程控電源電流值-CSDN博客 之前做CAPL通過串口控制數控電源&#xff0c;存在一個缺點&#xff1a;更換電腦需要改串口號 CSDN上有類似的博客&#xff0c;不過要收費&#xff0c;本文根據VID和PID來自動獲取串口號&#xff0c;代碼…

SpringBoot十二、SpringBoot系列web篇之過濾器Filte詳解

一、前言 JavaWeb三大組件Servlet、Filter、Listener&#xff0c;其中之一便是過濾器Filter。 其實&#xff0c;Filter我們平常用的不多&#xff0c;一般多為項目初期搭建web架構的時候使用&#xff0c;后面用的就少了&#xff0c;在日常業務開發中不太可能碰到需要手寫Filte…

Java實現飛機射擊游戲:從設計到完整源代碼

JAVA打飛機游戲畢業設計 一、游戲概述 本游戲基于Java Swing開發&#xff0c;實現了經典的飛機射擊游戲。玩家控制一架戰斗機在屏幕底部移動&#xff0c;發射子彈擊落敵機&#xff0c;同時躲避敵機攻擊。游戲包含多個關卡&#xff0c;隨著關卡提升&#xff0c;敵機速度和數量…

通俗易懂linux環境變量

如果想要清楚的了解環境變量&#xff0c;我覺得我們需要先大致搞清楚一個簡單的事——什么是會話&#xff1f; 會話大致是什么&#xff1f; 在這里我們的目的是更好的理解環境變量&#xff0c;所以適當講解一下會話即可。通常我們都是用xshell連接遠程服務器&#xff0c;都會打…

【補題】Codeforces Round 715 (Div. 2) C. The Sports Festival

題意&#xff1a;給你一個序列&#xff0c;你可以對它重新排序&#xff0c;然后使每個i&#xff0c;max(a0,a1……ai)-min(a0,a1……ai)最小。問答案是多少 思路&#xff1a; C. The Sports Festival&#xff08;區間DP&#xff09;-CSDN博客 區間dp&#xff0c;完全沒想到…