您的位置:首页 > 产品设计 > UI/UE

Core Image Programming Guide--图像编程指南

2015-06-03 09:06 519 查看
一、介绍

Core Image是一个处理和分析图像的技术,被设计用来提供接近实时处理静态和视频图像。Core Image隐藏了低级的graphics 处理过程,提供了一个易于使用的程序界面(API)。你不需要知道OpenGL ES的细节,也不需要知道GCD。它替你处理这些。

Core Image Programming Guide--图像编程指南 - supershll - 记忆里



1、Core Image 框架提供:

1)访问内置的图像处理filter

2)检测特征能力

3)支持自动图像增强

4)连接多个filter来创建自己想要的效果。

2、Core Image为iOS提供了超过90个内置filter,为OS X提供了超过120个的filter。你通过提供key-value对来设置filter的输入参数。filter的output可以作为另一个filter的input,这样就可以把多个filter连接起来,形成自己想要的效果。

filter有一打多的categories。一些被设计用来获得艺术的效果,例如stylize和halfone filter categories。另一些被设计用来优化修正图像问题,例如color adjustment 和 sharpen filters 。

Core Image可以分析一幅图像的质量,并提供了一系列filter来优化和调整这些,例如色度、对比度和色调等。

Core Image可以识别静止图像的人脸特征,并且可以在视频图像中追踪它们。知道脸在什么位置,你可以决定在什么地方应用filter。

3、Core Image有内置的filter相关文档。你可以查询系统来找出哪些filter是可用的。然后,对于每个filter,你可以获得一个字典,其中包含它的属性,例如输入参数、默认参数值、最小和最大值、display name,等等。

二、处理图像:

Core Image有3个类来支持图像处理:

1)CIFilter:表示一个效果,其至少有一个输入参数和产出一个output image。

2)CIImage:不可变对象,表示一幅图像。你可以synthesize image data或从一个file提供或从另一个CIFilter对象的output提供。

3)CIContext:从一个filter提供的对象,用于Core Image绘制结果。

1、概览

直接看例子:

CIContext *context = [CIContext contextWithOptions:nil]; // 1创建一个CIContext对象

CIImage *image = [CIImage imageWithContentsOfURL:myURL]; // 2创建一个CIImage对象

CIFilter *filter = [CIFilter filterWithName:@"CISepiaTone"]; // 3 创建一个filter,并设置其输入参数

[filter setValue:image forKey:kCIInputImgeKey];

[filter setValue:[NSNumber numberWithFloat:0.8f] forKey:@"InputIntensity"];

CIImage *result = [filter valueForKey:kCIOutputImageKey]; // 4 获得output图像,其输出是一个如何处理图像的处方,并没有实际被渲染。

CGImageRef cgImage = [context createCGImage:result fromRect:[result extent]; // 5 渲染CIImage到CGImage。

重要通知:一些filter处理图像是无限域的,例如在CICategoryTileEffect category中的filter。在渲染之前,无限图像必须或者被cropped(使用CICrop Filter),或者你必须指定一个有限维度的rectangle来渲染图像。

2、内置的filter:

一个filter category指定了效果的类型--blur(模糊)、distortion(变形)、generator(生成器?)、等等---或者指定了其使用目标---still image(静态图像)、video(视频)、nonsquare pixels(非方阵像素?)、等等。一个filter可以属于多个category。一个filter还拥有一个display name,这个名字是显示给用户看的,还有一个filter name,这个名字是你用来通过代码访问filter的名字。

大多数filter有多个input parameters,让你来控制如何完成处理。每个输入参数有一个attribute class,指定了其数据类型,例如NSNumber。一个输入参数可以有另一些属性,例如其默认值,允许的最小值和最大值,输入参数的display name,或其他任何在CIFilter 类中描述的属性。

例如,CIColorMonochrome filter有3个输入参数--需要处理的image,一个monochrome color,和color intensity(颜色强度)。你需要提供图像和选项--color和color intensity。大多数filters,包括CIColorMonochrome filter,为每个非图像的参数都设置了默认值。

Core Image使用KVC,这意味着你可以通过KVC获得和设置一个filter的属性。

3、创建一个Core Image Context:

1)方法:

a)contextWithOptions: :Renderer可以是CPU或GPU,仅iOS支持。

b)contextWithCGContext:options:和NSGraphicsContext : Renderer可以是CPU或GPU,仅OSX支持。

c) contextWithEAGLContext: 和 contextWithEAGLContext:options: :Renderer可以是CPU,仅iOS支持。

d) contextWithGLLContext:pixelFormat:options:和contextWithCGLContext:pixelFormat:colorSpace:options: :Renderer可以是CPU,仅OSX支持。

2)当你不需要实时性能时,创建一个Core Image Context:

CIContext *context=[CIContext contextWithOptions:nil];

如果要指定是CPU还是GPU来renderering,可以创建一个options字典,并设置kCIContextUserSoftwareRenderer键为相应的布尔值。CPU渲染慢于GPU,但是使用GPU,resulting image在其被拷贝回CPU内存和将其转换为另一个image类型之前是不会被显示的。

3)当你需要实时性能时,创建CIContext:

你应该从EAGL Context创建而不是使用contextWithOptions:,并指定GPU。优势是rendered image驻留在GPU中,并且永远不会拷贝回CPU内存中。首先你需要创建一个EAGL Context:

myEAGLContext=[[EAGLContext alloc]initWithAPI:kEAGLRenderingAPIOpenGLES2];

然后使用方法contextWithEAGLContext:来创建CIContext对象。

你应该关闭color management(通过提供null值给working color space)。Color management降低了性能。

NSMutableDictionary *options=[[NSMutableDictionary alloc]init];

[options setObject:[NSNull null] forKey:kCIContextWorkingColorSpace];

myContext=[CIContext contextWithEAGLContext:myEAGLContext options:options];

4)在OSX中创建CIContext

...

4、创建CIImage对象:

时刻记住CIImage只是一个处理实际图像的处方。CIImage实际上不产出任何pixels,直到其结果被渲染到destination。

1)创建方法:

a)图像源为URL的方法:imageWithContentsOfURL: 和imageWithContentsOfURL:options

b)图像源为Quartz 2D Image(CGImageRef):imageWithCGImage:

c) 图像源为Bitmap Data:ImageWithBitmapData:bytesPerRow:format:colorSpace: 和 imageWithImageProvider:size:format:colorSpace:options:

d)图像源为Emcode data:imageWithData:

e) 图像源为OpenGL texture: imageWithTexture:size:flipped:colorSpace:

f) ...

5、创建CIFilter:

使用filterWithName:来获得filter,name必须是filter的filter name。

在iOS中,逆获得filter的同时,其输入参数的默认值已经就设置好了,但是在OS X中,其输入参数刚开始为未定义,你还需要使用setDefaults来设置默认值。

如果你不知道一个filter的输入参数,你可以使用inputKeys来获得它们。使用setValue:forKey:来设置值。

让我们来看一个例子,使用filter来调整image的色彩度。

首先获得这个filter,它叫CIHueAdjust.

CIFilter *hueAdjust = [CIFilter filterWithName:@"CIHueAdjust"];

这个filter有2个输入参数,一个是input Image,另一个是input angle。input angle与在HSV和HLS color space中的hue的位置有关。这个角度值可以在0.0到2 pi之间。0表示颜色红;2/3 pi表示 green; 4/3 pi表示 blue。

[hueAdjust setValue: image forKey: @"inputImage"];

[hueAdjust setValue: [NSNumber numberWithFloat: 2.094] forKey: @"inputAngle"];

6、获得输出image:

使用kCIOutputImageKey=@"outputImage"键来获得输出:

CIImage *result=[hueAdjust valueForKey:@"outputImage"];

7、Rendering(渲染)the Resulting output Image:

a)方法drawImage:inRect:fromRect: 在iOS中,这个方法只渲染使用contextWithEAGLContext:创建的CIContext。

b)方法createCGImage:fromRect: 和 createCGImage:fromRect:format:colorSpace:

c)方法render:toBitmap:rowBytes:bounds:format:colorSpace:

d)方法createCGLayerWithSize:info: 只在iOS有效

e)方法render:toCVPixelBuffer: 和render:toCVPixelBuffer:bounds:colorSpace: 只在iOS有效

8、线程安全:

CIContext和CIImage都是不可变的,这意味着它们是线程安全的。但是CIFilter对象是可变的。一个CIFilter不能在多个线程中共享。如果你的应用是多线程的,每个线程必须创建其自己的CIFilter。否则,你的应用会表现的出人意料。

9、Chaining Filters:

10、使用Transition Effects:

Transition一般用在不同的images之间,或者不同场景的切换。这些效果需要时间来渲染,需要你设置一个timer。这个章节的目的是显示如何设置timer。你将学习到如何设计和应用filter(CICopyMachine)到两个静态图像。CICopyMachine filter创建一个light bar,就像你在copy machine或image scanner时看到的一样。light bar从左向右扫过原始图像,并显示目标图像。如下图所示:

Core Image Programming Guide--图像编程指南 - supershll - 记忆里



步骤:

1) 创建CImage对象用来transition

2)设置和安排timer

3)创建CIContext对象

4)创建CIFilter对象

5)设置filter的输入参数。

6)设置要处理的源和target image

7)计算时间

8)应用filter

9)绘制结果

10)重复8-10直到transition结束。

例子:假设自定义一个View。

1)在awakeFromNib中设置源image和target image和设置timer:

。。。省略

[[NSRunLoop currentRunLoop] addTimer: timer forMode: NSDefaultRunLoopMode];

[[NSRunLoop currentRunLoop] addTimer: timer forMode: NSEventTrackingRunLoopMode];

2)设置transition filter:

- (void)setupTransition

{

CIVector *extent;

float w,h;



w = thumbnailWidth;

h = thumbnailHeight;



extent = [CIVector vectorWithX: 0 Y: 0 Z: w W: h];



transition = [CIFilter filterWithName: @"CICopyMachineTransition"];

// Set defults on OS X; not necessary on iOS

[transition setDefaults];

[transition setValue: extent forKey: @"inputExtent"];

}

3)在drawRect:方法中

- (void)drawRect: (NSRect)rectangle

{

float t;

CGRect cg = CGRectMake(NSMinX(rectangle), NSMinY(rectangle),NSWidth(rectangle), NSHeight(rectangle));



t = 0.4*([NSDate timeIntervalSinceReferenceDate] - base);

if(context == nil)

{

context = [CIContext contextWithCGContext: [[NSGraphicsContext currentContext] graphicsPort] options: nil];

}

if(transition == nil)

[self setupTransition];

[context drawImage: [self imageForTransition: t + 0.1] inRect: cg fromRect: cg];

}

。。。需要的时候再查吧

11、应用filter到video:

Core Image和Core Video可以共同协作来达到很多效果。主要是在OS X中的。略过

三、检测图像中的脸:

Core Image是人脸检测,不是人脸识别。检测是指出包含人脸特征的矩形,识别是指出特定的某人的脸。在Core Image检测到人脸后,它可以提供人脸的信息,例如眼睛和嘴的位置。它还可以在视频中追踪一个指定的脸。

Core Image Programming Guide--图像编程指南 - supershll - 记忆里



1、检测脸:

使用CIDetector类来查找一幅图中的脸

CIContext *context = [CIContext contextWithOptions:nil]; // 1

NSDictionary *opts = [NSDictionary dictionaryWithObject:CIDetectorAccuracyHigh forKey:CIDetectorAccuracy]; // 2 指定detector的选项,这里是指定了精度

CIDetector *detector = [CIDetector detectorOfType:CIDetectorTypeFace context:context options:opts]; // 3

opts = [NSDictionary dictionaryWithObject: [[myImage properties] valueForKey:kCGImagePropertyOrientation] forKey:CIDetectorImageOrientation]]; // 4 让Core Image知道image的方向是很重要的。

NSArray *features = [detector featuresInImage:myImage options:opts]; // 5 包含一组CIFaceFeature对象,每个CIFaceFeature对象表示一个face,可以获得特征,例如眼睛和嘴巴的位置。

2、获得脸和脸部特征:

脸部特征包括:

1)左眼和右眼的位置

2)嘴巴的位置

3)tracking ID和tracking frame count ,Core Image使用的用来在视频中追踪用的

在你使用CIDetector获得一组CIFaceFeature对象之后,你可以循环这个数组来检查每个脸的bounds和其特征。

for (CIFaceFeature *f in features)

{

NSLog(@"%@",NSStringFromCGRect(f.bounds));

if (f.hasLeftEyePosition)

printf("Left eye %g %g\n", f.leftEyePosition.x, f.leftEyePosition.y);

if (f.hasRightEyePosition)

printf("Right eye %g %g\n", f.rightEyePosition.x, f.rightEyePosition.y);

if (f.hasMouthPosition)

printf("Mouth %g %g\n", f.mouthPosition.x, f.mouthPosition.y);

}

四、Auto Enhancing Images:

Core Image的自动增强特性分析一幅图像的histogram(直方图),人脸区域内容,和元数据属性。然后它返回一个CIFiter数组,其中的CIFiter的输入参数都已经设好值,为改善被分析的图像。

1、Auto Enhancement Filters:

下面列出了Core Image使用的用来自动增强图像的filters,这些filters补救一些在图片中最常用的issue。

1)CIRedEyeCorrection filter:用来修改red/amber(琥珀色)/white eye due to camera flash

2) CIFaceBalance filter:用来调整人脸的颜色

3)CIVibrance Filter:用来增加没有变形skin tones的图像的饱和度

4)CIToneCurve filter:用来调整图像的对比度

5)CIHighlightShadowAdjust filter:用来调整shadow details。

2、使用Auto Enhancement Filters:

只有2个方法:autoAdjustmentFilters和autoAdjustmentFiltersWithOptions:。在大多数情况下,你会使用一个options字典。

你可以这样设置options:

1)image的方向,这对CIRedEyeCorrection和CIFaceBalance filter很重要。

2)是否只应用red eye correction:设置kCIImageAutoAdjustEnhance为NO。

3)是否应用除了red eye correction之外的所有filters:设置kCIImageAutoAdjustRedEye为NO。

autoAdjustmentFiltersWithOptions:方法返回一组options filters,然后你将使用这些filters chain together,并应用到image。如下例所示:

NSDictionary *options = [NSDictionary dictionaryWithObject: [[image properties] valueForKey:kCGImagePropertyOrientation] forKey:CIDetectorImageOrientation]];

NSArray *adjustments = [myImage autoAdjustmentFiltersWithOptions:options];

for (CIFilter *filter in adjustments){

[filter setValue:myImage forKey:kCIInputImageKey];

myImage = filter.outputImage;

}

五、查询系统的filters:

1、获得Filters和Attributes的列表:

使用filterNamesInCategory:和filterNameInCategories:方法来发现哪些filters可用。

你可以传递nil参数给filterNameInCategories:来获得所有categories的所有filters。

下面列出了效果类型的category常量;

略kCICategoryDistortionEffect、GeometryAdjustment、CompositeOperation、。。。

下面列出了使用目标类型的category常量:

略 kCIImageStillImage、Video、Interlaced、NonSquarePixels、HighDynamicRange

下面列出了filter 源的category常量:

kCICategoryBuiltIn: 表示Core Image提供的filter

在你获得了一组filter names之后,你可以检索filter的属性。

CIFilter *filter;

NSDictionary *myFilterAttributes;

myFilter=[CIFilter filterWithName:@"<Filter Name>"];

myFilterAttributes=[myFilter attributes];

2、创建一个Filters options字典:

参数值类型为布尔的,可以用checkbox,有范围的也可以标志出来,使用其默认值为初始值等。

Filter的名字和属性提供了所有的信息来创建一个用户界面,让用户选择一个filter和控制其输入参数。

注意:如果你对创建一个Core Image Filter的用户界面感兴趣,你可以查看IKFilterUIView Class Reference,它提供了一个view,包含了Core Image Filter的参数控制。

六、Subclassing CIFilter:Recipes for Custom Effects

例子1:Chroma Key Filter Recipe:移除源图像中的一个颜色或一组颜色,然后混合源图像和一个背景图片。

例子2:把源图像中的脸保留,其余部位淡化

例子3:保留源图像中的某个位置,其他位置模糊化。

例子4:把源图像中的脸部模糊化,其他部位不变。

例子5:在两幅图像之间变化,中间使用一点点的像素变化

例子6:老电影化(即画面变黑白?)

七、获得最好的性能

八、使用Feedback来处理图像:

CIImageAccumulator类(仅在iOS中有效)是理想地处理feedback-based选择。

九、在你写一个自定义的filter之前,你需要知道些什么?

十、创建自定义FIlters

十一、打包和加载Image Units:
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: