在Camera編程中學(xué)攝影

1.Android sdk中的Camera

在Android Studio中敲下Camera,會(huì)給出兩個(gè)提示類:

  1. android.graphics.Camera ,一個(gè)照相機(jī)實(shí)例可以被用于計(jì)算3D變換,生成一個(gè)可以被使用的Matrix矩陣,一個(gè)實(shí)例,用在畫(huà)布上。
  2. android.hardware.Camera,用于設(shè)置圖像捕獲設(shè)置、開(kāi)始/停止預(yù)覽、快照?qǐng)D片以及檢索用于視頻編碼的幀。這個(gè)類是相機(jī)服務(wù)的客戶端,它管理實(shí)際的相機(jī)硬件。

今天要講的是相機(jī)管理類android.hardware.Camera,但在API 21+之后該類已被廢棄,新的相機(jī)管理類在 android.hardware.camera2 包下,所以本文會(huì)覆蓋camera和camera2兩種API。

2.Camera開(kāi)發(fā)中遇到的一些疑問(wèn)

  • 拍攝的照片為什么會(huì)旋轉(zhuǎn)90度
  • 預(yù)覽的圖像被拉伸
  • 預(yù)覽時(shí)返回的圖像幀數(shù)據(jù)為什么不能正常解析成bitmap

針對(duì)以上的問(wèn)題我們從camera成像說(shuō)起,camera其實(shí)應(yīng)該叫image sensor。

image sensor有兩大類CMOS和CCD,手機(jī)中常常使用的是價(jià)格低廉和整合性高的CMOS,sensor的成像原理是景物通過(guò)鏡頭(LENS)生成的光學(xué)圖像投射到圖像傳感器(Sensor)表面上,然后轉(zhuǎn)為模擬的電信號(hào),經(jīng)過(guò)A/D(模數(shù)轉(zhuǎn)換)轉(zhuǎn)換后變?yōu)閿?shù)字圖像信號(hào),再送到數(shù)字信號(hào)處理芯片(DSP)中加工處理,再通過(guò)IO接口傳輸?shù)紺PU中處理,通過(guò)LCD 就可以看到圖像了。

sensor一般的輸出格式:

1)YUV sensor

YUV sensor輸出的Data格式為YUV,也是使用android.hardware.Camera進(jìn)行預(yù)覽返回預(yù)覽幀的常見(jiàn)格式。

2)Raw sensor

Raw Sensor輸出的Data格式為原始未經(jīng)處理的Raw,圖像感應(yīng)器將捕捉到的光源信號(hào)轉(zhuǎn)化為數(shù)字信號(hào)的原始數(shù)據(jù)。RAW文件是一種記錄了數(shù)碼相機(jī)傳感器的原始信息,同時(shí)記錄了由相機(jī)拍攝所產(chǎn)生的一些原數(shù)據(jù)(如ISO的設(shè)置、快門(mén)速度、光圈值、白平衡等)的文件,在camera2中可查看相機(jī)是否支持raw格式并獲取raw數(shù)據(jù)。

從sensor輸出格式可以知道預(yù)覽時(shí)的幀數(shù)據(jù)為什么不能簡(jiǎn)單生成bitmap,因?yàn)閎itmap創(chuàng)建需要的是argb格式,而預(yù)覽幀數(shù)據(jù)一般是YUV格式。

image sensor的成像掃描方向是固定的,但image sensor安裝在手機(jī)的成像方向不一定和手機(jī)自然方向(一般為豎屏)一致


截圖 (8).png

上圖是常見(jiàn)的后置攝像頭與手機(jī)自然方向的對(duì)比,image sensor 順時(shí)針旋轉(zhuǎn)90度就和手機(jī)自然方向一致,這就是為什么我們要給camera設(shè)置90度才能豎屏預(yù)覽。
但90度不是定勢(shì),所以實(shí)際編碼中可以獲取image sensor的方向和phone display的方向進(jìn)行計(jì)算得出正確的旋轉(zhuǎn)值。
來(lái)看看Android官方給出的建議計(jì)算方案


截圖 (9).png

值得注意的是,以上操作只是讓預(yù)覽中顯示的圖像正常,對(duì)于預(yù)覽返回幀數(shù)據(jù)和拍照取得的數(shù)據(jù)并不會(huì)真正改變其方向,如果要得到和預(yù)覽圖像一致的照片還需要對(duì)圖像數(shù)據(jù)進(jìn)行額外的旋轉(zhuǎn)操作,但如果只需要拍照?qǐng)D像,則不需要對(duì)數(shù)據(jù)進(jìn)行旋轉(zhuǎn),使用camera.getParameters().setRotation(rotation)可以直接得到正確方向的jpeg圖像,對(duì)于rotation值的計(jì)算官方給出的算法在setRotation方法注釋中,要特別注意的是這個(gè)值只改變jpeg方向,并不能改變預(yù)覽幀YUV數(shù)據(jù)方向,在camera2中的使用會(huì)更直觀一點(diǎn),后面再講。
預(yù)覽時(shí)圖像顯示為什么被拉伸? 這和image sensor返回的預(yù)覽圖像大小有關(guān),只有預(yù)覽圖的大小和顯示預(yù)覽視圖大小相近相等時(shí)才最自然。

一臺(tái)手機(jī)image sensor支持的屬性設(shè)置都是有固定值的,絕大多數(shù)時(shí)候拍攝的圖片好不好看取決于image sensor的硬件成本,成像不好,再如何p圖也枉然。

3.android.hardware.Camera實(shí)例

截圖 (10).png

以上通過(guò)SurfaceTexture+GLSurfaceView進(jìn)行六種不同濾鏡效果預(yù)覽。關(guān)于SurfaceView、TextureView、GLSurfaceView、SurfaceTexture的區(qū)別可以看這篇文章。

通常大家拍照只要點(diǎn)擊一下就好,但是現(xiàn)在的手機(jī)越來(lái)越貴,硬件越來(lái)越好有些可以媲美相機(jī)效果,但是喜歡攝影的人都喜歡自己控制相機(jī)設(shè)置不同的效果進(jìn)行拍照,一鍵拍照顯得有點(diǎn)傻瓜式了,拍出來(lái)的效果都是千遍一律,隨著手機(jī)硬件的提升,手機(jī)拍照的可控性就越來(lái)越專業(yè)。

一鍵拍照為什么拍的還可以呢?對(duì)于軟件層面來(lái)說(shuō)其實(shí)關(guān)系不大,隨便寫(xiě)的Camera的小demo拍出的照片一樣好看,這是因?yàn)镃amera默認(rèn)情況下使用的是3A模式。

3A就是Auto Exposure(AE 自動(dòng)曝光) 、Auto Focus(AF自動(dòng)對(duì)焦) 、Auto White Balance(AWB自動(dòng)白平衡),一個(gè)合格的image sensor默認(rèn)條件下的成像就是這樣。

如何調(diào)節(jié)image sensor參數(shù)拍出不同的效果,還需要了解手機(jī)上的image sensor支持什么樣的參數(shù),對(duì)于image sensor來(lái)說(shuō)接收的參數(shù)非常嚴(yán)格,對(duì)于不支持的參數(shù)會(huì)直接拋出異常。

下面是榮耀8支持的可調(diào)節(jié)參數(shù)值:


截圖 (11).png

不同手機(jī)支持參數(shù)不一樣,對(duì)于預(yù)覽大小來(lái)說(shuō)尤其重要,設(shè)置的不合理,那么我們看見(jiàn)的圖像就可能被拉伸,所以在設(shè)置預(yù)覽大小之前,必須計(jì)算出和當(dāng)前顯示畫(huà)面大小高寬比例最接近且高考值最相近的預(yù)覽Size。

懂?dāng)z影的經(jīng)常說(shuō)這張照片曝光過(guò)度,這張照片曝光不足,專業(yè)照相機(jī)都有兩個(gè)按鍵+EV/-EV,就是通過(guò)加/減曝光補(bǔ)償來(lái)彌補(bǔ)當(dāng)前環(huán)境在曝光的缺陷。
在榮耀8上最大和最小的曝光補(bǔ)償如下圖:


截圖 (12).png

從上圖可見(jiàn)不同的曝光補(bǔ)償值對(duì)于成像來(lái)說(shuō)可見(jiàn)的細(xì)節(jié)不一樣。

如何使用android.hardware.Camera進(jìn)行預(yù)覽拍照相信大家都知道,這樣的文章很多,這里不贅述,但是對(duì)于預(yù)覽幀的返回?cái)?shù)據(jù)相信大家還是有點(diǎn)疑問(wèn)的,這里再講一講YUV。

什么是YUV?

YUV,分為三個(gè)分量,“Y”表示明亮度(Luminance或Luma),也就是灰度值;而“U”和“V” 表示的則是色度(Chrominance或Chroma),作用是描述影像色彩及飽和度,用于指定像素的顏色。

與我們熟知的RGB類似,YUV也是一種顏色編碼方法,主要用于電視系統(tǒng)以及模擬視頻領(lǐng)域,它將亮度信息(Y)與色彩信息(UV)分離,沒(méi)有UV信息一樣可以顯示完整的圖像,只不過(guò)是黑白的,這樣的設(shè)計(jì)很好地解決了彩色電視機(jī)與黑白電視的兼容問(wèn)題。并且,YUV不像RGB那樣要求三個(gè)獨(dú)立的視頻信號(hào)同時(shí)傳輸,所以用YUV方式傳送占用極少的頻寬。

YUV碼流的存儲(chǔ)格式其實(shí)與其采樣的方式密切相關(guān),主流的采樣方式有三種,YUV4:4:4,YUV4:2:2,YUV4:2:0,關(guān)于其詳細(xì)原理,可以通過(guò)網(wǎng)上其它文章了解,這里我想強(qiáng)調(diào)的是如何根據(jù)其采樣格式來(lái)從碼流中還原每個(gè)像素點(diǎn)的YUV值,因?yàn)橹挥姓_地還原了每個(gè)像素點(diǎn)的YUV值,才能通過(guò)YUV與RGB的轉(zhuǎn)換公式提取出每個(gè)像素點(diǎn)的RGB值,然后顯示出來(lái)。

用三個(gè)圖來(lái)直觀地表示采集的方式吧,以黑點(diǎn)表示采樣該像素點(diǎn)的Y分量,以空心圓圈表示采用該像素點(diǎn)的UV分量。
08141454_ACE9.jpg

先記住下面這段話,以后提取每個(gè)像素的YUV分量會(huì)用到。

YUV 4:4:4采樣,每一個(gè)Y對(duì)應(yīng)一組UV分量。

YUV 4:2:2采樣,每?jī)蓚€(gè)Y共用一組UV分量。

YUV 4:2:0采樣,每四個(gè)Y共用一組UV分量。

YUV格式有兩大類:planar和packed。

對(duì)于planar的YUV格式,先連續(xù)存儲(chǔ)所有像素點(diǎn)的Y,緊接著存儲(chǔ)所有像素點(diǎn)的U,隨后是所有像素點(diǎn)的V。

對(duì)于packed的YUV格式,每個(gè)像素點(diǎn)的Y,U,V是連續(xù)交替存儲(chǔ)的。

對(duì)于預(yù)覽幀來(lái)說(shuō)在Android API <=20的版本中返回的YUV格式通常只支持兩種格式ImageFormat.NV21和ImageFormat.YV12,它們的區(qū)別就是存儲(chǔ)方式不一樣

通過(guò)camera.getParameters().getPreviewFormat();可以獲取預(yù)覽幀的數(shù)據(jù)格式,一般來(lái)說(shuō)返回的是ImageFormat.NV21

通過(guò)camera.getParameters().getSupportedPreviewFormats();可以獲取支持的預(yù)覽幀數(shù)據(jù)格式列表,通過(guò)camera.getParameters().setPreviewFormat(ImageFormat.YV12);可以設(shè)置預(yù)覽幀格式,

不同手機(jī)返回支持格式可能不同,在榮耀8上支持ImageFormat.NV21和ImageFormat.YV12兩種。

一般來(lái)說(shuō)不需要開(kāi)發(fā)者自己編寫(xiě)YUV轉(zhuǎn)RGB,android.graphics.YuvImage類支持ImageFormat.NV21和ImageFormat.YUY2轉(zhuǎn)換成jpeg格式,但通過(guò)了解YUV格式的采樣規(guī)則、存儲(chǔ)格式、轉(zhuǎn)成RGB轉(zhuǎn)換公式,可以很方便的編寫(xiě)轉(zhuǎn)換算法。

轉(zhuǎn)換公式可參考微軟信息網(wǎng)站。

4.camera2實(shí)例

最近看見(jiàn)摩托羅拉發(fā)布的z3手機(jī)中相機(jī)支持微動(dòng)攝影的文章,還是很有意思的一個(gè)功能,因?yàn)閏amera2預(yù)覽返回的數(shù)據(jù)處理起來(lái)比較方便,就寫(xiě)了一個(gè)類似微動(dòng)攝影的demo

BrowserPreview_tmp.gif
截圖 (1) (2).png

camera2相比camera1對(duì)應(yīng)用程序來(lái)說(shuō)提供了更全面的API,提供了更接近于底層相機(jī)的功能,重新設(shè)計(jì)的API更大的提高了對(duì)相機(jī)子系統(tǒng)的控制能力
在Android 8.0以下,camera1和camera2的相機(jī)架構(gòu)


image

camera1中CameraService運(yùn)行在mediaserver進(jìn)程中,雖然camera2在5.0就存在,但CameraServide依然存在于mediaserver進(jìn)程中,在Android7.0+系統(tǒng)中CameraService才作為一個(gè)獨(dú)立的系統(tǒng)服務(wù)進(jìn)程存在。

看下應(yīng)用層的使用流程

使用camera2進(jìn)行預(yù)覽拍照最好的例子可查看官方demo。

先看兩個(gè)最關(guān)鍵的問(wèn)題

1、怎么設(shè)置預(yù)覽/拍照?qǐng)D像參數(shù)?

2、從哪里拿預(yù)覽/拍照的圖像數(shù)據(jù)?

第一點(diǎn),camera1的參數(shù)設(shè)置都在camera.getParameters()中,camera2在哪里呢?在CaptureRequest.Builder中,比如設(shè)置對(duì)焦和曝光模式:


截圖 (3).png

前面講過(guò)camera的3A模式,這里看參數(shù)命名就直接明了了,更多參數(shù)詳解可以看3A 模式和狀態(tài)轉(zhuǎn)換。

另外值得注意的是camera2相比camera1支持的數(shù)據(jù)格式、預(yù)覽大小等都有很大的差異,比如在榮耀8上使用camera1進(jìn)行預(yù)覽獲取的最大預(yù)覽大小是1920x1080, 拍照支持最大size是3968x2240, 使用camera2的最大預(yù)覽尺寸為3968x2240,拍照最大支持3968x2240,camera2可支持的預(yù)覽size更加豐富,使用camera2獲取的Size根據(jù)格式的不同返回不同, 如果不支持輸出的格式則返回null,使用方式如下;

截圖 (4).png

第二點(diǎn),camera2中預(yù)覽和拍照都沒(méi)有直接的圖像數(shù)據(jù)回調(diào),它引入了ImageReader類,在createCaptureSession時(shí)可傳入surface數(shù)組入?yún)ⅲㄟ^(guò)CaptureRequest.Builder.addTarget添加多個(gè)surface接收?qǐng)D像數(shù)據(jù):

SurfaceView、TextureView等呈現(xiàn)的surface數(shù)據(jù)不能被直接訪問(wèn),而ImageReader類允許應(yīng)用程序直接訪問(wèn)呈現(xiàn)到surface的圖像數(shù)據(jù),使用方式如下:

截圖 (5).png

在camera1中支持預(yù)覽返回格式有ImageFormat.NV21和ImageFormat.YV12,但是camera2中通常僅開(kāi)放ImageFormat.JPEG、ImageFormat.RAW_SENSOR和ImageFormat.YUV_420_888,其他格式通常是私有的,不可讀取,尤其不支持ImageFormat.NV21。
本例的實(shí)現(xiàn)就是通過(guò)鎖定對(duì)焦,預(yù)覽計(jì)時(shí)3秒,從ImageReader的OnImageAvailableListener中獲取可用Image放入list,解析list生成bitmap,生成原始GIF,自定義view創(chuàng)建畫(huà)布,獲得畫(huà)布上用戶選取繪制像素點(diǎn),根據(jù)像素點(diǎn)列表,獲取第一幀之后的每一幀相關(guān)像素,循環(huán)替換第一幀選取區(qū)域像素點(diǎn),生成微動(dòng)gif,核心代碼如下:
截圖 (6).png

5.總結(jié)

從camera2和camera1的使用體驗(yàn)來(lái)說(shuō),新的api帶來(lái)了更多的可能性,但廠商定制手機(jī)五花八門(mén),同樣版本的手機(jī)也不一定都支持同樣的功能,所以做相機(jī)開(kāi)發(fā)需要考慮到相當(dāng)多的 兼容特性。
從Android API出發(fā),需要考慮camera使用版本、預(yù)覽view使用類,從設(shè)備出發(fā),需要考慮相機(jī)支持特性、支持?jǐn)?shù)據(jù)格式等,谷歌官方給出的一份兼容方案如下:


截圖 (7).png

兼容方案源代碼

參考資料:

http://lib.csdn.net/article/embeddeddevelopment/67528

http://tangzm.com/blog/?p=20

http://www.cnblogs.com/azraelly/archive/2013/01/01/2841269.htm

http://www.fourcc.org/yuv.php

https://source.android.google.cn/devices/camera/

https://blog.csdn.net/jinzhuojun/article/details/44062175

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
禁止轉(zhuǎn)載,如需轉(zhuǎn)載請(qǐng)通過(guò)簡(jiǎn)信或評(píng)論聯(lián)系作者。

相關(guān)閱讀更多精彩內(nèi)容

  • 從 Android 5.0 開(kāi)始,Google 引入了一套全新的相機(jī)框架 Camera2(android.hard...
    HJDaryl閱讀 72,388評(píng)論 21 195
  • 標(biāo)簽(空格分隔):Android Camera 相機(jī) 圖像方向 圖像大小 【注】本文所提到的 Camera 均為 ...
    koguma閱讀 18,416評(píng)論 5 47
  • mean to add the formatted="false" attribute?.[ 46% 47325/...
    ProZoom閱讀 3,162評(píng)論 0 3
  • 以下內(nèi)容翻譯來(lái)源,Google官方開(kāi)發(fā)文檔:https://developer.android.google.cn...
    肱二頭肌的孤單閱讀 5,478評(píng)論 5 47
  • 東坡 洞仙歌 冰肌玉骨,自清涼無(wú)汗。水殿風(fēng)來(lái)暗香滿。繡簾開(kāi),一點(diǎn)明月窺人;人未寢,倚枕釵橫鬢亂。起來(lái)攜素手,庭戶無(wú)...
    陳大劉七王十四閱讀 285評(píng)論 0 1

友情鏈接更多精彩內(nèi)容