我正在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并不是万能的,大约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镜像中通过CIFilter更改最小值或最大值?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/16185424/