版本记录
版本号 | 时间 |
---|---|
V1.0 | 2018.01.28 |
前言
Core Image是IOS5中新加入的一个框架,里面提供了强大高效的图像处理功能,用来对基于像素的图像进行操作与分析。还提供了很多强大的滤镜,可以实现你想要的效果,下面我们就一起解析一下这个框架。感兴趣的可以参考上面几篇。
1. Core Image框架详细解析(一) —— 基本概览
2. Core Image框架详细解析(二) —— Core Image滤波器参考
3. Core Image框架详细解析(三) —— 关于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框架详细解析(八) —— 查询系统中的过滤器 Querying the System for Filters
子类化CIFilter:自定义效果的配方
您可以使用一个图像滤镜的输出作为另一个图像滤镜的输入来创建自定义效果,并根据需要链接尽可能多的滤镜。 当您通过多次使用这种方式创建效果时,请考虑继承CIFilter并封装过滤器的效果。
本章介绍Core Image如何继承自CIFilter类并创建为CIColorInvert
滤镜。 然后它描述了链接在一起的各种过滤器的recipes
,以实现有趣的效果。 按照Subclassing CIFilter to Create the CIColorInvert Filter的子类化过程,您应该能够从本章中的配方创建过滤器,或者创建自己感兴趣的Core Image提供的内置过滤器组合。
Subclassing CIFilter to Create the CIColorInvert Filter - 子类CIFilter创建CIColorInvert过滤器
当您对CIFilter
进行子类化时,您可以通过使用预设值对其进行编码或将它们链接在一起来修改现有的过滤器。 Core Image使用这种技术实现了一些内置的过滤器。
要创建一个过滤器的子类,您需要执行以下任务:
声明过滤器输入参数的属性。 您必须在每个输入参数名称前添加
input
,如inputImage。如有必要,重写
setDefaults
方法。 (这个例子中没有必要,因为输入参数是设定值。)重写
outputImage
方法。
Core Image提供的CIColorInvert
滤镜是CIColorMatrix
滤镜的变体。 顾名思义,CIColorInvert
将矢量提供给CIColorMatrix
,以反转输入图像的颜色。 按照Listing 5-1和Listing 5-2所示的简单示例构建自己的过滤器。
// 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 - 色度键过滤配方
从源图像中移除颜色或颜色范围,然后将源图像与背景图像进行合成。
创建色度键过滤器:
- 创建映射您想要移除的颜色值的数据的立方体贴图,使其透明(alpha值为0.0)。
- 使用
CIColorCube
过滤器和立方体贴图从源图像中删除色度键颜色。 - 使用
CISourceOverCompositing
过滤器将处理后的源图像混合到背景图像上
以下部分显示如何执行每个步骤。
1. Create a Cube Map - 创建一个多维数据图
彩色立方体是3D颜色查找表。Core Image过滤器CIColorCube
将颜色值作为输入,并将查找表应用于这些值。 CIColorCube
的默认查找表是一个单位矩阵,意思是它对提供的数据没有任何作用。但是,这个recipe
要求你从图像中删除所有的绿色。 (如果您愿意,可以移除不同的颜色。)
你需要通过设置绿色到alpha = 0.0来清除图像中的所有绿色,这使得透明。 “Green”包含一系列的颜色。最直接的方法是将图像中的颜色值从RGBA转换为HSV值。在HSV中,hue色调表示为围绕圆柱的中心轴的角度。在该表示中,可以将颜色可视化为饼图切片,然后简单地删除表示色度键颜色的切片。
要去除绿色,您需要定义包含绿色色调的中央通道周围的最小和最大角度。那么,对于任何绿色的东西,您将其alpha值设置为0.0。纯绿色的数值相当于120º。最小和最大角度需要以该值为中心。
立方体贴图数据必须预乘alpha,所以创建立方体贴图的最后一步是将RGB值乘以刚刚计算的alpha值,对于绿色的色调为0.0,否则为1.0。Listing 5-3显示了如何创建此过滤器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 -
从源图像中删除绿色
现在,您已经有了彩色map数据,将前景图像(即,要从中去除绿色的图像)提供给CIColorCube
滤镜并获取输出图像
[colorCube setValue:myInputImage forKey:kCIInputImageKey];
CIImage *result = [colorCube valueForKey:kCIOutputImageKey];
3. Blend the processed source image over a background image - 将处理的源图像混合到背景图像上
设置CISourceOverCompositing
过滤器的输入参数如下:
- 将
inputImage
设置为从CIColorCube
过滤器生成的图像。 - 将
inputBackgroundImage
设置为显示新背景的图像。 这个例子使用海滩图像。
现在,前景图像就好像在沙滩上一样。
White Vignette for Faces Filter Recipe - 面孔过滤Recipe的白色小插图
增加图像中检测到的脸部周围图像的亮度。
要创建一个白色的小插图过滤器:
- 在图像中找到人脸。
使用以脸部为中心的CIRadialGradient
创建基本阴影贴图。 - 将基本阴影贴图与原始图像混合。
以下部分显示如何执行每个步骤。
1. Find the Face - 找到脸部
使用CIDetector
类在图像中定位面部。 featuresInImage:options:
返回数组中的第一个元素,就是滤波器要作用的面部。 在识别脸部后,从探测器提供的边界计算脸部的中心。 您需要中心值来创建阴影图。 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 - 创建一个阴影图
使用CIRadialGradient
过滤器创建一个居中于人脸的阴影贴图。 阴影贴图的中心应该是透明的,以便图像中的面部保持不变。 图的边缘应该是不透明的白色。 两者之间的区域应该有不同程度的透明度。
要达到此效果,请将输入参数设置为CIRadialGradient
,如下所示:
- 将
inputRadius0
设置为大于图像最长尺寸的值。 - 将
inputRadius1
设置为比face更大的值,例如face.bounds.size.height + 50
。 - 将
inputColor0
设置为不透明的白色。 - 将
inputColor1
设置为透明白色。 - 将
inputCenter
设置为您使用Listing 5-4计算的面部边界的中心。
3. Blend the Gradient with the Face - 与脸部融合的渐变
设置CISourceOverCompositing
过滤器的输入参数如下:
- 将
inputImage
设置为原始图像。 - 将
inputBackgroundImage
设置为上一步生成的阴影贴图。
Tilt-Shift Filter Recipe - 倾斜移位滤波器Recipe
选择性地聚焦图像以模拟微型场景。
要创建一个倾斜移位滤镜:
- 创建图像的模糊版本。
- 创建两个线性渐变。
- 通过合成线性渐变创建一个蒙版。
- 合成模糊的图像,蒙版和原始图像。
以下部分显示如何执行每个步骤。
1. Create a Blurred Version of the image - 创建图像的模糊版本
设置CIGaussianBlur
过滤器的输入参数如下:
- 将
inputImage
设置为要处理的图像。 - 将
inputRadius
设置为10.0(这是默认值)。
2. Create Two Linear Gradients - 创建两个线性渐变
使用从上到下变化的单一颜色(例如绿色或灰色)创建线性渐变。 设置CILinearGradient
的输入参数如下:
- 将
inputPoint0
设置为(0,0.75 * h)
- 将
inputColor0
设置为(0,1,0,1)
- 将
inputPoint1
设置为(0,0.5 * h)
- 将
inputColor1
设置为(0,1,0,0)
创建一个从下到上变化的绿色线性渐变。 设置CILinearGradient
的输入参数如下:
- 将
inputPoint0
设置为(0,0.25 * h)
- 将
inputColor0
设置为(0,1,0,1)
- 将
inputPoint1
设置为(0,0.5 * h)
- 将
inputColor1
设置为(0,1,0,0)
3. Create a Mask from the Linear Gradients - 从线性渐变创建一个蒙版
要创建一个遮罩,请按如下方式设置CIAdditionCompositing
滤镜的输入参数:
- 将
inputImage
设置为您创建的第一个线性渐变。 - 将
inputBackgroundImage
设置为您创建的第二个线性渐变。
4. Combine the Blurred Image, Source Image, and the Gradients - 结合模糊图像,源图像和渐变
最后一步是使用CIBlendWithMask
过滤器,设置输入参数如下:
- 将
inputImage
设置为图像的模糊版本。 - 将
inputBackgroundImage
设置为原始未处理的图像。 - 将
inputMaskImage
设置为蒙版,即组合的渐变。
蒙版只会影响图像的外部。 蒙版的透明部分将通过原始未处理的图像显示。 蒙版的不透明部分允许显示模糊的图像。
后记
本篇已结束,后面更精彩~~~