Core Image框架詳細(xì)解析(九) —— 子類化CIFilter:自定義效果的配方 Subclassing CIFilter: Recipes for Custom Effects(一)

版本記錄

版本號(hào) 時(shí)間
V1.0 2018.01.28

前言

Core Image是IOS5中新加入的一個(gè)框架,里面提供了強(qiáng)大高效的圖像處理功能,用來對(duì)基于像素的圖像進(jìn)行操作與分析。還提供了很多強(qiáng)大的濾鏡,可以實(shí)現(xiàn)你想要的效果,下面我們就一起解析一下這個(gè)框架。感興趣的可以參考上面幾篇。
1. Core Image框架詳細(xì)解析(一) —— 基本概覽
2. Core Image框架詳細(xì)解析(二) —— Core Image濾波器參考
3. Core Image框架詳細(xì)解析(三) —— 關(guān)于Core Image
4. Core Image框架詳細(xì)解析(四) —— Processing Images處理圖像(一)
5. Core Image框架詳細(xì)解析(五) —— Processing Images處理圖像(二)
6. Core Image框架詳細(xì)解析(六) —— 圖像中的面部識(shí)別Detecting Faces in an Image(一)
7. Core Image框架詳細(xì)解析(七) —— 自動(dòng)增強(qiáng)圖像 Auto Enhancing Images
8. Core Image框架詳細(xì)解析(八) —— 查詢系統(tǒng)中的過濾器 Querying the System for Filters

子類化CIFilter:自定義效果的配方

您可以使用一個(gè)圖像濾鏡的輸出作為另一個(gè)圖像濾鏡的輸入來創(chuàng)建自定義效果,并根據(jù)需要鏈接盡可能多的濾鏡。 當(dāng)您通過多次使用這種方式創(chuàng)建效果時(shí),請(qǐng)考慮繼承CIFilter并封裝過濾器的效果。

本章介紹Core Image如何繼承自CIFilter類并創(chuàng)建為CIColorInvert濾鏡。 然后它描述了鏈接在一起的各種過濾器的recipes,以實(shí)現(xiàn)有趣的效果。 按照Subclassing CIFilter to Create the CIColorInvert Filter的子類化過程,您應(yīng)該能夠從本章中的配方創(chuàng)建過濾器,或者創(chuàng)建自己感興趣的Core Image提供的內(nèi)置過濾器組合。


Subclassing CIFilter to Create the CIColorInvert Filter - 子類CIFilter創(chuàng)建CIColorInvert過濾器

當(dāng)您對(duì)CIFilter進(jìn)行子類化時(shí),您可以通過使用預(yù)設(shè)值對(duì)其進(jìn)行編碼或?qū)⑺鼈冩溄釉谝黄饋硇薷默F(xiàn)有的過濾器。 Core Image使用這種技術(shù)實(shí)現(xiàn)了一些內(nèi)置的過濾器。

要?jiǎng)?chuàng)建一個(gè)過濾器的子類,您需要執(zhí)行以下任務(wù):

  • 聲明過濾器輸入?yún)?shù)的屬性。 您必須在每個(gè)輸入?yún)?shù)名稱前添加input,如inputImage。

  • 如有必要,重寫setDefaults方法。 (這個(gè)例子中沒有必要,因?yàn)檩斎雲(yún)?shù)是設(shè)定值。)

  • 重寫outputImage方法。

Core Image提供的CIColorInvert濾鏡是CIColorMatrix濾鏡的變體。 顧名思義,CIColorInvert將矢量提供給CIColorMatrix,以反轉(zhuǎn)輸入圖像的顏色。 按照Listing 5-1和Listing 5-2所示的簡(jiǎn)單示例構(gòu)建自己的過濾器。

// Listing 5-1  The interface for the CIColorInvert filter

@interface CIColorInvert: CIFilter {
    CIImage *inputImage;
}
@property (retain, nonatomic) CIImage *inputImage;
@end
// Listing 5-2  The outputImage method for the CIColorInvert filter

@implementation CIColorInvert
@synthesize inputImage;
- (CIImage *) outputImage
{
      CIFilter *filter = [CIFilter filterWithName:@"CIColorMatrix"
                            withInputParameters: @{
            kCIInputImageKey: inputImage,
        @"inputRVector": [CIVector vectorWithX:-1 Y:0 Z:0],
        @"inputGVector": [CIVector vectorWithX:0 Y:-1 Z:0],
        @"inputBVector": [CIVector vectorWithX:0 Y:0 Z:-1],
        @"inputBiasVector": [CIVector vectorWithX:1 Y:1 Z:1],
      return filter.outputImage;
}

Chroma Key Filter Recipe - 色度鍵過濾配方

從源圖像中移除顏色或顏色范圍,然后將源圖像與背景圖像進(jìn)行合成。

Figure 5-1 The Chroma Key filter processing chain

創(chuàng)建色度鍵過濾器:

  • 創(chuàng)建映射您想要移除的顏色值的數(shù)據(jù)的立方體貼圖,使其透明(alpha值為0.0)。
  • 使用CIColorCube過濾器和立方體貼圖從源圖像中刪除色度鍵顏色。
  • 使用CISourceOverCompositing過濾器將處理后的源圖像混合到背景圖像上

以下部分顯示如何執(zhí)行每個(gè)步驟。

1. Create a Cube Map - 創(chuàng)建一個(gè)多維數(shù)據(jù)圖

彩色立方體是3D顏色查找表。Core Image過濾器CIColorCube將顏色值作為輸入,并將查找表應(yīng)用于這些值。 CIColorCube的默認(rèn)查找表是一個(gè)單位矩陣,意思是它對(duì)提供的數(shù)據(jù)沒有任何作用。但是,這個(gè)recipe要求你從圖像中刪除所有的綠色。 (如果您愿意,可以移除不同的顏色。)

你需要通過設(shè)置綠色到alpha = 0.0來清除圖像中的所有綠色,這使得透明。 “Green”包含一系列的顏色。最直接的方法是將圖像中的顏色值從RGBA轉(zhuǎn)換為HSV值。在HSV中,hue色調(diào)表示為圍繞圓柱的中心軸的角度。在該表示中,可以將顏色可視化為餅圖切片,然后簡(jiǎn)單地刪除表示色度鍵顏色的切片。

要去除綠色,您需要定義包含綠色色調(diào)的中央通道周圍的最小和最大角度。那么,對(duì)于任何綠色的東西,您將其alpha值設(shè)置為0.0。純綠色的數(shù)值相當(dāng)于120o。最小和最大角度需要以該值為中心。

立方體貼圖數(shù)據(jù)必須預(yù)乘alpha,所以創(chuàng)建立方體貼圖的最后一步是將RGB值乘以剛剛計(jì)算的alpha值,對(duì)于綠色的色調(diào)為0.0,否則為1.0。Listing 5-3顯示了如何創(chuàng)建此過濾器recipe所需的顏色立方體。

// Listing 5-3  The color cube in code

// Allocate memory
const unsigned int size = 64;
float *cubeData = (float *)malloc (size * size * size * sizeof (float) * 4);
float rgb[3], hsv[3], *c = cubeData;

// Populate cube with a simple gradient going from 0 to 1
for (int z = 0; z < size; z++){
    rgb[2] = ((double)z)/(size-1); // Blue value
    for (int y = 0; y < size; y++){
        rgb[1] = ((double)y)/(size-1); // Green value
        for (int x = 0; x < size; x ++){
            rgb[0] = ((double)x)/(size-1); // Red value
            // Convert RGB to HSV
            // You can find publicly available rgbToHSV functions on the Internet
            rgbToHSV(rgb, hsv);
            // Use the hue value to determine which to make transparent
            // The minimum and maximum hue angle depends on
            // the color you want to remove
            float alpha = (hsv[0] > minHueAngle && hsv[0] < maxHueAngle) ? 0.0f: 1.0f;
            // Calculate premultiplied alpha values for the cube
            c[0] = rgb[0] * alpha;
            c[1] = rgb[1] * alpha;
            c[2] = rgb[2] * alpha;
            c[3] = alpha;
            c += 4; // advance our pointer into memory for the next color value
        }
    }
}

// Create memory with the cube data
NSData *data = [NSData dataWithBytesNoCopy:cubeData
                       length:cubeDataSize
                       freeWhenDone:YES];
CIColorCube *colorCube = [CIFilter filterWithName:@"CIColorCube"];
[colorCube setValue:@(size) forKey:@"inputCubeDimension"];

// Set data for cube
[colorCube setValue:data forKey:@"inputCubeData"];

2. Remove green from the source image -

從源圖像中刪除綠色

現(xiàn)在,您已經(jīng)有了彩色map數(shù)據(jù),將前景圖像(即,要從中去除綠色的圖像)提供給CIColorCube濾鏡并獲取輸出圖像

[colorCube setValue:myInputImage forKey:kCIInputImageKey];
CIImage *result = [colorCube valueForKey:kCIOutputImageKey];

3. Blend the processed source image over a background image - 將處理的源圖像混合到背景圖像上

設(shè)置CISourceOverCompositing過濾器的輸入?yún)?shù)如下:

  • inputImage設(shè)置為從CIColorCube過濾器生成的圖像。
  • inputBackgroundImage設(shè)置為顯示新背景的圖像。 這個(gè)例子使用海灘圖像。

現(xiàn)在,前景圖像就好像在沙灘上一樣。


White Vignette for Faces Filter Recipe - 面孔過濾Recipe的白色小插圖

增加圖像中檢測(cè)到的臉部周圍圖像的亮度。

Figure 5-2 The White Vignette filter processing chain

要?jiǎng)?chuàng)建一個(gè)白色的小插圖過濾器:

  • 在圖像中找到人臉。
    使用以臉部為中心的CIRadialGradient創(chuàng)建基本陰影貼圖。
  • 將基本陰影貼圖與原始圖像混合。

以下部分顯示如何執(zhí)行每個(gè)步驟。

1. Find the Face - 找到臉部

使用CIDetector類在圖像中定位面部。 featuresInImage:options:返回?cái)?shù)組中的第一個(gè)元素,就是濾波器要作用的面部。 在識(shí)別臉部后,從探測(cè)器提供的邊界計(jì)算臉部的中心。 您需要中心值來創(chuàng)建陰影圖。 Listing 5-4顯示了如何使用CIDetector定位面部。

// Listing 5-4  Using CIDetector to locate one face

CIDetector *detector = [CIDector detectorOfType:CIDetectorTypeFace
                                        context:nil
                                        options:nil];
NSArray *faceArray = [detector featuresInImage:image options:nil];
CIFeature *face = faceArray[0];
CGFloat xCenter = face.bounds.origin.x + face.bounds.size.width/2.0;
CGFloat yCenter = face.bounds.origin.y + face.bounds.size.height/2.0;
CIVector *center = [CIVector vectorWithX:xCenter Y:yCenter];

2. Create a Shade Map - 創(chuàng)建一個(gè)陰影圖

使用CIRadialGradient過濾器創(chuàng)建一個(gè)居中于人臉的陰影貼圖。 陰影貼圖的中心應(yīng)該是透明的,以便圖像中的面部保持不變。 圖的邊緣應(yīng)該是不透明的白色。 兩者之間的區(qū)域應(yīng)該有不同程度的透明度。

要達(dá)到此效果,請(qǐng)將輸入?yún)?shù)設(shè)置為CIRadialGradient,如下所示:

  • inputRadius0設(shè)置為大于圖像最長(zhǎng)尺寸的值。
  • inputRadius1設(shè)置為比face更大的值,例如face.bounds.size.height + 50
  • inputColor0設(shè)置為不透明的白色。
  • inputColor1設(shè)置為透明白色。
  • inputCenter設(shè)置為您使用Listing 5-4計(jì)算的面部邊界的中心。

3. Blend the Gradient with the Face - 與臉部融合的漸變

設(shè)置CISourceOverCompositing過濾器的輸入?yún)?shù)如下:

  • inputImage設(shè)置為原始圖像。
  • inputBackgroundImage設(shè)置為上一步生成的陰影貼圖。

Tilt-Shift Filter Recipe - 傾斜移位濾波器Recipe

選擇性地聚焦圖像以模擬微型場(chǎng)景。

Figure 5-3 The Tilt-Shift filter processing chain

要?jiǎng)?chuàng)建一個(gè)傾斜移位濾鏡:

  • 創(chuàng)建圖像的模糊版本。
  • 創(chuàng)建兩個(gè)線性漸變。
  • 通過合成線性漸變創(chuàng)建一個(gè)蒙版。
  • 合成模糊的圖像,蒙版和原始圖像。

以下部分顯示如何執(zhí)行每個(gè)步驟。

1. Create a Blurred Version of the image - 創(chuàng)建圖像的模糊版本

設(shè)置CIGaussianBlur過濾器的輸入?yún)?shù)如下:

  • inputImage設(shè)置為要處理的圖像。
  • inputRadius設(shè)置為10.0(這是默認(rèn)值)。

2. Create Two Linear Gradients - 創(chuàng)建兩個(gè)線性漸變

使用從上到下變化的單一顏色(例如綠色或灰色)創(chuàng)建線性漸變。 設(shè)置CILinearGradient的輸入?yún)?shù)如下:

  • inputPoint0設(shè)置為(0,0.75 * h)
  • inputColor0設(shè)置為(0,1,0,1)
  • inputPoint1設(shè)置為(0,0.5 * h)
  • inputColor1設(shè)置為(0,1,0,0)

創(chuàng)建一個(gè)從下到上變化的綠色線性漸變。 設(shè)置CILinearGradient的輸入?yún)?shù)如下:

  • inputPoint0設(shè)置為(0,0.25 * h)
  • inputColor0設(shè)置為(0,1,0,1)
  • inputPoint1設(shè)置為(0,0.5 * h)
  • inputColor1設(shè)置為(0,1,0,0)

3. Create a Mask from the Linear Gradients - 從線性漸變創(chuàng)建一個(gè)蒙版

要?jiǎng)?chuàng)建一個(gè)遮罩,請(qǐng)按如下方式設(shè)置CIAdditionCompositing濾鏡的輸入?yún)?shù):

  • inputImage設(shè)置為您創(chuàng)建的第一個(gè)線性漸變。
  • inputBackgroundImage設(shè)置為您創(chuàng)建的第二個(gè)線性漸變。

4. Combine the Blurred Image, Source Image, and the Gradients - 結(jié)合模糊圖像,源圖像和漸變

最后一步是使用CIBlendWithMask過濾器,設(shè)置輸入?yún)?shù)如下:

  • inputImage設(shè)置為圖像的模糊版本。
  • inputBackgroundImage設(shè)置為原始未處理的圖像。
  • inputMaskImage設(shè)置為蒙版,即組合的漸變。

蒙版只會(huì)影響圖像的外部。 蒙版的透明部分將通過原始未處理的圖像顯示。 蒙版的不透明部分允許顯示模糊的圖像。

后記

本篇已結(jié)束,后面更精彩~~~

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

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