首页 > 解决方案 > Numpy 3D数组最大值和最小值

问题描述

我有 Numpy 3d 数组,它只是一个灰色图像列表:

images = np.zeros((xlen, height, width), dtype=int)
for i in range (5):
   images[i] = cv2.imread(filename[i], cv2.IMREAD_GRAYSCALE)

所有图像都非常相似,但它们都有一些随机噪声像素。我的想法是,与其他图像中的相同像素相比,噪声像素是最大值或最小值。

所以我需要:

  1. 查找每个像素的最小值和最大值
  2. 计算没有最大值和最小值的所有图像之间每个像素的平均值
  3. 用计算的平均值替换所有最小值和最大值

我使用标准的python函数以一种天真的方式实现了这一点,但这太慢了:

   #remove highest and lowest values for each pixel
   for el in range (height):
      for em in range (width):
         mylist = []
         for j in range (0, xlen):
            mylist.append(images[j][el][em])
         indmin = mylist.index(min(mylist))
         indmax = mylist.index(max(mylist))
         temp_counterx=0
         temp_sum = 0
         for j in range (0, xlen):
            if (j!=indmin) and (j!=indmax):
               temp_counterx +=1
               temp_sum += mylist[j]
         temp_val = int(temp_sum/temp_counterx)
         images[indmin][el][em]=temp_val
         images[indmax][el][em]=temp_val

是否可以使用 Numpy 加快速度?

UPD:缺陷者提出的已接受的解决方案,并进行了一些小改动:

   mins = np.min(images, axis=0)
   maxs = np.max(images, axis=0)
   sums = np.sum(images, axis=0)
   # compute the mean without the extremes
   mean_without_extremes = (sums - mins - maxs) / (xlen - 2)
   mean_without_extremes = mean_without_extremes.astype(int)

   # replace maxima with the mean
   images = np.where((mins==images), images, mean_without_extremes)
   images = np.where((maxs==images), images, mean_without_extremes)

...并获得了 30 倍的速度提升!似乎 numpy 提供了非常快速和强大的计算引擎,但由于它处理的数据结构复杂,有时使用起来可能会很棘手。

标签: pythonnumpynoisenoise-reduction

解决方案


首先,要计算诸如平均值之类的东西,您可能希望使用浮点数而不是整数来开始宽度。所以在下面我假设你使用它们。

通过使用 python-loops,你放弃了 numpy 的所有优点,因为它们本质上很慢,至少与调用 numpy 函数时执行的底层编译代码相比。如果您希望您的代码相当快,您应该使用矢量化。考虑以下代码可以满足您的要求,但在 python 中没有任何循环:

# compute minima, maxima and sum
mins = np.min(images, axis=0)
maxs = np.max(images, axis=0)
sums = np.sum(images, axis=0)
# compute the mean without the extremes
mean_without_extremes = (sums - mins - maxs) / (xlen - 2)
# replace maxima with the mean
images[images == mins] = mean_without_extremes.reshape(-1)
images[images == maxs] = mean_without_extremes.reshape(-1)

由于您可能对此不熟悉,我建议您阅读文档中有关索引和广播的介绍,以便有效地使用 numpy:


编辑:正如评论中所指出的,上述解决方案仅适用于xlen > 2每个像素位置仅获得一次极值的情况。这可以通过将这些行替换为

images = np.where(images == mins, images, mean_without_extremes)
images[np.isnan(images)] = 0  # set "empty mean" to zero
# using "np.where" as suggested by OP
# we can actually reduce that to one "np.where" call which might be slightly faster
images = np.where(np.logical_or(images == mins, images == maxs), images, mean_without_extremes)

推荐阅读