objective-c - 如何在 Core image 中通过 CIFilter 更改最小值或最大值?

标签 objective-c image-processing ios6 grayscale cifilter

我正在 iOS 中绘制多张灰度图像。灰度图像的值具有最小值和最大值,即对于 [41,244] 范围内的 8 位值。

我想更改最小值或最大值。我想知道如何在 this list 中设置过滤器更改最小值以及如何在 this list 中设置过滤器改变最大值?

也许接下来的绘图会很好看:

[1。读取原始灰度数据] -> [2.创建 CGImageRef] -> [3.在 GPU 中加载引用]

现在,在 iOS 6 中可以实时在 GPU 中应用滤镜。操作 1 或 2 对我来说非常慢,因为我应该在一秒钟内绘制 100 张图像。所以我需要在 GPU 中使用 CIFilter。我知道如何过滤图像。但是什么过滤器可以完成我的工作呢?

一些示例代码对我很有用。

最佳答案

CIToneCurve 应该适合这种事情。

- (UIImage*) applyToneCurveToImage:(UIImage*)image
{
    CIContext* context = self.context;
    CIImage* ciImage = [[CIImage alloc] initWithImage:image];

    CIFilter*   filter =
        [CIFilter filterWithName:@"CIToneCurve"
                   keysAndValues:
                kCIInputImageKey, ciImage,
                  @"inputPoint0",[CIVector vectorWithX:0.00 Y:0.3]
                 ,@"inputPoint1",[CIVector vectorWithX:0.25 Y:0.4]
                 ,@"inputPoint2",[CIVector vectorWithX:0.50 Y:0.5]
                 ,@"inputPoint3",[CIVector vectorWithX:0.75 Y:0.6]
                 ,@"inputPoint4",[CIVector vectorWithX:1.00 Y:0.7]
                 ,nil];

    CIImage* result = [filter valueForKey:kCIOutputImageKey];

    CGImageRef cgImage = [context createCGImage:result
                                            fromRect:[result extent]];
    UIImage* filteredImage = [UIImage imageWithCGImage:cgImage];
    CGImageRelease(cgImage);
    return filteredImage;
}

self.context 可以是 CPU 或 GPU (EAGL) 上下文。这些点描述了色调曲线。 X是输入值,Y是输出值。在此示例中,我们正在减小斜率,从而降低对比度。您也可以保持斜率不变,但切断极端值,从而减少最大值和最小值。

以下是在 iPad mini 上处理 100 张图像的一些测量结果(每个设置的四个读数的平均值)。您会发现 GPU 并不是 Elixir ,大约 60-65% 的时间都花在了移动图像数据上。这些示例以 UIImage 开始和结束。我用 CGImage 得到了非常相似的结果。

                              57x57px png  640x800px jpeg
 UIImage->CIImage->UIImage (no filtering)      
                       CPU    0.57s        2.83s   
                       GPU    0.36s        2.83s    
 UIImage->CIImage->CIFilter->UIImage
                       CPU    0.75s        4.38s    
                       GPU    0.58s        4.32s    

更新

对于 Window and Level对窗口范围外的输入进行零值调整,您希望实现如下目标:

enter image description here

CGFloat w;  //window
CGFloat l;  //level

              @"inputPoint0",[CIVector vectorWithX:0.0   Y:0.0]
             ,@"inputPoint1",[CIVector vectorWithX:l-w/2 Y:0.0]
             ,@"inputPoint2",[CIVector vectorWithX:l+w/2 Y:1.0]
             ,@"inputPoint3",[CIVector vectorWithX:l+w/2 Y:0.0]
             ,@"inputPoint4",[CIVector vectorWithX:1.0   Y:0.0]

在实践中这是行不通的。这些点描述了一条样条曲线,它在方向急剧变化时表现不佳,例如 b-c-d。 (另外点 c 和 d(2 和 3)不能共享相同的 x 值,所以在任何情况下你都必须稍微增加以便 d.x = c.x*1.01)

如果您使用多步过滤器,您可以获得结果。第一个过滤器适本地使用了 CIToneCurve(这是正确的窗口/级别算法,没有试图将您的最大级别降低到零)。

enter image description here

        CIFilter*   filter =
        [CIFilter filterWithName:@"CIToneCurve"
                   keysAndValues:
                kCIInputImageKey, ciImage,
              @"inputPoint0",[CIVector vectorWithX:0.0   Y:0.0]
             ,@"inputPoint1",[CIVector vectorWithX:l-w/2 Y:0.0]
             ,@"inputPoint2",[CIVector vectorWithX:l     Y:0.5]
             ,@"inputPoint3",[CIVector vectorWithX:l+w/2 Y:1.0]
             ,@"inputPoint4",[CIVector vectorWithX:1.0   Y:1.0]

我们制作过滤器的副本,因为我们在最后一步中将再次需要它:

        filter2 = [filter copy];

应用 CIColorControls 过滤器以最大化结果的对比度和亮度

        filter = [CIFilter filterWithName:@"CIColorControls"
                            keysAndValues:kCIInputImageKey,
                    [filter valueForKey:kCIOutputImageKey], nil];

        [filter setValue:[NSNumber numberWithFloat:-1]
                  forKey:@"inputBrightness"];
        [filter setValue:[NSNumber numberWithFloat:4]
                  forKey:@"inputContrast"];

现在分色到 1 位调色板

        filter = [CIFilter filterWithName:@"CIColorPosterize"
                             keysAndValues:kCIInputImageKey,
                     [filter valueForKey:kCIOutputImageKey], nil];

        [filter setValue:@2 forKey:@"inputLevels"];

反转结果

        filter = [CIFilter filterWithName:@"CIColorInvert"
                            keysAndValues:kCIInputImageKey,
                    [filter valueForKey:kCIOutputImageKey], nil];

现在我们将此结果用作窗口/调平图像的​​蒙版,以便所有最大白色级别都减少为黑色。

        filter = [CIFilter filterWithName:@"CIDarkenBlendMode"
                            keysAndValues:kCIInputImageKey,
                    [ filter valueForKey:kCIOutputImageKey], nil];

        [filter setValue:[filter2 valueForKey:kCIOutputImageKey]
                  forKey:@"inputBackgroundImage"];

原创

enter image description here

filter1 CIToneCurve

enter image description here

filter2 CIColorControls

enter image description here

filter3 CIColorPosterize

enter image description here

filter4 CIColorInvert

enter image description here

filter5 CIDarkenBlendMode

enter image description here

如果您看一下 Brad Larson 的 GPUImage您应该会发现 GPUImageLuminanceThresholdFilter 会更好地替换过滤器 2->5。

关于objective-c - 如何在 Core image 中通过 CIFilter 更改最小值或最大值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16185424/

相关文章:

objective-c - 将 ATMHud 添加到 tabBarController.view 是否有意义

facebook-graph-api - 使用 Facebook iOS SDK 3.1.1 checkin 的图形 API

ios - iOS 6 中方向定义的任何更改

ios - 在 iOS 7 之前的项目上编译警告 “Incompatible pointer types initializing ' UIImage *' with an expression of type ' CIImage * _Nullable”

objective-c - Objective C 组件SeparatedByCharactersInSet

ios - 有没有办法在没有登录的情况下使用 adobe creative sdk [我只想使用 adobe labs 魔术选择工具]?

java - 在 Java 中实现 MATLAB 代码 - 光照不变式

c++ - OpenCV imread 问题

Java - 位操作表现得很奇怪

ios - 在没有核心数据的情况下使用 JSON