IOS的Core Image使用
Core Image Programming Guide--图像编程指南
Core Image是一个处理和分析图像的技术,被设计用来提供接近实时处理静态和视频图像。Core Image隐藏了低级的graphics 处理过程,提供了一个易于使用的程序界面(API)。你不需要知道OpenGL ES的细节,也不需要知道GCD。它替你处理这些。
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从左向右扫过原始图像,并显示目标图像。如下图所示:
步骤:
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检测到人脸后,它可以提供人脸的信息,例如眼睛和嘴的位置。它还可以在视频中追踪一个指定的脸。
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:
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。