iOS慢图像像素迭代

时间:2014-12-12 21:42:24

标签: ios image-processing swift

我正在尝试在Swift中实现图像的RGB直方图计算(我是iOS新手)。 然而,1500x1000图像的计算时间约为66秒,我认为这太慢了。 有没有办法加速图像遍历?

P.S。当前代码如下:

func calcHistogram(image: UIImage) {
    let bins: Int = 20;
    let width = Int(image.size.width);
    let height = Int(image.size.height);
    let binStep: Double = Double(bins-1)/255.0
    var hist = Array(count:bins, repeatedValue:Array(count:bins, repeatedValue:Array(count:bins, repeatedValue:Int())))

    for i in 0..<bins {
        for j in 0..<bins {
            for k in 0..<bins {
                hist[i][j][k] = 0;
            }
        }
    }

    var pixelData = CGDataProviderCopyData(CGImageGetDataProvider(image.CGImage))
    var data: UnsafePointer<UInt8> = CFDataGetBytePtr(pixelData)
    for x in 0..<width {
        for y in 0..<height {
            var pixelInfo: Int = ((width * y) + x) * 4
            var r = Double(data[pixelInfo])
            var g = Double(data[pixelInfo+1])
            var b = Double(data[pixelInfo+2])

            let r_bin: Int = Int(floor(r*binStep));
            let g_bin: Int = Int(floor(g*binStep));
            let b_bin: Int = Int(floor(b*binStep));
            hist[r_bin][g_bin][b_bin] += 1;
        }
    }

}

2 个答案:

答案 0 :(得分:4)

正如我对此问题的评论中所述,在您尝试优化此代码之前,您可能会重新考虑一些事项。

但即使你确实转向更好的整体解决方案,比如基于GPU的直方图,图书馆,或两者兼而有之......你有一些Swift陷阱,你可以在这里讨论,所以你不要#39;在其他地方遇到它们。

首先,这段代码:

var hist = Array(count:bins, repeatedValue:Array(count:bins, repeatedValue:Array(count:bins, repeatedValue:Int())))

for i in 0..<bins {
    for j in 0..<bins {
        for k in 0..<bins {
            hist[i][j][k] = 0;
        }
    }
}

...正在初始化3D数组的每个成员两次,结果相同。 Int()生成的值为零,因此您可以省略三for次循环。 (并且可能会在最里面的Int()参数中将0更改为repeatedValue:,以使其更具可读性。)

其次,Swift中的数组是写时复制,但是这种优化可以在多维数组中分解:更改嵌套数组的元素会导致整个嵌套数组被重写而不仅仅是一个元素。乘以嵌套数组的深度和你在双for循环中进行的元素写入次数,并且...它并不漂亮。

除非您的垃圾箱需要以这种方式组织,否则我建议为它们寻找不同的数据结构。三个独立的阵列?一个Int数组,其中索引i为红色,i + 1为绿色,i + 2为蓝色?您定义的一个自定义struct数组是否有单独的r,g和b成员?查看概念上适合您的口味或应用程序的其余部分,以及配置文件以确保其正常运行。

最后,一些Swift风格点:

    第二个循环中的
  • pixelInforgb不会发生变化。使用let,而不是var,优化程序会感谢您。
  • 声明和初始化let foo: Int = Int(whatever)之类的内容是多余的。有些人喜欢明确键入所有变量/常量,但它确实使你的代码可读性更低,更难以重构。
  • Int(floor(x))是多余的 - 转换为整数始终发言。

答案 1 :(得分:0)

如果您的代码中存在一些性能问题,请首先使用Instruments的Time Profiler。您可以通过Xcode菜单Build-&gt; Profile启动它,然后打开Instruments app,您可以在其中选择Time Profiler。

开始录制并在您的应用中进行所有互动。

停止录制并分析代码“最紧密”的位置。

同时选中“反转调用树”,“隐藏缺失符号”和“隐藏系统库”选项,以便更好地查看配置文件结果。

您还可以双击任何列出的功能,在代码中查看它并查看使用百分比