版本記錄
版本號 | 時間 |
---|---|
V1.0 | 2018.01.28 |
前言
Core Image是IOS5中新加入的一個框架,里面提供了強大高效的圖像處理功能,用來對基于像素的圖像進行操作與分析。還提供了很多強大的濾鏡,可以實現(xiàn)你想要的效果,下面我們就一起解析一下這個框架。感興趣的可以參考上面幾篇。
1. Core Image框架詳細解析(一) —— 基本概覽
2. Core Image框架詳細解析(二) —— Core Image濾波器參考
3. Core Image框架詳細解析(三) —— 關(guān)于Core Image
4. Core Image框架詳細解析(四) —— Processing Images處理圖像(一)
5. Core Image框架詳細解析(五) —— Processing Images處理圖像(二)
6. Core Image框架詳細解析(六) —— 圖像中的面部識別Detecting Faces in an Image(一)
7. Core Image框架詳細解析(七) —— 自動增強圖像 Auto Enhancing Images
8. Core Image框架詳細解析(八) —— 查詢系統(tǒng)中的過濾器 Querying the System for Filters
9. Core Image框架詳細解析(九) —— 子類化CIFilter:自定義效果的配方 Subclassing CIFilter: Recipes for Custom Effects(一)
10. Core Image框架詳細解析(十) —— 子類化CIFilter:自定義效果的配方 Subclassing CIFilter: Recipes for Custom Effects(二)
11. Core Image框架詳細解析(十一) —— 獲得最佳性能 Getting the Best Performance
12. Core Image框架詳細解析(十二) —— 使用反饋處理圖像 Using Feedback to Process Images
What You Need to Know Before Writing a Custom Filter - 在寫一個自定義濾波器之前你需要知道什么?
Core Image提供了編寫自定義過濾器的支持。 自定義過濾器是您為其編寫一個稱為內(nèi)核的例程,用于指定要對每個源圖像像素執(zhí)行的計算。 如果您打算使用內(nèi)置的Core Image過濾器,或者按照成為它們的子類化過濾,則不需要閱讀本章。 如果您打算編寫自定義過濾器,則應(yīng)閱讀本章,以便了解自定義過濾器中的處理路徑和組件。 閱讀本章后,您可以了解如何在Creating Custom Filters中編寫過濾器。 如果您有興趣打包自定義過濾器進行分發(fā),您還應(yīng)該閱讀 Packaging and Loading Image Units。
Filter Clients and Filter Creators - 過濾客戶端和過濾器創(chuàng)建者
Core Image是為兩種類型的開發(fā)人員設(shè)計的:Filter Clients and Filter Creators
。 如果您只打算使用Core Image過濾器,則您是過濾客戶端。 如果您打算編寫自己的過濾器,則您是過濾器創(chuàng)建者。
圖8-1顯示了典型濾波器的組件。 圖中的陰影部分表示“底層”部分 - 過濾器客戶端不需要知道任何內(nèi)容的部分,但過濾器創(chuàng)建者必須了解的部分。 未加陰影的部分顯示了向過濾器客戶端提供數(shù)據(jù)的兩個方法(attributes
和outputImage
)。 過濾器的attributes
方法返回描述過濾器的鍵值對的列表。 outputImage
方法使用下面2點生成一個圖像:
- 采樣器從源獲取像素
- 處理像素的內(nèi)核
每個自定義過濾器的核心都是內(nèi)核。 內(nèi)核指定在每個源圖像像素上執(zhí)行的計算。 內(nèi)核計算可能非常簡單或復(fù)雜。 一個非常簡單的內(nèi)核“無所事事”的過濾器可以簡單地返回源像素:
destination pixel = source pixel
過濾器創(chuàng)建者使用OpenGL著色語言(glslang)
的變體來指定每個像素的計算。 (請參閱Core Image Kernel Language Reference。)內(nèi)核對過濾器客戶端是不透明的。 過濾器實際上可以使用多個內(nèi)核例程,將一個輸出傳遞給另一個輸入。 有關(guān)如何編寫自定義過濾器的說明,請參閱Creating Custom Filters。
Note: A kernel is the actual routine, written using the Core Image variant of glslang, that a filter uses to process pixels. A CIKernel object is a Core Image object that contains a kernel routine. When you create a filter, you’ll see that the kernel routine exists in its own file—one that has a .cikernel extension. You create a CIKernel object programmatically by passing a string that contains the kernel routine. 注意:內(nèi)核是使用
glslang
的Core Image變體編寫的實際例程,過濾器用它來處理像素。CIKernel
對象是包含內(nèi)核例程的Core Image
對象。 當(dāng)你創(chuàng)建一個過濾器的時候,你會看到內(nèi)核例程存在于它自己的文件中,一個擴展名是.cikernel
。 通過傳遞一個包含內(nèi)核例程的字符串,以編程方式創(chuàng)建一個CIKernel
對象。
過濾器創(chuàng)建者可以使用NSBundle
類指定的體系結(jié)構(gòu)將它們的自定義過濾器打包為插件或圖像單元,以便其他App可以使用。 圖像單元可以包含多個過濾器,如圖8-2所示。 例如,您可以編寫一組執(zhí)行不同類型邊緣檢測的濾鏡,并將它們打包為單個圖像單元。 過濾器客戶端可以使用Core Image API來加載圖像單元,并獲取該圖像單元中包含的濾鏡列表。 請參閱Loading Image Units基本信息。 有關(guān)寫入過濾器并將其打包為獨立映像單元的深入示例和詳細信息,請參閱Image Unit Tutorial。
The Processing Path - 處理路徑
圖8-3顯示了在兩個源圖像上運行的濾鏡的像素處理路徑。源圖像總是被指定為CIImage
對象。 Core Image提供了多種獲取圖像數(shù)據(jù)的方法。您可以為圖像提供URL,讀取原始圖像數(shù)據(jù)(使用NSData類),或者將Quartz 2D圖像(CGContextRef
),OpenGL
紋理或Core Video
圖像緩沖區(qū)(CVImageBufferRef)
轉(zhuǎn)換為CIImage
對象。
請注意,輸入圖像的實際數(shù)量以及過濾器是否需要輸入圖像取決于過濾器。過濾器非常靈活 - 過濾器可以:
- 沒有輸入圖像的工作。一些過濾器根據(jù)不是圖像的輸入?yún)?shù)生成圖像。 (例如,請參閱Core Image Filter Reference中的
CICheckerboardGenerator
和CIConstantColorGenerator
過濾器。) - 需要一個圖像。 (例如,請參閱Core Image Filter Reference中的
CIColorPosterize
和CICMYKHalftone
過濾器。) - 需要兩個或更多的圖像。過濾器合成圖像或使用一個圖像中的值來控制如何處理另一個圖像中的像素通常需要兩個或更多個圖像。一個輸入圖像可以作為陰影圖像,圖像蒙版,背景圖像,或者提供查找值的來源,以控制其他圖像的處理方式。 (例如,請參閱Core Image Filter Reference中的
CIShadedMaterial
過濾器。)
處理圖像時,您有責(zé)任創(chuàng)建一個包含適當(dāng)輸入數(shù)據(jù)的CIImage
對象。
Note: Although a CIImage object has image data associated with it, it is not an image. You can think of a CIImage object as an image “recipe.” A CIImage object has all the information necessary to produce an image, but Core Image doesn’t actually render an image until it is told to do so. 注意:盡管CIImage對象具有與之關(guān)聯(lián)的圖像數(shù)據(jù),但它不是圖像。 您可以將CIImage對象視為圖像
“ recipe”
。CIImage對象具有生成圖像所需的所有信息,但Core Image實際上并不呈現(xiàn)圖像,除非被告知這樣做。
來自每個源圖像的像素由CISampler
對象提取,或簡單地取樣器sampler。顧名思義,采樣器sampler檢索圖像的樣本,并將其提供給內(nèi)核。過濾器創(chuàng)建者為每個源圖像提供一個采樣器。過濾器客戶端不需要知道有關(guān)采樣器的任何信息。
采樣器定義:
- 坐標(biāo)變換,如果不需要變換,可以是
identity transform
。 - 插值模式,可以是最近鄰采樣或雙線性插值(這是默認值)。
- 指定如何在采樣區(qū)域位于源圖像之外時生成像素的環(huán)繞模式 - 要么使用透明黑色,要么使用
clamp to the extent
。
過濾器創(chuàng)建者在內(nèi)核中定義每像素圖像處理計算,但Core Image處理這些計算的實際實現(xiàn)。Core Image確定是否使用GPU或CPU執(zhí)行計算。 Core Image根據(jù)設(shè)備功能使用Metal,OpenGL或OpenGL ES實現(xiàn)硬件光柵化。它通過仿真環(huán)境實現(xiàn)軟件光柵化,專門為在大四邊形(四邊形)上使用非投影紋理查找來評估片段程序而進行了調(diào)整。
盡管像素處理路徑是從源圖像到目的地的,但Core Image使用的計算路徑是從目的地開始的,并返回到源像素,如圖8-4所示。 這個反向計算可能看起來很笨拙,但實際上最小化了任何計算中使用的像素數(shù)量。 Core Image不使用的替代方法是處理所有源像素的蠻力方法,然后決定目的地需要什么。 讓我們仔細看看圖8-4。
假設(shè)圖8-4中的過濾器執(zhí)行某種合成操作,例如源合成合成。過濾器客戶端希望重疊兩個圖像,使得每個圖像只有一小部分被合成,以實現(xiàn)圖8-4左側(cè)所示的結(jié)果。通過展望目標(biāo)應(yīng)該是什么,Core Image可以確定來自源圖像的哪些數(shù)據(jù)影響最終圖像,然后將計算僅限于那些源像素。因此,采樣器僅從源圖像中的陰影區(qū)域提取采樣像素,如圖8-4所示。
請注意圖8-4中標(biāo)有Domain of definition
的部分。定義的范圍只是進一步限制計算的一種方法。它是所有像素都透明的區(qū)域(即,alpha分量等于0)。在此示例中,定義的域與目標(biāo)圖像完全一致。Core Image讓你提供一個CIFilterShape
對象來定義這個區(qū)域。 CIFilterShape類提供了許多可以定義矩形形狀,變換形狀以及在形狀上執(zhí)行插入,合并和交叉操作的方法。例如,如果使用比圖8-4所示陰影區(qū)域更小的矩形定義濾鏡形狀,則Core Image會使用該信息來進一步限制計算中使用的源像素。
Core Image以其他方式促進高效處理。它執(zhí)行智能緩存和編譯器優(yōu)化,使其非常適合實時視頻處理和圖像分析等任務(wù)。它緩存重復(fù)評估的任何數(shù)據(jù)集的中間結(jié)果。每當(dāng)添加新圖像時,Core Image會以最近最少使用的次序逐出數(shù)據(jù),這會導(dǎo)致緩存變得太大。經(jīng)常重復(fù)使用的對象保留在緩存中,而偶爾使用的對象可能會根據(jù)需要移入和移出緩存。您的App可從Core Image緩存中受益,而無需了解如何實施緩存的詳細信息。但是,只要可以,就可以通過重新使用對象(圖像,上下文等)來獲得最佳性能。
Core Image通過在內(nèi)核和傳遞級別使用傳統(tǒng)的編譯技術(shù)也獲得了很好的性能。Core Image用于分配寄存器的方法使臨時寄存器(每個內(nèi)核)和臨時像素緩沖器(每個過濾器圖)的數(shù)量最小化。編譯器執(zhí)行幾次優(yōu)化,并自動區(qū)分閱讀基于以前計算的依賴于數(shù)據(jù)的紋理和不依賴于數(shù)據(jù)的紋理。再次,你不需要關(guān)心編譯技術(shù)的細節(jié)。重要的一點是Core Image是硬件知識,它盡可能地使用GPU和多核CPU的功能,而且它是以智能的方式實現(xiàn)的。
Coordinate Spaces - 坐標(biāo)空間
Core Image在獨立于設(shè)備的工作空間中執(zhí)行操作。Core Image的工作空間在理論上是無限的。工作空間中的點由坐標(biāo)對(x,y)表示,其中x表示沿著水平軸的位置,并且y表示沿著垂直軸的位置。坐標(biāo)是浮點值。默認情況下,原點是(0,0)。
Core Image讀取圖像時,會將像素位置轉(zhuǎn)換為與設(shè)備無關(guān)的工作空間坐標(biāo)。當(dāng)顯示處理后的圖像時,Core Image將工作空間坐標(biāo)轉(zhuǎn)換為目標(biāo)(例如顯示器)的適當(dāng)坐標(biāo)。
編寫自己的過濾器時,需要熟悉兩個坐標(biāo)空間:目標(biāo)坐標(biāo)空間和采樣器空間。目標(biāo)坐標(biāo)空間表示要渲染的圖像。采樣器空間代表你正在從別處獲取的紋理(另一個圖像,查找表等)。您使用destCoord
函數(shù)獲取目標(biāo)空間中的當(dāng)前位置,而samplerCoord
函數(shù)提供采樣空間中的當(dāng)前位置。 (請參閱 Core Image Kernel Language Reference。)
請記住,如果源數(shù)據(jù)平鋪,則采樣器坐標(biāo)具有偏移量(dx / dy)。如果您的樣本坐標(biāo)有偏移量,則可能需要使用函數(shù)samplerTransform
將目標(biāo)位置轉(zhuǎn)換為采樣器位置。
The Region of Interest - 感興趣的區(qū)域
雖然在圖8-4中沒有明確標(biāo)注,但每個源圖像中的陰影區(qū)域都是圖中描述的采樣器的region of interest
。 感興趣區(qū)域或ROI定義了采樣器采用像素信息提供給內(nèi)核進行處理的源中的區(qū)域。 如果您是過濾器客戶端,則無需關(guān)心ROI。 但是,如果您是過濾器創(chuàng)建者,則需要了解關(guān)注區(qū)域與定義域之間的關(guān)系。
回想一下,定義域描述了一個過濾器的邊界形狀。 理論上,這個形狀可以是無邊界的。 例如,考慮一個過濾器,創(chuàng)建一個可以延伸到無限的重復(fù)模式。
ROI和定義域可以通過以下方式相互關(guān)聯(lián):
- 它們恰好一致 - 源和目標(biāo)之間有1:1映射。例如,色調(diào)過濾器處理來自ROI中的工作空間坐標(biāo)(r,s)的像素以在定義域中的工作空間坐標(biāo)(r,s)處產(chǎn)生像素。
- 他們彼此依賴,但以某種方式調(diào)制。一些最有意思的濾鏡 - 例如模糊和變形 - 在計算一個目標(biāo)像素時使用許多源像素。例如,失真過濾器可以使用來自ROI中的工作坐標(biāo)空間的像素(r,s)及其鄰居在定義域中產(chǎn)生單個像素(r,s)。
- 定義域是從采樣器提供的查找表中的值中計算出來的。圖或表格中值的位置與源圖像和目的地中的工作空間坐標(biāo)無關(guān)。位于(r,s)中的著色圖像中的值不需要是在定義域中的工作空間坐標(biāo)(r,s)處產(chǎn)生像素的值。許多濾鏡使用著色圖像或查找表中提供的值與圖像源結(jié)合使用。例如,顏色漸變或近似函數(shù)的表(如
arcsin
函數(shù))提供的值與工作坐標(biāo)的概念無關(guān)。
除非另有指示,否則Core Image假定ROI和定義域一致。 如果你寫一個這個假設(shè)不適用的過濾器,你需要為Core Image提供一個例程來計算特定采樣器的ROI。
請參閱Supplying an ROI Function以獲取更多信息。
Executable and Nonexecutable Filters - 可執(zhí)行和不可執(zhí)行的過濾器
您可以根據(jù)自定義Core Image過濾器是否需要輔助二進制可執(zhí)行文件加載到客戶端應(yīng)用程序的地址空間中進行分類。在您使用Core Image API時,您會注意到這些API簡稱為可執(zhí)行文件和不可執(zhí)行文件。過濾器創(chuàng)建者可以選擇寫任何一種過濾器。過濾器客戶端可以選擇僅使用不可執(zhí)行或使用兩種過濾器。
安全性是區(qū)分CPU可執(zhí)行文件和CPU不可執(zhí)行過濾器的主要動機。不可執(zhí)行的過濾器只包含一個Core Image內(nèi)核程序來描述過濾器操作。相比之下,一個可執(zhí)行的過濾器也包含在CPU上運行的機器代碼。 Core Image內(nèi)核程序在受限制的環(huán)境中運行,不能構(gòu)成病毒,特洛伊木馬或其他安全威脅,而運行在CPU上的任意代碼都可以。
不可執(zhí)行的過濾器有特殊要求,其中之一是不可執(zhí)行的過濾器必須作為圖像單元的一部分進行封裝。過濾器創(chuàng)建者可以讀取Writing Nonexecutable Filters以獲取更多信息。過濾器客戶端可以在Loading Image Units中查找有關(guān)加載每種過濾器的信息。
Color Components and Premultiplied Alpha - 顏色組件和預(yù)乘Alpha
Premultiplied alpha
是一個術(shù)語,用于描述源顏色,其組成部分已經(jīng)乘以一個alpha值。通過消除對每個顏色分量執(zhí)行乘法運算的需要,預(yù)乘可以加快圖像的渲染速度。例如,在RGB色彩空間中,使用預(yù)乘alpha來渲染圖像會消除圖像中每個像素的三次乘法運算(紅色次alpha,綠色次alpha,藍色次alpha)。
過濾器創(chuàng)建者必須提供Core Image以及由alpha值預(yù)乘的顏色分量。否則,過濾器的行為就好像一個顏色分量的alpha值是1.0。確保顏色組件預(yù)乘是非常重要的操作顏色的過濾器。
默認情況下,Core Image假定處理節(jié)點是每像素128位,線性光,預(yù)乘RGBA浮點值,使用GenericRGB
色彩空間。您可以通過提供Quartz 2D CGColorSpace
對象來指定不同的工作色彩空間。請注意,工作色彩空間必須是基于RGB的。如果您將YUV數(shù)據(jù)作為輸入(或其他不是基于RGB的數(shù)據(jù)),則可以使用ColorSync
功能轉(zhuǎn)換為工作色彩空間。 (有關(guān)創(chuàng)建和使用CGColorspace
對象的信息,請參見Quartz 2D Programming Guide。)
對于8位YUV 4:2:2
來源,Core Image每千兆字節(jié)可以處理240個HD圖層。八位YUV是DV,MPEG,未壓縮的D1和JPEG等視頻源的原生色彩格式。您需要將YUV色彩空間轉(zhuǎn)換為Core Image的RGB色彩空間。
See Also - 也可參考
Shantzis, Michael A., “A Model for Efficient and Flexible Image Computing,” (1994), Proceedings of the 21st Annual Conference on Computer Graphics and Interactive Techniques.
Smith, Alvy Ray, “Image Compositing Fundamentals,” Memo 4, Microsoft, July 1995. Available from http://alvyray.com/Memos/MemosCG.htm#ImageCompositing
后記
本篇已結(jié)束,后面更精彩~~~