我需要一种在Python中快速循环图像/堆栈像素的方法

我需要一种在Python中快速循环图像/堆栈像素的方法,python,image,loops,numpy,pixels,Python,Image,Loops,Numpy,Pixels,我已经创建了一个3D中值滤波器,它确实有效,如下所示: def Median_Filter_3D(image,kernel): window = np.zeros(shape=(kernel,kernel,kernel), dtype = np.uint8) n = (kernel-1)/2 #Deals with Image border imgout = np.empty_like(image) w,h,l = image.shape() %%在每个像素上开始循环 for y in

我已经创建了一个3D中值滤波器,它确实有效,如下所示:

def Median_Filter_3D(image,kernel):

window = np.zeros(shape=(kernel,kernel,kernel), dtype = np.uint8)
n = (kernel-1)/2    #Deals with Image border
imgout = np.empty_like(image)
w,h,l = image.shape()
%%在每个像素上开始循环

for y in np.arange(0,(w-n*2),1):
    for x in np.arange(0,(h-n*2),1):
        for z in np.arange(0,(l-n*2),1):
            window[:,:,:] = image[x:x+kernel,y:y+kernel,z:z+kernel]
            med = np.median(window)
            imgout[x+n,y+n,z+n] = med 
return(imgout)
因此,在每个像素上,它创建一个大小为kernelxkernelxkernel的窗口,找到窗口中像素的中值,并用新的中值替换该像素的值

我的问题是,它非常慢,我有成千上万的大图像要处理。必须有一种更快的方法来迭代所有这些像素,并且仍然能够得到相同的结果


提前谢谢

首先,在python中循环3D矩阵是一个非常糟糕的主意。为了循环一个大的3D矩阵,最好使用或C/C++/Fortran并创建一个python扩展。但是,对于这种特殊情况,scipy已经包含了用于n维数组的实现:

>>> from scipy.ndimage import median_filter
>>> median_filter(my_large_3d_array, radious)
简而言之,在python中没有一种更快的迭代体素的方法(可能会有所帮助,但不会显著提高性能)。如果你需要在Python中执行更复杂的3D素材,你应该考虑Cython中的LoopIn接口编程,或者,使用一个块库,例如,它实现了数组块的并行操作。
Python的问题是,如果
for
循环的
速度非常慢,特别是如果它们是嵌套的并且具有大数组。因此,没有一种标准的pythonic方法来获得数组上的有效迭代。通常,获得加速的方法是通过矢量化操作和numpy记号,但是这些都是非常特定于问题的,没有通用的技巧,在SO中您将学到很多numpy技巧

作为一种通用方法,如果您真的需要迭代数组,那么您可以在中编写代码。Cython是Python的一个类似C的扩展。您可以用Python语法编写代码,但要指定变量类型(如在C中,使用
int
float
。然后,该代码会自动编译为C,并可以从Python中调用。一个简单的示例:

Python循环函数示例: 我知道上面的代码有点多余,可以写成
B=A*2
,但其目的只是为了说明python循环非常慢

Cython版本的函数: 两种实现的测试速度: 注意:您不能按原样运行Cython函数。您需要将其放在单独的文件中并首先编译(或在IPython笔记本中使用
%%Cython
magic)


它显示原始python版本花了
400ms
迭代整个数组,而Cython版本(
x200
加速)只花了2ms

好的,谢谢。我对python有点陌生,所以还不知道Cython或Dask是什么,但我会研究它(Y)。我知道scipy已经有了过滤器,但这只是一个练习函数,以后会产生更复杂的过滤器。@ScottAlistair我刚刚编辑了答案,以提供更多关于Cython的信息,以及为什么在python中迭代大型数组是一个坏主意。我知道如果您是python新手,需要特别消化很多内容,但我只是想指出一点好的方向。谢谢,这非常有用!@ScottAlistair很高兴它能帮上忙!注意:
Py\u ssize\u t
与C中的
size\u t
相当(类似),如果你熟悉它(如果不是,则是一个大整数:P)。为了能够使用cython代码,你需要使用它。cython代码通常存储在
.pyx
文件中。
import numpy as np

def iter_A(A):
    B = np.empty(A.shape, dtype=np.float64)

    for i in range(A.shape[0]):
        for j in range(A.shape[1]):
            B[i, j] = A[i, j] * 2
    return B
import numpy as np
cimport numpy as np

def iter_A_cy(double[:, ::1] A):
    cdef Py_ssize_t H = A.shape[0], W = A.shape[1]
    cdef double[:, ::1] B = np.empty((H, W), dtype=np.float64)
    cdef Py_ssize_t i, j

    for i in range(H):
        for j in range(W):
            B[i, j] = A[i, j] * 2

    return np.asarray(B)
>>> import numpy as np
>>> A = np.random.randn(1000, 1000)
>>> %timeit iter_A(A)
1 loop, best of 3: 399 ms per loop
>>> %timeit iter_A_cy(A)
100 loops, best of 3: 2.11 ms per loop