CoreImage系列三:攝像頭人臉檢測與寫入本地

上一篇寫靜態(tài)圖片檢測的寫的有點冗長,導致寫不完后面的了 ( 捂臉 )。所以重新開一篇來寫。


人臉檢測

其實攝像頭的人臉檢測和靜態(tài)圖并沒有多大的區(qū)別。不同點是我們不需要手動生成CIDetector來進行檢測,蘋果在AVFoudation中內(nèi)置了人臉的檢測。
在第一篇文章中我們實現(xiàn)攝像頭的濾鏡,這次,我們在AVCaptureSession中多加入一個輸出源--AVCaptureMetadataOutput。這個類是內(nèi)置的進行檢測的類,一般現(xiàn)在進行二維碼什么的檢測,就是用的這個類。

_metaOutput = [AVCaptureMetadataOutput new];
if ([session canAddOutput:_metaOutput]) {
  [session addOutput:_metaOutput];
}
[_metaOutput setMetadataObjectsDelegate:self queue:_queue];
_metaOutput.metadataObjectTypes = [_metaOutput availableMetadataObjectTypes];

我們先生成一個新的metaOutput,并加入到session中,設置代理接受回調(diào)。
然后設置這個檢測類型,這里也有一個坑,如果你在加入到session之前獲取availableMetadataObjectTypes,你會得到空數(shù)組,這個問題我調(diào)了很久,然后看到注釋中有這么一段話,

Available metadata object types are dependent on the capabilities of the AVCaptureInputPort to which this receiver's AVCaptureConnection is connected.

可檢測的類型是跟connection有關(guān)的,因為在加入session之前,并沒有和它相關(guān)的connection,所以的到的availableMetadataObjectTypes自然是空的。

接下來在回調(diào)

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection

中接收檢測到的對象數(shù)組。
數(shù)組中裝的并不是CoreImge的feature對象,而是AVMetadataObject,但是它也有對應的人臉的位置,但是如果你直接取這個值,你會發(fā)現(xiàn),并不是標準的CGRect。

If the metadata originates from video, bounds may be expressed as scalar values from 0. - 1.

注釋中寫了,它的值是在0到1之間,所以我們需要直接轉(zhuǎn)換成對應的frame。但是一旦你開始轉(zhuǎn)換,你會發(fā)現(xiàn),這個東西有點燙手。


坐標轉(zhuǎn)換.png

其實這個bounds是經(jīng)過旋轉(zhuǎn)了的,順時針旋轉(zhuǎn)了90度。所以它的x和y都是換了的。

CGFloat x = (1-object.bounds.origin.y)*self.view.frame.size.width - object.bounds.size.width*self.view.frame.size.height;
CGFloat y =  object.bounds.origin.x*self.view.frame.size.height;
CGRect frame = CGRectMake(x, y, object.bounds.size.height*self.view.frame.size.width, object.bounds.size.width*self.view.frame.size.height);

這樣經(jīng)過一番轉(zhuǎn)換后才是真正的frame。


IMG_1952.PNG

這樣,我們獲取到了真的位置,就像處理靜態(tài)圖一樣處理就行了。后面會有demo,里面有具體代碼。


IMG_1953.PNG

寫入本地

本來如果是沒有處理過的CMSampleBufferRef,我們可以直接用writer寫入就可以了,但是我們處理過之后,生成的是CIImage,所以并不能用之前的方式。
所以我們需要將CIImage轉(zhuǎn)成CVPixelBufferRef,再用AVAssetWriterInputPixelBufferAdaptor寫入。

AVAssetWriterInputPixelBufferAdaptor

Defines an interface for appending video samples packaged as CVPixelBuffer objects to a single AVAssetWriterInput object.

可以看出AVAssetWriterInputPixelBufferAdaptor是用來寫入CVPixelBuffer的。它的生成也很簡單,

AVAssetWriterInputPixelBufferAdaptor *adaptor = [AVAssetWriterInputPixelBufferAdaptor assetWriterInputPixelBufferAdaptorWithAssetWriterInput:_videoWriterInput sourcePixelBufferAttributes:nil];

主要參數(shù)是一個AVAssetWriterInput,而且這個input應該是AVMediaTypeVideo的input。后面的參數(shù)可以不傳也可以傳<CoreVideo/CVPixelBuffer.h>內(nèi)的Pixel buffer attributes keys。

接下來我們將濾鏡完成的CIImage轉(zhuǎn)換成CVPixelBuffer,

CVPixelBufferRef buffer = NULL;
CVPixelBufferPoolCreatePixelBuffer(NULL, self.adaptor.pixelBufferPool, &buffer);
[self.context render:endImage toCVPixelBuffer:buffer];
[self.adaptor appendPixelBuffer:buffer withPresentationTime:CMSampleBufferGetPresentationTimeStamp(sampleBuffer)];
            CFRelease(buffer);

我們先生成一個空的CVPixelBufferRef類型的buffer,這里有一個CVPixelBufferPoolRef,這是一個類似于autoreleasepool的東西,在AVAssetWriterInputPixelBufferAdaptor的聲明有一段話

Using the provided pixel buffer pool for buffer allocation is typically more efficient than appending pixel buffers allocated using a separate pool.

簡單說就是用這個很方便的生成一個CVPixelBufferRef。
這個時候生成的CVPixelBufferRef還只是一個初始對象,里面并沒有包含任何的視頻數(shù)據(jù),我們需要將我們剛才的CIImage寫入到buffer中,這個用到CIContext中的API。然后我們就可以將這個buffer加入到寫入adaptor了,有個時間信息,我們直接獲取原始CMSampleBufferRef的信息就行。
這樣我們就能將我們處理過的視頻直接寫入到本地了。Demo在這里

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,983評論 6 537
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,772評論 3 422
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,947評論 0 381
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,201評論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,960評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,350評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,406評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,549評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,104評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,914評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,089評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,647評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,340評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,753評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,007評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,834評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,106評論 2 375

推薦閱讀更多精彩內(nèi)容

  • 從三月份找實習到現(xiàn)在,面了一些公司,掛了不少,但最終還是拿到小米、百度、阿里、京東、新浪、CVTE、樂視家的研發(fā)崗...
    時芥藍閱讀 42,328評論 11 349
  • gihub:https://github.com/wangdxh/Desert-Eagle/只實現(xiàn)了視頻的處理。r...
    little_wang閱讀 9,832評論 0 21
  • 本篇文章是基于谷歌有關(guān)Graphic的一篇概覽文章的翻譯:http://source.android.com/de...
    lee_3do閱讀 7,162評論 2 21
  • Java NIO(New IO)是從Java 1.4版本開始引入的一個新的IO API,可以替代標準的Java I...
    JackChen1024閱讀 7,568評論 1 143
  • 我沒有見過法國女人,但我喜歡書中的法國女人,她們什么時候都很優(yōu)雅,和環(huán)境無關(guān),和年齡也無關(guān),哪怕歲月在她們的臉上刻...
    書荒者閱讀 267評論 0 1