您的位置:首页 > 移动开发 > IOS开发

iOS之CoreImage图像处理框架

2016-05-25 01:48 525 查看
iOS为应用程序开发提供了许多可使用的框架,并构成IOS操作系统的层次架构,分为四层,从上到下依次为:Cocoa
Touch Layer(触摸UI层)、MediaLayer(媒体层)、Core Services Layer(核心服务层)、Core
OS Layer(核心OS层)。



========================================

CoreImage是一个图像框架,它基于OpenGL顶层创建,底层则用着色器来处理图像,这意味着它利用了GPU基于硬件加速来处理图像。CoreImage中有很多滤镜,它们能够一次给予一张图像或者视频帧多种视觉效果。而且滤镜可以连接起来组成一个滤镜链,把滤镜效果叠加起来处理图像。CoreImage框架最早出现于iOS5,iOS6也对这个框架进行了扩展,可以实现人脸识别

CoreImage图像处理框架


主要分为三部分:

1)定义部分:CoreImage 何CoreImageDefines。见名思义,代表了CoreImage 这个框架和它的定义。

2)操作部分:

滤镜(CIFliter):CIFilter 产生一个CIImage。典型的,接受一到多的图片作为输入,经过一些过滤操作,产生指定输出的图片。

检测(CIDetector):CIDetector 检测处理图片的特性,如使用来检测图片中人脸的眼睛、嘴巴、等等。

特征(CIFeature):CIFeature 代表由 detector处理后产生的特征。 

3)图像部分:

画布(CIContext):画布类可被用与处理Quartz 2D 或者   OpenGL。可以用它来关联CoreImage类。如滤镜、颜色等渲染处理。

上下文类,如CoreGraphics以及CoreData中的上下文用于处理绘制渲染以及处理托管对象一样,CoreImage的上下文也是实现对图像处理的具体对象。

这里需要注意的是在Context创建的时候,我们需要给它设定为是基于GPU还是CPU。(这里使用GPU)

基于GPU的话,处理速度更快,因为利用了GPU硬件的并行优势。但是GPU受限于硬件纹理尺寸,而且如果你的程序在后台继续处理和保存图片的话,那么需要使用CPU,因为当app切换到后台状态时GPU处理会被打断。

颜色(CIColor):   图片的关联与画布、图片像素颜色的处理。

向量(CIVector): 图片的坐标向量等几何方法处理。

图片(CIImage): 代表一个图像,可代表关联后输出的图像。 

查看所有内置滤镜

-(void)showAllFilters{  

NSArray *filterNames=[CIFilter filterNamesInCategory:kCICategoryBuiltIn]; 

  for (NSString *filterName in filterNames) {     

  CIFilter *filter=[CIFilter filterWithName:filterName];      

NSLog(@"\rfilter:%@\rattributes:%@",filterName,[filter attributes]); 

  }}

调用[CIFilter attributes]会返回filter详细信息,

文/anyurchao(简书作者)

原文链接:http://www.jianshu.com/p/b58b7d4615ee

著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。

使用Core Image框架创建滤镜效果一般分为以下几步:

1.创建图像上下文CIContext

//创建基于CPU的图像上下文

//    NSNumber *number=[NSNumber numberWithBool:YES];

//    NSDictionary *option=[NSDictionary dictionaryWithObject:number forKey:kCIContextUseSoftwareRenderer];

//    _context=[CIContext contextWithOptions:option];

//使用GPU渲染,推荐,但注意GPU的CIContext无法跨应用访问,例如直接在UIImagePickerController的完成方法中调用上下文处理就会自动降级为CPU渲染,所以推荐现在完成方法中保存图像,然后在主程序中调用

_context=[CIContext contextWithOptions:nil];

//    EAGLContext *eaglContext=[[EAGLContext alloc]initWithAPI:kEAGLRenderingAPIOpenGLES1];

//    _context=[CIContext contextWithEAGLContext:eaglContext];//OpenGL优化过的图像上下文

2.创建滤镜CIFilter

CIFilter用来表示CoreImage提供的各种滤镜。滤镜使用键-值来设置输入值,一旦这些值设置好,CIFilter就可以用来生成新的CIImage输出图像了。记住,这里的输出的图像不会进行实际的图像渲染,他只包含一个对输入图像的引用以及需要应用与数据上的滤镜链。IOS永远在最佳的时间选择渲染图像。

CIFilter *filter = [CIFilter filterWithName:@"CISepiaTone"];
  //设置滤镜

[filter setValue:inputImage forKey:@"inputImage"];
 //设置从输入的图片

[filter setValue:[NSNumber numberWithFloat:0.8] forKey:@"inputIntensity"];
 //设置滤镜参数

3.创建过滤原图片CIImage

         CIImage是CoreImage框架中最基本代表图像的对象,他不仅包含元图像数据,还包含作用在原图像上的滤镜链。这里我想特别强调的是CIImage和其他图像是不同的,在CIImage被CIContext渲染出来之前,他是依赖于滤镜链的,滤镜是不会更改CIImage中的图像数据。这个需要正确理解,不然会给你的程序造成错误。说到了CIImage的不同,就必须得提一下如何创建CIImage了,CIImage是不能直接有UIImage转化而来的,有以下几种创建CIImage的类方法:

[cpp] view
plaincopy

1.CIImage*image=[CIImage imageWithContentsOfURL:myURL];  

2.CIImage*image=[CIImage imageWithData:myData];  

3.CIImage*image=[CIImage imageWithCGImage:myCgimage];  

4.CIImage*image=[CIImage imageWithCVPixelBuffer:CVBuffer]

4.调用CIFilter的setValue: forKey:方法为滤镜指定源图片

        

5.设置滤镜参数【可选】

6.取得输出图片显示或保存

CIContext *context = [CIContext context];  

  

// Get outputImage from the last filter in chain  

  CIImage *ciimage = [filter outputImage];  

  

// Render the CIImage into a CGImageRef  

  CGImageRef cgimg = [context createCGImage:ciimage fromRect:[ciimage extent]];  

  

// Create a UIImage from the CGImageRef  

UIImage *uiimage = [UIImage imageWithCGImage:cgimg scale:1.0f  

orientation:ui_orientation([ciimage properties])];  

CGImageRelease(cgimg);  

// Use the UIImage in an UIImageView  

imageView.image = uiimage;  

7.CIDetector和CIFeature

         CIDetector用来分析CIImage,得到CIFeature。每个CIDetector都要用一个探测器来初始化,这个类型高数探测器要在图像中寻找什么特征。

         当一个CIDetector分析一张图片时,返回一个探测到的CIFeature的数组,如果CIDetector 被初始化为寻找面孔,那么返回的数组会被填上CIFaceFeature对象,每个CIFaceFeature都包含一个面部的CGrect引用(按照图像的坐标系),以及检测到的面孔的左眼,右眼,嘴部位置的CGPoint;

[cpp] view
plaincopy

CIDetector *faceDetector = [CIDetector   

                                    detectorOfType:CIDetectorTypeFace  

                                    context:self.imageContext   

                                    options:options];                

NSArray *faces = [faceDetector featuresInImage:coreImage  

                                               options:nil];  

for(CIFaceFeature *face in faces){  

            coreImage = [CIFilter filterWithName:@"CISourceOverCompositing"  

                                   keysAndValues:kCIInputImageKey, [self makeBoxForFace:face],  

                         kCIInputBackgroundImageKey, coreImage, nil].outputImage;  

        }  

======================

大家都知道在美图秀秀中有一个“增强”功能,利用它可以调整照片的饱和度、亮度、对比度,其实在Core Image中也有这样一款滤镜

1.
//创建基于CPU的图像上下文

//    NSNumber *number=[NSNumber numberWithBool:YES];

//    NSDictionary *option=[NSDictionary dictionaryWithObject:number forKey:kCIContextUseSoftwareRenderer];

//    _context=[CIContext contextWithOptions:option];

//使用GPU渲染,推荐,但注意GPU的CIContext无法跨应用访问,例如直接在UIImagePickerController的完成方法中调用上下文处理就会自动降级为CPU渲染,所以推荐现在完成方法中保存图像,然后在主程序中调用

_context=[CIContext contextWithOptions:nil];

//    EAGLContext *eaglContext=[[EAGLContext alloc]initWithAPI:kEAGLRenderingAPIOpenGLES1];

//    _context=[CIContext contextWithEAGLContext:eaglContext];//OpenGL优化过的图像上下文

2._colorControlsFilter=[CIFilter filterWithName:@"CIColorControls"];//设置滤镜
3.[_colorControlsFilter setValue:_image
forKey:@"inputImage"];//设置滤镜的输入图片

4.[_colorControlsFilter setValue:[NSNumber numberWithFloat:slider.value] forKey:@"inputSaturation"];//设置滤镜参数(饱和度)

[_colorControlsFilter setValue:[NSNumber numberWithFloat:slider.value] forKey:@"inputBrightness"];//设置滤镜参数(明度)

[_colorControlsFilter setValue:[NSNumber numberWithFloat:slider.value] forKey:@"inputContrast"];//设置滤镜参数(对比度)
5.

CIImage *outputImage= [_colorControlsFilter outputImage];//取得输出图像

CGImageRef temp=[_context createCGImage:outputImage fromRect:[outputImage extent]];

self.imgView.image=[UIImage imageWithCGImage:temp];//转化为CGImage显示在界面中

CGImageRelease(temp);//释放CGImage对象

===============================

下面是一个简单的棕色滤镜的使用:

?
=============================

使用中的注意事项:
1.为了防止阻塞主线程,用GCD异步执行滤镜与渲染操作,在获取渲染后的照片以后,返回主线程进行界面的更新。

2 不要重复应用滤镜,即使是同一个滤镜也不要应用两次,因为滤镜后输出照片包含滤镜链,在进行照片渲染是会将滤镜链效果叠加到原始数据上,这时会造成问题。比如,有一个CIImage,上面配置了强度为0.5的棕色滤镜,现在通过滑块将强度改为0.6,这个滤镜应该用在新的CIImage上,如果不是新的CIImage上,那么原来的CIImage中将包含强度为0.5和0.6的棕色滤镜,而我们只想0.6的棕色滤镜,这样就造成错误,这一点在编写程序的时候一定要切忌。

 

3 app中应用的滤镜太多,改变速率太快,如果是根据滑块来产生事件的话,一定要注意在使用滑条值前要首先判断更改的滤镜当前是否正在起作用,如果该滤镜正在生成新的渲染图片,则应该这次滑块的更新。这一点也是很重要的,弄的不好常常导致程序崩溃,出现内存泄露问题。
========================
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: