Core Image使用指南

簡(jiǎn)介

Core Image是一個(gè)圖片處理及分析庫(kù),里面封裝了非常易用的API,比如大量常用濾鏡歪沃。因?yàn)樗柚鶪PU或者CPU渲染,所以可以接近實(shí)時(shí)的速度處理靜態(tài)圖片和視頻圖片嫌松,圖片可來(lái)自Core Graphics沪曙、Core Video以及I/O框架。

Core Image架構(gòu)

功能列表

Core Image提供的能力包括:

  • 通過(guò)大量?jī)?nèi)置濾鏡處理圖片
  • 通過(guò)濾鏡鏈自定義處理效果
  • 自動(dòng)化圖片增強(qiáng)
  • 特征檢測(cè)萎羔,比如人臉液走、矩形、文字等
  • 創(chuàng)建自定義濾鏡

基本概念

濾鏡

一個(gè)濾鏡在語(yǔ)義上表示某種能力,當(dāng)作用在一張圖片上時(shí)缘眶,可以經(jīng)過(guò)某種變換從而得到另一張圖片嘱根。

我們都知道,圖片在計(jì)算機(jī)中是以像素為基本單位而保存的像素矩陣巷懈,通過(guò)圖像處理單元GPU才能將其顯示在屏幕上该抒。在數(shù)學(xué)上,濾鏡其實(shí)也是一個(gè)矩陣顶燕,也叫卷積核凑保,通常比圖片的像素矩陣維度小得多。在真正處理圖片時(shí),圖片像素矩陣和卷積核做卷積運(yùn)算椿访,最終輸出一個(gè)“新”圖片浸遗。

濾鏡的處理過(guò)程

濾鏡鏈

顧名思義,濾鏡鏈就是將多個(gè)濾鏡鏈接在一起维咸,前一個(gè)濾鏡的輸出作為下一個(gè)濾鏡的輸入,就像流水線一樣惠爽,圖片從第一個(gè)濾鏡中進(jìn)入癌蓖,處理之后再進(jìn)入下一個(gè),一直到最后一個(gè)濾鏡婚肆。通過(guò)這種方式租副,可以創(chuàng)建出更加如何需求的效果。

但實(shí)際上较性,Core Image的處理邏輯有點(diǎn)不同用僧,它并不會(huì)讓一張圖片經(jīng)過(guò)多次處理。為了性能考慮赞咙,Core Image會(huì)先將多個(gè)濾鏡的卷積核合成為一個(gè)责循,然后一次性得出最終的結(jié)果。

圖片處理

簡(jiǎn)單來(lái)說(shuō)攀操,圖片處理就是將某張圖片作用于某個(gè)濾鏡的過(guò)程院仿。

在Core Image中,圖片為CIImage速和,濾鏡為CIFilter歹垫,為濾鏡設(shè)置參數(shù)要通過(guò)KVC實(shí)現(xiàn)。同時(shí)颠放,還需要一個(gè)上下文對(duì)象CIContext排惨,里面保存著所有相關(guān)的細(xì)節(jié)。因?yàn)檫@些細(xì)節(jié)非常多碰凶,所以最好在合適的時(shí)機(jī)創(chuàng)建一個(gè)可重復(fù)利用的CIContext對(duì)象暮芭。

單濾鏡

最基本的用法就是只使用單個(gè)濾鏡鹿驼,如下所示。

- (void)blurImageWithRadius:(CGFloat)radius {    
    UIImage *originalImage = [UIImage imageNamed:@"blackboard.jpg"];
    CIImage *ciimage = [CIImage imageWithData: UIImageJPEGRepresentation(originalImage, .9)];
    
    CIFilter *gaussianBlur = [CIFilter filterWithName:@"CIGaussianBlur"];
    [gaussianBlur setValue:@(radius) forKey:@"inputRadius"];
    [gaussianBlur setValue:ciimage forKey:@"inputImage"];
    
    [self.processedImageView setImage:[UIImage imageWithCIImage:gaussianBlur.outputImage]];
}

在CoreImage中所有相關(guān)操作中只能使用CIImage這個(gè)格式谴麦,但是它并不能直接呈現(xiàn)給用戶蠢沿,因?yàn)?strong>CIImage只是一種用來(lái)生產(chǎn)圖片的“配方”,其實(shí)就是一種操作流程匾效,比如從URL讀取圖片文件舷蟀,某個(gè)濾鏡操作的輸出等,只有在渲染或者輸出時(shí)才會(huì)開(kāi)始執(zhí)行面哼∫耙耍總結(jié)下來(lái),可以通過(guò)下面這些方法創(chuàng)建CIImage:

  • NSURL
  • NSData
  • UIImage
  • CGImageRef
  • CVImageBufferRef
  • CIImageProvider
- (void)createCIImageMethods {
    CIImage *ciimg;
    
    // 1. URL
    ciimg = [[CIImage alloc] initWithContentsOfURL:[NSURL URLWithString:@"some-url"]];
    
    // 2. bytes
    ciimg = [CIImage imageWithData:[NSData dataWithContentsOfFile:@"some-file-path"]];
    
    // 3. UIImage
    ciimg = [CIImage imageWithData:UIImageJPEGRepresentation([UIImage imageNamed:@"some-img-name"], .9)];
    ciimg = [CIImage imageWithData:UIImagePNGRepresentation([UIImage imageNamed:@"png-name"])];
    
    // 4. CGImageRef
    ciimg = [CIImage imageWithCGImage:[UIImage imageNamed:@"some-img"].CGImage];
    
    //...
}

濾鏡分類(lèi)

Core Image中有大量的濾鏡魔策,而且隨著系統(tǒng)的不斷升級(jí)匈子,還在不斷添加新的濾鏡。系統(tǒng)將它們分為以下這些類(lèi)別:

類(lèi)別名稱(chēng) 說(shuō)明 例子
CICategoryBlur 模糊 高斯模糊闯袒、降噪等
CICategoryColorAdjustment 顏色調(diào)整 色值虎敦、曝光度、明暗度調(diào)整政敢,色溫其徙,色調(diào)曲線等
CICategoryColorEffect 顏色效果 色值轉(zhuǎn)換、黑白效果喷户、褪色等
CICategoryCompositeOperation 合成 疊加唾那,顏色混合、差分褪尝、乘除闹获,亮度、色度混合等等
CICategoryDistortionEffect 扭曲 隆起河哑、線性隆起避诽,德羅斯特效應(yīng),替換扭曲璃谨,玻璃扭曲等
CICategoryGenerator 生成器 生成條形碼茎用、二維碼、星光??睬罗、日光,純色圖片旭斥、隨機(jī)圖片等
CICategoryGeometryAdjustment 幾何變換 仿射容达、透視變換,剪裁垂券,蘭索斯縮放
CICategoryGradient 漸變 高斯?jié)u變花盐、線性漸變羡滑、徑向漸變等
CICategoryHalftoneEffect 網(wǎng)版效果 圓形網(wǎng)屏,點(diǎn)狀網(wǎng)目板等
CICategoryReduction 不知道該如何翻譯 區(qū)域平均值算芯、最值柒昏,行、列平均值等
CICategorySharpen 銳化 亮度銳化熙揍、非銳化蒙版
CICategoryStylize 風(fēng)格化 蒙版混合职祷,軟化邊緣,喜劇效果届囚,卷積有梆,結(jié)晶,邊緣檢測(cè)等
CICategoryTileEffect 鋪貼效果 以多種不同形式填充圖案等
CICategoryTransition 過(guò)渡 條形過(guò)渡意系,溶劑過(guò)渡等

把這些功能組合在一起泥耀,基本可以實(shí)現(xiàn)一個(gè)Photoshop了。

濾鏡鏈

前面說(shuō)了蛔添,當(dāng)要經(jīng)過(guò)多個(gè)濾鏡的處理時(shí)痰催,CoreImage為了提高性能會(huì)將多個(gè)濾鏡合成為一個(gè),并在合適時(shí)機(jī)完成處理迎瞧。

例如夸溶,如果分步處理,其流程如下:

分步處理濾鏡鏈

但如果合成為一個(gè)Filter夹攒,則其流程如下:

將多個(gè)濾鏡合成為一個(gè)
- (CIImage *)processWithImage:(CIImage *)image fileterName:(NSString *)name params:(NSDictionary *)params {
    CIFilter *filter = [CIFilter filterWithName:name];
    [filter setValue:image forKey:@"inputImage"];
    for (NSString *key in params.allKeys) {
        [filter setValue:params[key] forKey:key];
    }
    return filter.outputImage;
}

- (IBAction)startProcessWithChain:(UIButton *)sender {
    CIImage *blurImg, *bloomImg, *croppedImg;
    blurImg = [self processWithImage:self.inputImage
                         fileterName:@"CIGaussianBlur"
                              params:@{kCIInputRadiusKey: @(1.2)}];
    bloomImg = [self processWithImage:blurImg
                          fileterName:@"CIBloom"
                               params:@{kCIInputRadiusKey: @(8.0),
                                        kCIInputIntensityKey: @(1.0)}];
    croppedImg = [bloomImg imageByCroppingToRect:CGRectMake(50, 100, 300, 300)];
    
    [self.processedImageView setImage:[UIImage imageWithCIImage:croppedImg]];
}

常用操作

Core Image除過(guò)用CFilter來(lái)處理圖片外蜘醋,還可以通過(guò)一些預(yù)定義的方法直接處理圖片,將更加簡(jiǎn)便咏尝。比如:

  • initWithColor: 純色圖片
  • imageByApplyingTransform: 給圖片進(jìn)行仿射變換
  • imageByCompositingOverImage: 疊加圖片
  • imageByCroppingToRect: 剪裁圖片
  • imageByClampingToRect: 擴(kuò)展邊界
  • imageByInsertingIntermediate 插值

檢測(cè)

在圖片識(shí)別處理中压语,如果要識(shí)別特定對(duì)象,一般都要先進(jìn)行輪廓檢測(cè)编检,然后再根據(jù)輪廓剪裁后識(shí)別物體胎食,這樣會(huì)更加高效準(zhǔn)確。比如人臉允懂、矩形等對(duì)象的識(shí)別厕怜。在Core Image中,提供了開(kāi)箱即用的輪廓檢測(cè)功能蕾总,其中只能進(jìn)行三類(lèi)操作:人臉粥航、矩形、文字生百。下面看看人臉檢測(cè)的使用方法:

- (void)detect:(UIBarButtonItem *)sender{
    CIImage *image = [CIImage imageWithData:UIImageJPEGRepresentation(self.image, .95)];
    NSLog(@"image size: %@", NSStringFromCGSize(self.image.size));
    CIContext *context = [CIContext context];
    NSDictionary *options = @{CIDetectorAccuracy: CIDetectorAccuracyHigh};
    CIDetector *detector = [CIDetector detectorOfType:CIDetectorTypeFace context:context options:options];
    options = @{CIDetectorImageOrientation: [[image properties] valueForKey:(NSString *)kCGImagePropertyOrientation]};
    
    NSArray *features = [detector featuresInImage:image options:options];
    
    for (CIFaceFeature *feature in features) {
        NSLog(@"face bounds: %@", NSStringFromCGRect(feature.bounds));
        [self drawBorderWithFaceFeature:feature];
    }
}

- (void)drawBorderWithFaceFeature:(CIFaceFeature *)feature{
    CGRect frame = [self convertFaceBoundsToView:feature.bounds];
    NSLog(@"converted face bounds: %@", NSStringFromCGRect(frame));

    UILabel *label = [[UILabel alloc] initWithFrame:frame];
    label.backgroundColor = [UIColor clearColor];
    label.layer.borderColor = [UIColor redColor].CGColor;
    label.layer.borderWidth = 2.f;
    [self.imageView addSubview:label];
}

- (CGRect)convertFaceBoundsToView:(CGRect)bounds{
    CGFloat ratio = CGRectGetWidth(self.imageView.bounds)/self.image.size.width;
    return CGRectMake(CGRectGetMinX(bounds)*ratio, CGRectGetMinY(bounds)*ratio, CGRectGetWidth(bounds)*ratio, CGRectGetHeight(bounds)*ratio);
}

經(jīng)過(guò)使用發(fā)現(xiàn)递雀,只要當(dāng)圖片中含有少量人時(shí)結(jié)果比較準(zhǔn)確,當(dāng)圖片清晰度降低蚀浆、并且人較多時(shí)結(jié)果不一定準(zhǔn)確缀程。

注意點(diǎn)

為了提高應(yīng)用程序的性能搜吧,在使用Core Image時(shí)盡可能注意以下細(xì)節(jié):

  • 不要每次都創(chuàng)建CIContext,應(yīng)盡可能復(fù)用杨凑;
  • 如果沒(méi)有必要滤奈,避免動(dòng)畫(huà)和顏色空間管理;
  • 盡可能使用更小的圖片撩满、簡(jiǎn)單的濾鏡蜒程;
  • 確保不要超過(guò)CPU或者GPU的限度等。

參考

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末鹦牛,一起剝皮案震驚了整個(gè)濱河市搞糕,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌曼追,老刑警劉巖窍仰,帶你破解...
    沈念sama閱讀 218,941評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異礼殊,居然都是意外死亡驹吮,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)晶伦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)碟狞,“玉大人,你說(shuō)我怎么就攤上這事婚陪∽逦郑” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,345評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵泌参,是天一觀的道長(zhǎng)脆淹。 經(jīng)常有香客問(wèn)我,道長(zhǎng)沽一,這世上最難降的妖魔是什么盖溺? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,851評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮铣缠,結(jié)果婚禮上烘嘱,老公的妹妹穿的比我還像新娘。我一直安慰自己蝗蛙,他們只是感情好蝇庭,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著捡硅,像睡著了一般遗契。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上病曾,一...
    開(kāi)封第一講書(shū)人閱讀 51,688評(píng)論 1 305
  • 那天牍蜂,我揣著相機(jī)與錄音,去河邊找鬼泰涂。 笑死鲫竞,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的逼蒙。 我是一名探鬼主播从绘,決...
    沈念sama閱讀 40,414評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼是牢!你這毒婦竟也來(lái)了僵井?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,319評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤驳棱,失蹤者是張志新(化名)和其女友劉穎批什,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體社搅,經(jīng)...
    沈念sama閱讀 45,775評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡驻债,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了形葬。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片合呐。...
    茶點(diǎn)故事閱讀 40,096評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖笙以,靈堂內(nèi)的尸體忽然破棺而出淌实,到底是詐尸還是另有隱情,我是刑警寧澤猖腕,帶...
    沈念sama閱讀 35,789評(píng)論 5 346
  • 正文 年R本政府宣布拆祈,位于F島的核電站,受9級(jí)特大地震影響谈息,放射性物質(zhì)發(fā)生泄漏缘屹。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評(píng)論 3 331
  • 文/蒙蒙 一侠仇、第九天 我趴在偏房一處隱蔽的房頂上張望轻姿。 院中可真熱鬧,春花似錦逻炊、人聲如沸互亮。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,993評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)豹休。三九已至,卻和暖如春桨吊,著一層夾襖步出監(jiān)牢的瞬間威根,已是汗流浹背凤巨。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,107評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留洛搀,地道東北人敢茁。 一個(gè)月前我還...
    沈念sama閱讀 48,308評(píng)論 3 372
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像留美,于是被迫代替她去往敵國(guó)和親彰檬。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評(píng)論 2 355

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