cjm*_*671 5 python numpy scipy python-2.7
我有一个在 Mac 上编写的程序,但由于 RAM 不足(MemoryError)无法在我的 Raspberry Pi 上运行。
该程序的本质是一些图像处理,它将 640x480 uint8 与两倍大小的 complex128 进行卷积。
我认为内存使用情况是:初始图像:
640 x 480 x 8 bits / 8 bits / 1024 bytes = 300 kb
Run Code Online (Sandbox Code Playgroud)
复矩阵:
640 x 480 x 2^2 x 128 bits / 8 bits / 1024^2 = 18.75 MB
Run Code Online (Sandbox Code Playgroud)
假设它必须在内存中保存这些不同矩阵的两到三个副本——这应该是一个相当小的占用空间——也许 < 100 MB。不幸的是,它似乎耗尽了全部 330MB 可用空间(Python 运行时也必须加载到这个空间中)。
更新:
正如下面所建议的,我已经做了一些内存分析,它确实是 fftconvolve 使 RAM 使用量激增,如下所示:
65 86.121 MiB 0.000 MiB @profile
66 def iriscode(self):
67 86.121 MiB 0.000 MiB img = self.polar
68
69 86.379 MiB 0.258 MiB pupil_curve = find_max(img[0:40])
70 86.379 MiB 0.000 MiB blur = cv2.GaussianBlur(self.polar, (9, 9), 0)
71 76.137 MiB -10.242 MiB iris_fft = fit_iris_fft(radial_diff(blur[50:,:])) + 50
72
73 76.160 MiB 0.023 MiB img = warp(img, iris_fft, pupil_curve)
74 # cv2.imshow("mask",np.uint8(ma.getmaskarray(img))*255)
75
76 global GABOR_FILTER
77 262.898 MiB 186.738 MiB output = signal.fftconvolve(GABOR_FILTER, img, mode="valid")
Run Code Online (Sandbox Code Playgroud)
尽管如此,这种增长的幅度还是让我感到惊讶。任何想法我可以做些什么来减少它?我尝试使用complex64而不是,complex128但内存使用情况是一样的。
要了解发生了什么,您可以查看fftconvolve 此处的源代码。
傅里叶变换卷积背后的整个思想是,时域中的卷积只是频域中的元素乘法。但因为您使用的是 FFT,它会将您的函数视为周期性函数,即,就好像卷积核缠绕在边缘上。因此,为了获得正确的结果,数组用零填充到一个常见的形状,在您的情况下,该形状将是(1280+640-1, 960+480-1) = (1919, 1439). 为了加快计算速度,这个形状会进一步扩展到下一个更大的数字,该数字只有 2、3 或 5 作为质因数,在您的情况下会产生一个(1920, 1440)形状。对于复杂的数组,需要占用1920 * 1440 * 16 / 2**20 = 42 MiB.
您将有 2 个这样的数组,每个输入一个,再加上两个(当您计算它们各自的 FFT 时),加上另一个(当您将它们相乘时),再加上另一个(当您计算它们的逆 FFT 以获得卷积时)。
目前尚不清楚所有这些数组是否会同时共存,因为有些数组可能会一路上被垃圾收集,但在某个时刻至少会有 3 个,可能是 4 个。加上 FFT 计算的一些开销,你就得到了你186 MiB解释了。
您可能想尝试非 FFT 卷积,它不需要所有的填充。您还可以尝试稍微优化scipy.signal.fftconvolve. 将此else块替换为:
else:
ret = fftn(in1, fshape)
ret *= fftn(in2, fshape)
ret = ifftn(ret)[fslice].copy()
Run Code Online (Sandbox Code Playgroud)
应该去掉其中一个中间副本,并给你 40 个额外的 MiB,这可能对你的情况有用。
| 归档时间: |
|
| 查看次数: |
1599 次 |
| 最近记录: |