Numpy 3D 数组最大值和最小值
Numpy 3D array max and min value
我有 Numpy 3d 数组,它只是一个灰色图像列表:
images = np.zeros((xlen, height, width), dtype=int)
for i in range (5):
images[i] = cv2.imread(filename[i], cv2.IMREAD_GRAYSCALE)
所有图像都非常相似,但它们都有一些随机噪声像素。
我的想法是,与其他图像中的相同像素相比,噪声像素是最大值或最小值。
所以我需要:
- 找出每个像素的最小值和最大值
- 计算没有最大值和最小值的所有图像之间每个像素的平均值
- 用计算出的平均值替换所有最小值和最大值
我使用标准 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 加快速度?
更新:
接受了 flawr 提出的一些小改动的解决方案:
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 提供了非常快速和强大的计算引擎,只是由于它处理的数据结构复杂,有时使用起来可能很棘手。
确保您使用的所有内容都是 numpy array
而 不是 Python list
并确保所有成员都具有相同的数据类型。在你的情况下这是真的。
现在您可以使用名为 numba
的库。它使用 JIT。
可以看到演示它的视频here。
可以查看 numba
的文档 here
首先,要计算诸如 mean 之类的东西,您可能希望使用浮点数而不是整数来开始宽度。因此,在下文中,我假设您改用它们。
通过使用 python 循环,您放弃了 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:
- https://numpy.org/doc/stable/user/basics.indexing.html#basics-indexing
- https://numpy.org/doc/stable/user/theory.broadcasting.html#array-broadcasting-in-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)
我有 Numpy 3d 数组,它只是一个灰色图像列表:
images = np.zeros((xlen, height, width), dtype=int)
for i in range (5):
images[i] = cv2.imread(filename[i], cv2.IMREAD_GRAYSCALE)
所有图像都非常相似,但它们都有一些随机噪声像素。 我的想法是,与其他图像中的相同像素相比,噪声像素是最大值或最小值。
所以我需要:
- 找出每个像素的最小值和最大值
- 计算没有最大值和最小值的所有图像之间每个像素的平均值
- 用计算出的平均值替换所有最小值和最大值
我使用标准 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 加快速度?
更新: 接受了 flawr 提出的一些小改动的解决方案:
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 提供了非常快速和强大的计算引擎,只是由于它处理的数据结构复杂,有时使用起来可能很棘手。
确保您使用的所有内容都是 numpy array
而 不是 Python list
并确保所有成员都具有相同的数据类型。在你的情况下这是真的。
现在您可以使用名为 numba
的库。它使用 JIT。
可以看到演示它的视频here。
可以查看 numba
的文档 here
首先,要计算诸如 mean 之类的东西,您可能希望使用浮点数而不是整数来开始宽度。因此,在下文中,我假设您改用它们。
通过使用 python 循环,您放弃了 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:
- https://numpy.org/doc/stable/user/basics.indexing.html#basics-indexing
- https://numpy.org/doc/stable/user/theory.broadcasting.html#array-broadcasting-in-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)