如何使用Core Image Framework为iOS创建简单的自定义过滤器?
我想在我的应用程序中使用一个自定义过滤器。现在我知道我需要使用核心映像框架,但我不确定这是正确的方法。 核心映像框架用于Mac OS和iOS 5.0——我不确定是否可以用于定制CIFilter效果。 你能帮我解决这个问题吗?如何使用Core Image Framework为iOS创建简单的自定义过滤器?,ios,image-processing,core-image,Ios,Image Processing,Core Image,我想在我的应用程序中使用一个自定义过滤器。现在我知道我需要使用核心映像框架,但我不确定这是正确的方法。 核心映像框架用于Mac OS和iOS 5.0——我不确定是否可以用于定制CIFilter效果。 你能帮我解决这个问题吗? 谢谢大家 过时 您还不能在iOS中创建自己的自定义内核/过滤器。具体见: 虽然本文档包含在参考库中,但它 尚未对iOS 5.0进行详细更新。即将进行的修订将 详细说明iOS上核心映像的差异。特别是关键 不同之处在于,iOS上的核心映像不包括 创建自定义图像过滤器 (我用粗体
谢谢大家 过时 您还不能在iOS中创建自己的自定义内核/过滤器。具体见: 虽然本文档包含在参考库中,但它 尚未对iOS 5.0进行详细更新。即将进行的修订将 详细说明iOS上核心映像的差异。特别是关键 不同之处在于,iOS上的核心映像不包括 创建自定义图像过滤器
(我用粗体显示)正如Adam所说,目前iOS上的核心映像不支持像旧版Mac实现那样的定制内核。这将框架的功能限制为现有过滤器的某种组合 (更新:2/13/2012) 因此,我为iOS创建了一个名为的开源框架,它允许您创建自定义过滤器,以便使用OpenGL ES 2.0片段着色器应用于图像和视频。我将详细介绍此框架如何在中运行。基本上,您可以提供自己的自定义OpenGL着色语言(GLSL)片段着色器来创建自定义过滤器,然后针对静态图像或实时视频运行该过滤器。此框架与支持OpenGL ES 2.0的所有iOS设备兼容,并可以创建以iOS 4.0为目标的应用程序 例如,您可以使用如下代码设置实时视频过滤:
GPUImageVideoCamera *videoCamera = [[GPUImageVideoCamera alloc] initWithSessionPreset:AVCaptureSessionPreset640x480 cameraPosition:AVCaptureDevicePositionBack];
GPUImageFilter *customFilter = [[GPUImageFilter alloc] initWithFragmentShaderFromFile:@"CustomShader"];
GPUImageView *filteredVideoView = [[GPUImageView alloc] initWithFrame:CGRectMake(0.0, 0.0, viewWidth, viewHeight)];
// Add the view somewhere so it's visible
[videoCamera addTarget:thresholdFilter];
[customFilter addTarget:filteredVideoView];
[videoCamera startCameraCapture];
作为定义过滤器的自定义片段着色器程序的示例,以下应用了深褐色色调效果:
varying highp vec2 textureCoordinate;
uniform sampler2D inputImageTexture;
void main()
{
lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);
lowp vec4 outputColor;
outputColor.r = (textureColor.r * 0.393) + (textureColor.g * 0.769) + (textureColor.b * 0.189);
outputColor.g = (textureColor.r * 0.349) + (textureColor.g * 0.686) + (textureColor.b * 0.168);
outputColor.b = (textureColor.r * 0.272) + (textureColor.g * 0.534) + (textureColor.b * 0.131);
gl_FragColor = outputColor;
}
用于在Mac上编写自定义核心映像内核的语言与GLSL非常相似。事实上,您可以做一些在桌面核心映像中做不到的事情,因为核心映像的内核语言缺少GLSL所具有的一些东西(比如分支)。最初接受的答案被贬低了。在iOS 8中,您可以为过滤器创建自定义内核。有关这方面的更多信息,请访问:
CIFilter* PrewittKernel = [CIFilter filterWithName:@"PrewittKernel"];
CIImage *result = [CIFilter filterWithName:@"PrewittKernel" keysAndValues:kCIInputImageKey, self.inputImage, nil].outputImage;
下面是一个使用OpenGL将Prewitt操作符应用于图像的简单示例;首先是Cocoa Touch类(CIFilter的子类),然后是CIKernel文件(包含OpenGL ES 3.0代码):
头文件:
//
// PrewittKernel.h
// Photo Filter
//
// Created by James Alan Bush on 5/23/15.
//
//
#import <CoreImage/CoreImage.h>
@interface PrewittKernel : CIFilter
{
CIImage *inputImage;
}
@property (retain, nonatomic) CIImage *inputImage;
@end
//
// GaussianKernel.h
// Chroma
//
// Created by James Alan Bush on 7/12/15.
// Copyright © 2015 James Alan Bush. All rights reserved.
//
#import <CoreImage/CoreImage.h>
@interface GaussianKernel : CIFilter
{
CIImage *inputImage;
NSNumber *inputRadius;
}
@property (retain, nonatomic) CIImage *inputImage;
@property (retain, nonatomic) NSNumber *inputRadius;
@end
这是另一个过滤器,它通过使用内置核心图像过滤器(无核心图像内核代码,OpenGL)从原始图像中减去(或者说,差分)高斯模糊图像来生成反锐化掩模;它显示了如何指定和使用自定义属性,即高斯模糊的半径:
头文件:
//
// PrewittKernel.h
// Photo Filter
//
// Created by James Alan Bush on 5/23/15.
//
//
#import <CoreImage/CoreImage.h>
@interface PrewittKernel : CIFilter
{
CIImage *inputImage;
}
@property (retain, nonatomic) CIImage *inputImage;
@end
//
// GaussianKernel.h
// Chroma
//
// Created by James Alan Bush on 7/12/15.
// Copyright © 2015 James Alan Bush. All rights reserved.
//
#import <CoreImage/CoreImage.h>
@interface GaussianKernel : CIFilter
{
CIImage *inputImage;
NSNumber *inputRadius;
}
@property (retain, nonatomic) CIImage *inputImage;
@property (retain, nonatomic) NSNumber *inputRadius;
@end
请注意,尽管您不能编写自己的内核,但可以组合现有的CIFILTER以获得您想要的效果。你想创造什么样的效果?确实如此。您也可以完全自己编写自己的图像过滤器函数,直接对数据进行操作。如果您明智地使用Accelerate框架,您还将获得重要的硬件支持。iOS 8添加了自定义CoreImage过滤器(即自定义
CIKernel
)。可以在此处建议:感谢您的回答!是的,如果使用openGL,这对我来说是最好的结果。但是现在我对OpenGL的这些特性有了一些了解谢谢你的更新,这是一个老问题,我认为新的答案可以帮助其他人找到一些新的细节,如果他们使用iOS 8 sdk的话。
//
// GaussianKernel.m
// Chroma
//
// Created by James Alan Bush on 7/12/15.
// Copyright © 2015 James Alan Bush. All rights reserved.
//
#import "GaussianKernel.h"
@implementation GaussianKernel
@synthesize inputImage;
@synthesize inputRadius;
+ (NSDictionary *)customAttributes
{
return @{
@"inputRadius" :
@{
kCIAttributeMin : @3.0,
kCIAttributeMax : @15.0,
kCIAttributeDefault : @7.5,
kCIAttributeType : kCIAttributeTypeScalar
}
};
}
- (void)setDefaults
{
self.inputRadius = @7.5;
}
- (CIImage *)outputImage
{
CIImage *result = self.inputImage;
CGRect rect = [[GlobalCIImage sharedSingleton].ciImage extent];
rect.origin = CGPointZero;
CGRect cropRectLeft = CGRectMake(0, 0, rect.size.width, rect.size.height);
CIVector *cropRect = [CIVector vectorWithX:rect.origin.x Y:rect.origin.y Z:rect.size.width W:rect.size.height];
result = [[CIFilter filterWithName:@"CIGaussianBlur" keysAndValues:kCIInputImageKey, result, @"inputRadius", [NSNumber numberWithFloat:inputRadius.floatValue], nil].outputImage imageByCroppingToRect:cropRectLeft];
result = [CIFilter filterWithName:@"CICrop" keysAndValues:@"inputImage", result, @"inputRectangle", cropRect, nil].outputImage;
result = [CIFilter filterWithName:@"CIDifferenceBlendMode" keysAndValues:kCIInputImageKey, result, kCIInputBackgroundImageKey, result, nil].outputImage;
return result;
}
@end