我有一个巨大的图像数据集,无法容纳在内存中。我想计算meanstandard deviation,从磁盘加载图像。

我目前正在尝试使用wikipedia上的此算法。

# for a new value newValue, compute the new count, new mean, the new M2.
# mean accumulates the mean of the entire dataset
# M2 aggregates the squared distance from the mean
# count aggregates the amount of samples seen so far
def update(existingAggregate, newValue):
    (count, mean, M2) = existingAggregate
    count = count + 1
    delta = newValue - mean
    mean = mean + delta / count
    delta2 = newValue - mean
    M2 = M2 + delta * delta2

    return existingAggregate

# retrieve the mean and variance from an aggregate
def finalize(existingAggregate):
    (count, mean, M2) = existingAggregate
    (mean, variance) = (mean, M2/(count - 1))
    if count < 2:
        return float('nan')
    else:
        return (mean, variance)

这是我当前的实现(仅针对红色通道进行计算):
count = 0
mean = 0
delta = 0
delta2 = 0
M2 = 0
for i, file in enumerate(tqdm(first)):
    image = cv2.imread(file)
    for i in range(224):
        for j in range(224):
            r, g, b = image[i, j, :]
            newValue = r
            count = count + 1
            delta = newValue - mean
            mean = mean + delta / count
            delta2 = newValue - mean
            M2 = M2 + delta * delta2

print('first mean', mean)
print('first std', np.sqrt(M2 / (count - 1)))

此实现在我尝试的数据集的子集上足够接近。

问题是它非常慢,因此不可行。
  • 是否有执行此操作的标准方法?
  • 如何适应此方法以获得更快的结果,或者为所有数据集计算RGB平均值和标准偏差,而又不以合理的速度将它们全部同时加载到内存中?
  • 最佳答案

    由于这是一项繁重的任务(围绕矩阵或张量进行大量迭代),因此我始终建议使用擅长此功能的库:numpy。

    正确安装的numpy应该能够利用底层的BLAS(基本线性代数子例程)例程,这些例程从内存层次结构的 Angular 进行了优化,可用于操作浮点数组。

    imread应该已经为您提供了numpy数组。您可以通过以下方式获得红色通道图像的重塑一维数组:

    import numpy as np
    val = np.reshape(image[:,:,0], -1)
    

    这样的意思是
    np.mean(val)
    

    和标准差
    np.std(val)
    

    这样,您可以摆脱两层python循环:
    count = 0
    mean = 0
    delta = 0
    delta2 = 0
    M2 = 0
    for i, file in enumerate(tqdm(first)):
        image = cv2.imread(file)
            val = np.reshape(image[:,:,0], -1)
            img_mean = np.mean(val)
            img_std = np.std(val)
            ...
    

    其余的增量更新应该很简单。

    完成此操作后,瓶颈将成为镜像加载速度,该速度受磁盘读取操作性能的限制。在这方面,我怀疑使用其他人建议的多线程会有所帮助,这基于我以前的经验。

    关于python - 用Python计算图像数据集 channel 明智均值和标准差的最快方法,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47850280/

    10-13 06:56