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