如何更快地制作此代码?

时间:2016-08-23 20:09:55

标签: python scipy

我有很多750x750的图片。我想从每个图像中获取非重叠5x5色块的几何平均值,然后对于每个图像,平均这些几何平均值以为每个图像创建一个特征。我写了下面的代码,它似乎工作得很好。但是,我知道它效率不高。在300张左右的图像上运行它需要大约60秒。我有大约3000张图片。因此,虽然它适用于我的目的,但效率不高。如何改进此代码?

1.0e^p, p < 0

1 个答案:

答案 0 :(得分:2)

我可以理解将此移至代码审查网站的建议, 但这个问题提供了使用矢量化的力量的一个很好的例子 numpy和scipy函数,所以我会给出答案。

下面的函数,巧妙地称为func,计算所需的值。 关键是将图像重塑为四维阵列。然后 它可以解释为二维的二维数组 数组,其中内部数组是5x5块。

scipy.stats.gmean可以计算多个几何平均值 维度,因此用于将四维数组减少到 所需的二维几何平均数组。返回值是 (算术)这些几何平均值的意思。

import numpy as np
from scipy.stats import gmean


def func(img, blocksize=5):
    # img must be a 2-d array whose dimensions are divisible by blocksize.
    if (img.shape[0] % blocksize) != 0 or (img.shape[1] % blocksize) != 0: 
        raise ValueError("blocksize does not divide the shape of img.")

    # Reshape 'img' into a 4-d array 'blocks', so blocks[i, :, j, :] is
    # the subarray with shape (blocksize, blocksize).
    blocks_nrows = img.shape[0] // blocksize
    blocks_ncols = img.shape[1] // blocksize
    blocks = img.reshape(blocks_nrows, blocksize, blocks_ncols, blocksize)

    # Compute the geometric mean over axes 1 and 3 of 'blocks'.  This results
    # in the array of geometric means with size (blocks_nrows, blocks_ncols).
    gmeans = gmean(blocks, axis=(1, 3), dtype=np.float64)

    # The return value is the average of 'gmeans'.
    avg = gmeans.mean()

    return avg

例如,此处函数应用于具有形状(750,750)的数组。

In [358]: np.random.seed(123)

In [359]: img = np.random.randint(1, 256, size=(750, 750)).astype(np.uint8)

In [360]: func(img)
Out[360]: 97.035648309350179

要验证这是正确的结果并不容易,所以这里有一个小得多的例子:

In [365]: np.random.seed(123)

In [366]: img = np.random.randint(1, 4, size=(3, 6))

In [367]: img
Out[367]: 
array([[3, 2, 3, 3, 1, 3],
       [3, 2, 3, 2, 3, 2],
       [1, 2, 3, 2, 1, 3]])

In [368]: func(img, blocksize=3)
Out[368]: 2.1863131342986666

这是直接计算:

In [369]: 0.5*(gmean(img[:,:3], axis=None) + gmean(img[:, 3:], axis=None))
Out[369]: 2.1863131342986666