Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/dart/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
有人有在iOS中使用CoreImage CICategoryTransition筛选器的示例吗?_Ios_Objective C_Core Image_Cifilter - Fatal编程技术网

有人有在iOS中使用CoreImage CICategoryTransition筛选器的示例吗?

有人有在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(转换结束),并在指定阶段返回

苹果在iOS 6中添加了许多“过渡”核心图像过滤器(属于CICategoryTransition类别)

有人知道一个示例项目,它展示了如何使用它们来实际生成图像之间的实时转换吗

到目前为止,我在iOS中使用CI过滤器的唯一方法是传入源CIImage,设置各种参数,然后向过滤器请求其输出CIImage


根据我的经验,这相当缓慢。筛选器的CICategoryTransition类别具有时间属性。关于如何使用它的文档非常薄,但我假设您将时间参数从0(转换开始)更改为1.0(转换结束),并在指定阶段返回转换的图像。但是,我认为这不够快,无法生成平滑动画所需的30 FPS。

我不同意文档“很薄”。这都是我从警察那里弄来的

转换筛选器需要执行以下任务:

  • 创建核心图像(CIImage对象)以用于 过渡

  • 设置并安排一个计时器

  • 创建CIContext对象

  • 为要应用于映像的筛选器创建CIFilter对象

  • 在OSX上,设置过滤器的默认值

  • 设置过滤器参数

  • 设置要处理的源图像和目标图像

  • 计算时间

  • 应用过滤器

  • 得出结果

  • 重复步骤8–10,直到转换完成

  • 获取图像并设置计时器

    - (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过渡过滤器也能有这样的功能啊,我会继续关注这个。