如何在iOS平台上实现快速图像过滤器
我正在开发iOS应用程序,用户可以在其中应用一组特定的照片过滤器。每个过滤器基本上是一组具有特定参数的Photoshop操作。这些行动包括:如何在iOS平台上实现快速图像过滤器,ios,image-processing,opengl-es,matrix-multiplication,accelerate-framework,Ios,Image Processing,Opengl Es,Matrix Multiplication,Accelerate Framework,我正在开发iOS应用程序,用户可以在其中应用一组特定的照片过滤器。每个过滤器基本上是一组具有特定参数的Photoshop操作。这些行动包括: 水平调整 亮度/对比度 色调/饱和度 单重叠加 我在我的代码中重复了所有这些操作,使用算术表达式在图像中的所有像素中循环。但是,当我在iPhone4上运行我的应用程序时,每个过滤器大约需要3-4秒才能应用,这对于用户来说是相当长的等待时间。图像大小为640x640像素,是我视图大小的@2x,因为它显示在视网膜显示器上。我发现我的主要问题是每次需要调整g
- 水平调整
- 亮度/对比度
- 色调/饱和度
- 单重叠加
Andrey.对于示例代码中的过滤器,可以使用查找表使其更快。我假设您的输入图像是每种颜色8位,在将其传递给此函数之前,您将其转换为float。对于每种颜色,这仅提供256个可能的值,因此仅提供256个可能的输出值。您可以预先计算这些数据并将它们存储在一个数组中。这将避免
pow()
计算和边界检查,因为您可以将它们考虑到预计算中
它看起来像这样:
unsigned char table[256];
for(int i=0; i<256; i++) {
float tmp = pow((float)i/255.0f, 1.3f) * 255.0;
table[i] = tmp > 255 ? 255 : (unsigned char)tmp;
}
for(int i=0; i<length; ++i)
m_OriginalPixelBuf[i] = table[m_OriginalPixelBuf[i]];
无符号字符表[256];
对于(inti=0;i255-255:(无符号字符)tmp;
}
对于(inti=0;i,正如我在评论中所说的,你也应该在苹果官方开发者论坛上发布这个问题
除此之外,还有一个真正的快速检查:您是在调用pow()
还是powf()
?即使您的数据是float
,调用pow()
也会得到双精度数学库函数,这比单精度变量powf()
要慢得多(您还必须支付浮点
和双精度
之间的额外转换费用)
还有第二项检查:你在Instruments中分析过你的过滤器吗?你真的知道执行时间花在哪里了吗?或者你在猜测吗?我其实想自己做这一切,但我找到了Silverberg的。你可以在你的图像上应用各种instagram类型的图像过滤器。这比其他图像要好得多过滤器在那里-GLImageProcessing或Cimg
也检查一下
希望这能有所帮助……如果你正在寻找最快的方法来完成这项工作,你会希望使用GPU来处理处理。它是为进行大规模并行操作而构建的,比如对单个像素进行颜色调整
正如我在中提到的,当使用OpenGL ES而不是在CPU上运行图像处理操作时,我测量到性能提高了14倍-28倍。你可以使用加速框架在CPU上更快地进行图像处理(我相信苹果声称大约4-5倍的提升在这里是可能的),但它不会像OpenGL ES那么快。但是,它可以更容易实现,这就是为什么我有时在OpenGL ES上使用加速
iOS 5.0还带来了桌面上的核心图像,这为您提供了一个很好的包装,可以对这些GPU上的图像进行调整。但是,iOS核心图像实现存在一些限制,这些限制在直接使用OpenGL ES 2.0着色器时是没有的
在我的文章中,我给出了一个OpenGL ES 2.0着色器图像过滤器的示例。进行这种处理最困难的部分是设置OpenGL ES脚手架。使用我的示例应用程序,您应该能够提取设置代码并使用它应用您自己的过滤器。为了使这更容易,我创建了一个开源的framework为您处理所有OpenGL ES交互。它几乎有您上面列出的所有过滤器,并且大多数在iPhone 4上运行640x480帧的视频不到2.5毫秒,因此它们比CPU上处理的任何东西都快。这是一个旧线程,但我是从另一个链接获得的,所以人们仍然阅读它
在iOS 5中,苹果增加了对核心图像的支持,并提供了大量的核心图像过滤器。我很确定OP中提到的所有过滤器都是可用的
Core Image在封面下使用OpenGL着色器,因此速度非常快。但是,它比OpenGL更易于使用。如果您还没有在OpenGL中工作,并且只想对CGImage或UIIMage对象应用过滤器,Core Image过滤器是一个不错的选择。从iOS 5开始,您可以使用Core Image过滤器来调整良好的ima范围ge参数
例如,要调整对比度,此代码就像一个符咒:
- (void)setImageContrast:(float)contrast forImageView:(UIImageView *)imageView {
if (contrast > MIN_CONTRAST && contrast < MAX_CONTRAST) {
CIImage *inputImage = [[CIImage alloc] initWithImage:imageView.image];
CIFilter *exposureAdjustmentFilter = [CIFilter filterWithName:@"CIColorControls"];
[exposureAdjustmentFilter setDefaults];
[exposureAdjustmentFilter setValue:inputImage forKey:@"inputImage"];
[exposureAdjustmentFilter setValue:[NSNumber numberWithFloat:contrast] forKey:@"inputContrast"]; //default = 1.00
// [exposureAdjustmentFilter setValue:[NSNumber numberWithFloat:1.0f] forKey:@"inputSaturation"]; //default = 1.00
// [exposureAdjustmentFilter setValue:[NSNumber numberWithFloat:0.0f] forKey:@"inputBrightness"];
CIImage *outputImage = [exposureAdjustmentFilter valueForKey:@"outputImage"];
CIContext *context = [CIContext contextWithOptions:nil];
imageView.image = [UIImage imageWithCGImage:[context createCGImage:outputImage fromRect:outputImage.extent]];
}
}
你也应该在苹果开发者论坛上发布这个问题。谢谢,Srikar,但实际上“ios图像过滤器”也很慢(使用相同的逐像素算法)。谢谢,powf的捕捉很好!事实上,我使用了这个函数的双版本。太棒了,非常感谢!我将在代码中实现查找表。
NSArray* filters = [CIFilter filterNamesInCategories:nil];
for (NSString* filterName in filters)
{
NSLog(@"Filter: %@", filterName);
NSLog(@"Parameters: %@", [[CIFilter filterWithName:filterName] attributes]);
}