有人有在iOS中使用CoreImage CICategoryTransition筛选器的示例吗?
苹果在iOS 6中添加了许多“过渡”核心图像过滤器(属于CICategoryTransition类别) 有人知道一个示例项目,它展示了如何使用它们来实际生成图像之间的实时转换吗 到目前为止,我在iOS中使用CI过滤器的唯一方法是传入源CIImage,设置各种参数,然后向过滤器请求其输出CIImage有人有在iOS中使用CoreImage CICategoryTransition筛选器的示例吗?,ios,objective-c,core-image,cifilter,Ios,Objective C,Core Image,Cifilter,苹果在iOS 6中添加了许多“过渡”核心图像过滤器(属于CICategoryTransition类别) 有人知道一个示例项目,它展示了如何使用它们来实际生成图像之间的实时转换吗 到目前为止,我在iOS中使用CI过滤器的唯一方法是传入源CIImage,设置各种参数,然后向过滤器请求其输出CIImage 根据我的经验,这相当缓慢。筛选器的CICategoryTransition类别具有时间属性。关于如何使用它的文档非常薄,但我假设您将时间参数从0(转换开始)更改为1.0(转换结束),并在指定阶段返回
根据我的经验,这相当缓慢。筛选器的CICategoryTransition类别具有时间属性。关于如何使用它的文档非常薄,但我假设您将时间参数从0(转换开始)更改为1.0(转换结束),并在指定阶段返回转换的图像。但是,我认为这不够快,无法生成平滑动画所需的30 FPS。我不同意文档“很薄”。这都是我从警察那里弄来的 转换筛选器需要执行以下任务:
- (void)awakeFromNib {
NSTimer *timer;
NSURL *url;
thumbnailWidth = 340.0;
thumbnailHeight = 240.0;
url = [NSURL fileURLWithPath: [[NSBundle mainBundle]
pathForResource: @"boots" ofType: @"jpg"]];
[self setSourceImage: [CIImage imageWithContentsOfURL: url]];
url = [NSURL fileURLWithPath: [[NSBundle mainBundle]
pathForResource: @"skier" ofType: @"jpg"]];
[self setTargetImage: [CIImage imageWithContentsOfURL: url]];
timer = [NSTimer scheduledTimerWithTimeInterval: 1.0/30.0
target: self
selector: @selector(timerFired:)
userInfo: nil
repeats: YES];
base = [NSDate timeIntervalSinceReferenceDate];
[[NSRunLoop currentRunLoop] addTimer: timer
forMode: NSDefaultRunLoopMode];
[[NSRunLoop currentRunLoop] addTimer: timer
forMode: NSEventTrackingRunLoopMode];
}
设置转换过滤器
- (void)setupTransition {
CGFloat w = thumbnailWidth;
CGFloat h = thumbnailHeight;
CIVector *extent = [CIVector vectorWithX: 0 Y: 0 Z: w W: h];
transition = [CIFilter filterWithName: @"CICopyMachineTransition"];
// Set defaults on OS X; not necessary on iOS.
[transition setDefaults];
[transition setValue: extent forKey: kCIInputExtentKey];
}
- (CIImage *)imageForTransition: (float)t {
// Remove the if-else construct if you don't want the transition to loop
if (fmodf(t, 2.0) < 1.0f) {
[transition setValue: sourceImage forKey: kCIInputImageKey];
[transition setValue: targetImage forKey: kCIInputTargetImageKey];
} else {
[transition setValue: targetImage forKey: kCIInputImageKey];
[transition setValue: sourceImage forKey: kCIInputTargetImageKey];
}
[transition setValue: @( 0.5 * (1 - cos(fmodf(t, 1.0f) * M_PI)) )
forKey: kCIInputTimeKey];
CIFilter *crop = [CIFilter filterWithName: @"CICrop"
keysAndValues:
kCIInputImageKey, [transition valueForKey: kCIOutputImageKey],
@"inputRectangle", [CIVector vectorWithX: 0 Y: 0
Z: thumbnailWidth W: thumbnailHeight],
nil];
return [crop valueForKey: kCIOutputImageKey];
}
drawRect:复印机转换效果的方法
- (void)drawRect: (NSRect)rectangle {
CGRect cg = CGRectMake(NSMinX(rectangle), NSMinY(rectangle),
NSWidth(rectangle), NSHeight(rectangle));
CGFloat 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];
}
应用过渡过滤器
- (void)setupTransition {
CGFloat w = thumbnailWidth;
CGFloat h = thumbnailHeight;
CIVector *extent = [CIVector vectorWithX: 0 Y: 0 Z: w W: h];
transition = [CIFilter filterWithName: @"CICopyMachineTransition"];
// Set defaults on OS X; not necessary on iOS.
[transition setDefaults];
[transition setValue: extent forKey: kCIInputExtentKey];
}
- (CIImage *)imageForTransition: (float)t {
// Remove the if-else construct if you don't want the transition to loop
if (fmodf(t, 2.0) < 1.0f) {
[transition setValue: sourceImage forKey: kCIInputImageKey];
[transition setValue: targetImage forKey: kCIInputTargetImageKey];
} else {
[transition setValue: targetImage forKey: kCIInputImageKey];
[transition setValue: sourceImage forKey: kCIInputTargetImageKey];
}
[transition setValue: @( 0.5 * (1 - cos(fmodf(t, 1.0f) * M_PI)) )
forKey: kCIInputTimeKey];
CIFilter *crop = [CIFilter filterWithName: @"CICrop"
keysAndValues:
kCIInputImageKey, [transition valueForKey: kCIOutputImageKey],
@"inputRectangle", [CIVector vectorWithX: 0 Y: 0
Z: thumbnailWidth W: thumbnailHeight],
nil];
return [crop valueForKey: kCIOutputImageKey];
}
设置源图像和目标图像
- (void)setSourceImage: (CIImage *)source {
sourceImage = source;
}
- (void)setTargetImage: (CIImage *)target {
targetImage = target;
}
我还建议看一下下面的项目示例,我已经编写了与上面相当类似的代码。我希望能有更好的表现。上面的代码为转换中的每一帧创建一个新的CIImage,这很慢。我已经编写了处理视频和识别其中人脸的代码,为此,我能够将传入“原始”视频和传出处理视频的CVPixelBuffers映射到OpenGL纹理,以便它们实际上使用相同的内存。像素缓冲区在整个视频处理过程中保持不变,因此不需要为每个帧分配新的缓冲区。我希望CI过渡过滤器也能有这样的功能啊,我会继续关注这个。