自动增强图片效果

Core Image的自动强图片效果,会分析图像的直方图,图像属性,脸部区域,然后通过一组滤镜来改善图片效果。

自动增强滤镜

下面这些滤镜可以修正照片中的大部分问题:

Filter Purpose
CIRedEyeCorrection Repairs red/amber/white eye due to camera flash
CIFaceBalance Adjusts the color of a face to give pleasing skin tones
CIVibrance Increases the saturation of an image without distorting the skin tones
CIToneCurve Adjusts image contrast
CIHighlightShadowAdjust Adjusts shadow details

自动增强API仅有2个方法:autoAdjustmentFiltersautoAdjustmentFiltersWithOptions: . 多数情况下,我们使用带参数的方法。

通过autoAdjustmentFiltersWithOptions我们会得到一个包含图像增强的所有的滤镜的数组。依次调用它们处理图像。

1 CIContext *context = [CIContext contextWithOptions:nil];
2 UIImage *baby = [UIImage imageNamed:@"1.jpg"];
3 CIImage *myImage = [CIImage imageWithCGImage:baby.CGImage];
4 NSArray *adjustments = [myImage autoAdjustmentFilters];
5 for (CIFilter *filter in adjustments) {
6   [filter setValue:myImage forKey:kCIInputImageKey];
7   myImage = filter.outputImage;
8 }

image

左图就是自动增强之后的效果。

负片滤镜

1 CIFilter *filter = [CIFilter filterWithName:@"CIColorMatrix" keysAndValues:
2                   kCIInputImageKey, myImage,
3                   @"inputRVector", [CIVector vectorWithX: -1 Y:0 Z:0],
4                   @"inputGVector", [CIVector vectorWithX:0 Y:-1 Z:0 ],
5                   @"inputBVector", [CIVector vectorWithX: 0 Y:0 Z:-1],
6                   @"inputBiasVector", [CIVector vectorWithX:1 Y:1 Z:1],nil];

image

扣图滤镜

我们可以删除一幅图像中指定的颜色,然后填充一个背景。类似好莱坞大片的背景合成。 image

要实现上面图片的效果有下面几个步骤

创建一个 color Cube Map

一个color cube是一个3D颜色查找表(lookup table)。Core Image 滤镜 CIColorCube 使用色值作为输入,并应用一个查找表到这些色值。 CIColorCube从图像中删除所有的绿色。就是要把图中的把绿色的alpha值设置为0.0(透明)。

“绿色”包括一定范围内的颜色。最直接的处理方式是把图像的色值从RGBA转为HSV。HSV把颜色描述在圆柱坐标系内的点。

image

要删除绿色,你需要定义围绕中心点的最小和最大的角度。之后,对于任何的绿色,将其alpha值设置为0.0。纯绿的相对角度是120º。最小值和最大值要以这个值为中心。 image

Cube map数据必须预乘alpha,所以创建cube map的最后一步是把RGB值乘以你刚刚计算出的alpha值(如果是绿色,就是0,如果不是就是1.0) 下面是例子代码。

 1 CIContext *context = [CIContext contextWithOptions:nil];
 2 UIImage *baby = [UIImage imageNamed:@"2.jpg"];
 3 CIImage *myImage = [CIImage imageWithCGImage:baby.CGImage];
 4 // Allocate memory
 5 const unsigned int size = 64;
 6 float *cubeData = (float *)malloc (size * size * size * sizeof (float) * 4);
 7 float rgb[3], hsv[3], *c = cubeData;
 8 
 9 // Populate cube with a simple gradient going from 0 to 1
10 for (int z = 0; z < size; z++){
11  rgb[2] = ((double)z)/(size-1); // Blue value
12  for (int y = 0; y < size; y++){
13      rgb[1] = ((double)y)/(size-1); // Green value
14      for (int x = 0; x < size; x ++){
15          rgb[0] = ((double)x)/(size-1); // Red value
16          // Convert RGB to HSV
17          // You can find publicly available rgbToHSV functions on the Internet
18          RGBtoHSV(rgb[0],rgb[1],rgb[2], &hsv[0],&hsv[1],&hsv[2]);
19 
20          float alpha = (hsv[0] > 80 && hsv[0] < 130) ? 0.0f:1.0f;
21          // Calculate premultiplied alpha values for the cube
22          c[0] = rgb[0] * alpha;
23          c[1] = rgb[1] * alpha;
24          c[2] = rgb[2] * alpha;
25          c[3] = alpha;
26          c += 4;
27      }
28  }
29 }
30 // Create memory with the cube data
31 NSData *data = [NSData dataWithBytesNoCopy:cubeData length:(size * size * size * sizeof (float) * 4) freeWhenDone:YES];
32 CIFilter *colorCube = [CIFilter filterWithName:@"CIColorCube"];
33 [colorCube setValue:@(size) forKey:@"inputCubeDimension"];
34 [colorCube setValue:myImage forKey:@"inputImage"];
35 [colorCube setValue:data forKey:@"inputCubeData"];
36 myImage = colorCube.outputImage;
37 
38 void RGBtoHSV( float r, float g, float b, float *h, float *s, float *v ){
39  float min, max, delta;
40  min = MIN( r, MIN(g, b) );
41  max = MAX( r, MAX(g, b) );
42  *v = max;                // v
43  delta = max - min;
44  if( max != 0 )
45      *s = delta / max;      // s
46  else {
47  // r = g = b = 0       // s = 0, v is undefined
48      *s = 0;
49      *h = -1;
50      return;
51  }
52  if( r == max )
53      *h = ( g - b ) / delta;        // between yellow & magenta
54  else if( g == max )
55      *h = 2 + ( b - r ) / delta; // between cyan & yellow
56  else
57      *h = 4 + ( r - g ) / delta; // between magenta & cyan
58  *h *= 60;               // degrees
59  if( *h < 0 )
60      *h += 360;
61 }

image

我们可以根据 HSV角度试试删除黄色

    float alpha = (hsv[0] > 30 && hsv[0] < 55) ? 0.0f:1.0f;

image

删除指定的颜色后,我们可以填充一个背景图片。

image

1 UIImage *image2 = [UIImage imageNamed:@"5.png"];
2 CIImage *backgroundCIImage = [CIImage imageWithCGImage:image2.CGImage];
3 myImage = [[CIFilter filterWithName:@"CISourceOverCompositing" keysAndValues:kCIInputImageKey,myImage,kCIInputBackgroundImageKey,backgroundCIImage,nil] valueForKey:kCIOutputImageKey];
4 CGRect extent = [myImage extent];
5 CGImageRef cgImage = [context createCGImage:myImage fromRect:extent];

image