CoreImage系列一:運(yùn)用CoreImage與GLKit實現(xiàn)攝像實時濾鏡

初衷

CoreImage系列是關(guān)于最近學(xué)習(xí)CoreImage處理圖片和視頻的一些總結(jié)接癌,如果有高手看到有錯誤的地方請幫我指出來趁猴,免得誤導(dǎo)了大家杨伙。謝謝淘衙。


CoreImage一瞥

CoreImage是蘋果在iOS5出的一個對圖片和視頻的圖像數(shù)據(jù)進(jìn)行實時分析横浑、加工的圖像框架剔桨。通過運(yùn)用CPU或GPU進(jìn)行圖片處理,開發(fā)者不用太關(guān)注于底層的OpenGL等技術(shù)就能進(jìn)行強(qiáng)大的圖片編輯徙融。
它的核心類有以下幾個:

  • CIContext:CoreImage的上下文,這個上下文是框架真正工作的地方洒缀,它需要分配必要的內(nèi)存,并編譯和運(yùn)行濾鏡內(nèi)核來執(zhí)行圖像處理欺冀。
  • CIFilter:CoreImage進(jìn)行圖像的濾鏡處理的對象树绩。濾鏡可以單獨(dú)使用,也可以組成一個濾鏡鏈來進(jìn)行處理 ( 因為CoreImage并不是一個真正的圖片對象隐轩,而是一個圖片生成的"模板"饺饭,所以在運(yùn)用濾鏡鏈的時候,并不會對一個圖片進(jìn)行多次濾鏡职车,而是會把這些濾鏡在底層的kernel進(jìn)行像素處理混合瘫俊,所以只會處理一次圖片,效率大大增加 ) 悴灵。
  • CIKernel:對圖片進(jìn)行處理的核心模塊军援,負(fù)責(zé)進(jìn)行像素變化等工作,最后返回加工完成的圖片称勋。開發(fā)者可以自定義Kernel進(jìn)行濾鏡開發(fā)胸哥。
    。赡鲜。空厌。
    當(dāng)然,還有一些其他的類银酬,在這里就不一一介紹嘲更,在接下來需要的時候會進(jìn)行介紹。

1.運(yùn)用CoreImage進(jìn)行圖片濾鏡

CoreImage進(jìn)行圖片的濾鏡開發(fā)其實還是挺簡單的揩瞪,最主要的是選擇合適的濾鏡赋朦,在CoreImage中提供了127個濾鏡進(jìn)行處理 ( 看今年的WWDC上的CoreImage session,好像今年又加入了很多濾鏡,達(dá)到了196個 ,Amazing! ) 宠哄。
選擇濾鏡首先選擇合適的濾鏡分類壹将,有些分類是用來處理圖片修補(bǔ)的、有些是用來合并或者轉(zhuǎn)場的等等毛嫉。在這兒我們就進(jìn)行簡單的進(jìn)行圖片的處理就行了诽俯。
首先我們需要生成一個CIFilter,我們可以通過filterNamesInCategory或者filterNamesInCategories來獲取到一個分類或多個分類的濾鏡 ( 如果你想獲取所有的 ,傳入nil就可以了 )承粤。

你拿到了filter的名字之后就可以用filterWithName來生成一個CIFilter:
CIFilter *filter = [CIFilter filterWithName:@"CIPhotoEffectMono"];

但是一般濾鏡都有一些參數(shù)可以設(shè)置的暴区,我們怎么知道這些參數(shù)喃?而且每個濾鏡的參數(shù)都可能不一樣靶岭O闪弧!

一臉懵逼.jpg

別著急彻舰,蘋果爸爸肯定不會為難我們的伐割。
我們可以獲取filter的inputKeys和outputKeys來獲取輸入?yún)?shù)和輸出參數(shù)。而且這些參數(shù)是接受什么參數(shù)也有標(biāo)志淹遵,當(dāng)然口猜,蘋果的官方文檔也是有個,傳送門透揣。
接下來我們就可以傳入圖片了济炎,傳圖片直接用KVC進(jìn)行傳入,key是kCIInputImageKey辐真,value是CIImage類型的對象须尚,你可以用NSData、CIColor侍咱、UIImage耐床、CGImgae、CVImageBufferRef等等來創(chuàng)建楔脯。
這樣就完成了所以準(zhǔn)備撩轰,現(xiàn)在你只要去取outputImage就行了,它會傳出一個CIImage對象昧廷,你可以用它來生成真正的Image進(jìn)行顯示堪嫂。
Still Image Filter.png


2.進(jìn)行視頻濾鏡

現(xiàn)在我們能夠進(jìn)行簡單的圖片處理了,現(xiàn)在我們更深入一點(diǎn)木柬,進(jìn)行視頻處理皆串。
因為我們需要實時的處理視頻,所以需要拿到視頻每一幀的圖像眉枕,所以像UIImagePickerController這樣的視頻錄制就不能滿足我們的需求了恶复,我們需要進(jìn)行深度挖掘怜森,我們就會用到AVCaptureAudioDataOutput,它能將我們錄制的每一幀傳出供我們處理谤牡,但是我們必須在一定的時間內(nèi)進(jìn)行處理副硅,否則它就會將這一幀丟掉,從而出現(xiàn)卡頓現(xiàn)象拓哟,就像我們的UITableView一樣想许。像這樣實時的處理伶授,如果我們用CPU的話顯然是不行的断序,Core Graphics的效率我們都是知道的,嘻嘻糜烹。所以需要GPU出場违诗,基于GPU處理,我們可以用GLKit和Metal來實現(xiàn)疮蹦,這篇文章我們先用GLKit來實現(xiàn)诸迟,下一篇我會用Metal來實現(xiàn)。

對于GLKit愕乎,我就用官方的原話來介紹了

The GLKit framework provides functions and classes that reduce the effort required to create new shader-based apps or to port existing apps that rely on fixed-function vertex or fragment processing provided by earlier versions of OpenGL ES or OpenGL阵苇。

簡單說就是基于OpenGL進(jìn)行封裝吧,讓我們好用感论。

回歸正題绅项,我們首先需要建立視頻連接,讓我們能看到攝像頭拍攝的東西比肄,

    //視頻輸入
    AVCaptureDevice *video = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    AVCaptureDeviceInput *videoInput = [AVCaptureDeviceInput deviceInputWithDevice:video error:nil];

    AVCaptureSession *session = [[AVCaptureSession alloc] init];
    if ([session canAddInput:videoInput]) {
        [session addInput:videoInput];
    }
    _session = session;

    //視頻輸出
    _queue = dispatch_queue_create("DataOutputQueue", DISPATCH_QUEUE_SERIAL);
    _videoOutput = [AVCaptureVideoDataOutput new];
    NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys:
                                   [NSNumber numberWithInt:kCVPixelFormatType_32BGRA], kCVPixelBufferPixelFormatTypeKey,
                                   nil];
    _videoOutput.videoSettings = videoSettings;
    [_videoOutput setAlwaysDiscardsLateVideoFrames:YES];
    [_videoOutput setSampleBufferDelegate:self queue:self.queue];
    if ([session canAddOutput:_videoOutput]){
        [session addOutput:_videoOutput];
    }
    AVCaptureConnection *connection = [_videoOutput connectionWithMediaType:AVMediaTypeVideo];
    connection.videoOrientation = AVCaptureVideoOrientationPortrait;

    [session startRunning];

這樣我們就能在videoOutPut的代理回調(diào)

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection

只不過拿到錄制的視頻幀了快耿,就是CMSampleBufferRef對象。

然后我們需要創(chuàng)建濾鏡相關(guān)的東西了芳绩,首先是GLKView的生成掀亥,它有一個方法來進(jìn)行創(chuàng)建

- (instancetype)initWithFrame:(CGRect)frame context:(EAGLContext *)context;

但是這個EAGLContext又是什么喃?其實這個是GLKit相關(guān)的上下文對象妥色,跳到EAGLContext的定義里面搪花,我們能看到它的創(chuàng)建方式:

- (instancetype) init NS_UNAVAILABLE;
- (instancetype) initWithAPI:(EAGLRenderingAPI) api;
- (instancetype) initWithAPI:(EAGLRenderingAPI) api sharegroup:(EAGLSharegroup*) sharegroup NS_DESIGNATED_INITIALIZER;

第一種不能使用,二三種都有一個EAGLRenderingAPI的枚舉嘹害,其實就是你要使用的OpenGL 的版本撮竿,sharegroup也只是一個用于debug時方便查看的對象,所以我們直接用第二種:[[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
因為我們需要對圖像進(jìn)行處理吼拥,所以我們需要關(guān)閉GLKView的自動渲染倚聚,.enableSetNeedsDisplay = NO;

有了GLKit的上下文,我們就能生成CIFilterd的上下文了凿可,

[CIContext contextWithEAGLContext:_eaglContext options:@{kCIContextWorkingColorSpace : [NSNull null]} ]

因為CIContext的創(chuàng)建開銷很大惑折,所以我們很多時候都會復(fù)用一個context授账。
接下來我們生成一個濾鏡就行了。
準(zhǔn)備工作已經(jīng)完成惨驶,接下來就是對實時視頻幀進(jìn)行處理了白热。

    CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); 
    CIImage *sourceImage = [CIImage imageWithCVPixelBuffer:(CVPixelBufferRef)imageBuffer options:nil];
    CIImage *filteredImage = RunFilter(sourceImage, self.filter);

    [_videoPreviewView bindDrawable];
    if (filteredImage)
        [self.context drawImage:filteredImage inRect:CGRectMake(0, 0, self.videoPreviewView.drawableWidth, self.videoPreviewView.drawableHeight) fromRect:sourceImage.extent];
    [_videoPreviewView display];

我們首先需要將CoreMedia的數(shù)據(jù)對象轉(zhuǎn)換成圖像數(shù)據(jù),通過CMSampleBufferRef-> CVImageBufferRef-> CIImage,我們就拿到了我們需要的原始圖像數(shù)據(jù)粗卜,接下來就是對圖像進(jìn)行濾鏡處理屋确,這里和上邊處理圖片一樣的,就不貼代碼了续扔。
接下來我們就讓濾鏡上下文開始著色和讓GLKView進(jìn)行渲染攻臀。

這樣,我們就實現(xiàn)了拍攝實時濾鏡了纱昧,demo在此刨啸。

參考文章

About Core Image

Core Image 介紹

CoreImage session

ps

最近在學(xué)習(xí)視頻相關(guān)的東西,本來想的是仿寫一個VUE來試試的识脆;恰逢今天純銀大大的新產(chǎn)品發(fā)布了设联,而且看那個準(zhǔn)維密模特看得我一愣一愣的,準(zhǔn)備參考一下貓餅來寫一個灼捂,不知道純銀大大有沒有意見啊离例,咳咳~

如果這篇還可以的話,接下來就再寫一些Core Image的文章悉稠。如果我寫的不好或者理解的不深甚至有錯誤的話宫蛆,請幫忙指出。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末偎球,一起剝皮案震驚了整個濱河市洒扎,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌衰絮,老刑警劉巖袍冷,帶你破解...
    沈念sama閱讀 217,406評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異猫牡,居然都是意外死亡胡诗,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評論 3 393
  • 文/潘曉璐 我一進(jìn)店門淌友,熙熙樓的掌柜王于貴愁眉苦臉地迎上來煌恢,“玉大人,你說我怎么就攤上這事震庭」宓郑” “怎么了?”我有些...
    開封第一講書人閱讀 163,711評論 0 353
  • 文/不壞的土叔 我叫張陵器联,是天一觀的道長二汛。 經(jīng)常有香客問我婿崭,道長,這世上最難降的妖魔是什么肴颊? 我笑而不...
    開封第一講書人閱讀 58,380評論 1 293
  • 正文 為了忘掉前任氓栈,我火速辦了婚禮,結(jié)果婚禮上婿着,老公的妹妹穿的比我還像新娘授瘦。我一直安慰自己,他們只是感情好竟宋,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評論 6 392
  • 文/花漫 我一把揭開白布提完。 她就那樣靜靜地躺著,像睡著了一般袜硫。 火紅的嫁衣襯著肌膚如雪氯葬。 梳的紋絲不亂的頭發(fā)上挡篓,一...
    開封第一講書人閱讀 51,301評論 1 301
  • 那天婉陷,我揣著相機(jī)與錄音,去河邊找鬼官研。 笑死秽澳,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的戏羽。 我是一名探鬼主播担神,決...
    沈念sama閱讀 40,145評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼始花!你這毒婦竟也來了妄讯?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,008評論 0 276
  • 序言:老撾萬榮一對情侶失蹤酷宵,失蹤者是張志新(化名)和其女友劉穎亥贸,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體浇垦,經(jīng)...
    沈念sama閱讀 45,443評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡炕置,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了男韧。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片朴摊。...
    茶點(diǎn)故事閱讀 39,795評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖此虑,靈堂內(nèi)的尸體忽然破棺而出甚纲,到底是詐尸還是另有隱情,我是刑警寧澤朦前,帶...
    沈念sama閱讀 35,501評論 5 345
  • 正文 年R本政府宣布介杆,位于F島的核電站讹弯,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏这溅。R本人自食惡果不足惜组民,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望悲靴。 院中可真熱鬧臭胜,春花似錦、人聲如沸癞尚。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽浇揩。三九已至仪壮,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間胳徽,已是汗流浹背积锅。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留养盗,地道東北人缚陷。 一個月前我還...
    沈念sama閱讀 47,899評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像往核,于是被迫代替她去往敵國和親箫爷。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評論 2 354

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

  • 老驥伏櫪聂儒,志在千里 前記 最近一直在研究圖像處理方面虎锚,既上一篇iOS Quart2D繪圖之UIImage簡單使用后...
    半笑半醉間閱讀 4,400評論 0 14
  • --繪圖與濾鏡全面解析 概述 在iOS中可以很容易的開發(fā)出絢麗的界面效果,一方面得益于成功系統(tǒng)的設(shè)計衩婚,另一方面得益...
    韓七夏閱讀 2,727評論 2 10
  • 前言現(xiàn)在很多的APP當(dāng)中選擇圖片都會帶有圖片處理效果窜护,一些類似于美圖,PS的功能谅猾,其實在iOS中系統(tǒng)內(nèi)部也有這樣一...
    清溪丷閱讀 6,940評論 3 42
  • 前言 最近在研究 Core Image 自定義 Filter 相關(guān)內(nèi)容柄慰,重新學(xué)習(xí)了 Core Image,對 Co...
    泥孩兒0107閱讀 764評論 0 4
  • 荷 一池碧水戀芙蓉税娜, 素面無黛潤潮紅坐搔。 花蓋欲滴迎風(fēng)笑, 潔凈淡雅立風(fēng)中敬矩。 荷 潔入群芳譜概行, 淡雅心自清。 待到雨...
    荷靜閱讀 305評論 10 20