我正在 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对窗口范围外的输入进行零值调整,您希望实现如下目标:
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
(这是正确的窗口/级别算法,没有试图将您的最大级别降低到零)。
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"];
原创
filter1 CIToneCurve
filter2 CIColorControls
filter3 CIColorPosterize
filter4 CIColorInvert
filter5 CIDarkenBlendMode
如果您看一下 Brad Larson 的 GPUImage
您应该会发现 GPUImageLuminanceThresholdFilter
会更好地替换过滤器 2->5。
关于objective-c - 如何在 Core image 中通过 CIFilter 更改最小值或最大值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16185424/