【问题标题】:Why python is slower than matlab?为什么python比matlab慢?
【发布时间】:2020-01-14 02:36:46
【问题描述】:

终于成功将MATLAB代码改成Python代码了。

然而,与我所听到的相反,Python 的执行速度非常慢。

现在 MATLAB 在图像处理方面是否更好?

当然,我也只能用 Python,因为公司不买 MATLAB……

ps。在visual studio 环境和IDLE 中运行Python。

如果有加快 Python 速度的方法,请帮助我。

## Exercise Python image processing ##

import numpy as np
import cv2
import matplotlib.pyplot as plt

B = cv2.imread(r'D:\remedi\Exercise\Xray\Offset.png', -1) # offset image

for i in range(2,3):

    org_I = cv2.imread(r'D:\remedi\Exercise\Xray\objects\object (' + str(i) + ').png', -1) # original image

    w = cv2.imread(r'D:\remedi\Exercise\Xray\white\white (' + str(i) + ').png', -1) # white image

    # dead & bad pixel correction
    corrected_w = w.copy()
    corrected_org_I = org_I.copy()

    c = np.mean(corrected_w)
    p = np.abs(corrected_w - c)

    sens = 0.7
    [num_y, num_x] = np.where((p < c*sens) | (p > c*sens))

    ar = np.zeros((3,3))
    ar2 = np.zeros((3,3))
    for n in range(0, num_y.shape[0]):
        for j in range(-1,2):
            for k in range(-1,2):
                if num_y[n]+j+1 == 0 or num_x[n]+k+1 == 0 or num_y[n]+j+1 == 577 or num_x[n]+k+1 == 577:
                    ar[j+1][k+1] = 0
                    ar2[j+1][k+1] = 0
                else:
                    ar[j+1][k+1] = corrected_w[num_y[n]+j-1][num_x[n]+k-1]
                    ar2[j+1][k+1] = corrected_org_I[num_y[n]+j-1][num_x[n]+k-1]
        ar[1][1] = 0
        ar2[1][1] = 0
        corrected_w[num_y[n]][num_x[n]] = np.sum(ar)/np.count_nonzero(ar)
        corrected_org_I[num_y[n]][num_x[n]] = np.sum(ar2)/np.count_nonzero(ar2)

c = np.mean(corrected_w) # constant

FFC = np.uint16(np.divide(c*(corrected_org_I-B), (corrected_w-B))) # flat field correction

plt.subplot(2,3,1), plt.imshow(org_I, cmap='gray'), plt.title('Original Image')
plt.subplot(2,3,2), plt.imshow(corrected_org_I, cmap='gray'), plt.title('corrected original Image')
plt.subplot(2,3,3), plt.imshow(FFC, cmap='gray'), plt.title('FFC')
plt.subplot(2,3,4), plt.imshow(w, cmap='gray'), plt.title('w')
plt.subplot(2,3,5), plt.imshow(corrected_w, cmap='gray'), plt.title('corrected w')
plt.subplot(2,3,6), plt.imshow(B, cmap='gray'), plt.title('B')
plt.show()

【问题讨论】:

  • 抱歉,您从哪里听说 Python 很快?
  • 有很多方法可以加速 Python,但它不会像编译语言那样快。也就是说,您可以使用 C API 和一些第三方库来加速特定任务。此外,良好的代码结构(生成器、类等)也会有所帮助。
  • 我对 MATLAB 的经验很少,但 Python 绝不是快!您是否尝试过分析您的代码?我觉得 Python for 循环会很慢。
  • cv2 是 C++ 代码的前端,所以可能不是问题。三重嵌套循环可能会减慢您的速度。 numpy 就像旧的 MATLAB;使用整个数组操作时速度很快;在 Python 代码中迭代时很慢。较新的 MATLAB 让您可以懒惰并进行迭代,因为它进行了大量的 JIT 编译。如果你想走那条路,你必须添加numba。你会看到很多关于vectorizing 或“消除循环”的问题;这就是我们在 MATLAB 中使用的方式。
  • for n in range(0, num_y.shape[0]): 不是使用numpy.ndarray 对象的正确方法,这将非常慢,甚至比使用常规 Python 列表对象要慢得多。要有效地使用numpy.ndarray 对象,您必须使用矢量化操作。或者,存在 numba,它是 numpy 代码的 JIT,它将加速这种确切类型的代码非常非常

标签: python matlab numpy


【解决方案1】:

cv2 调用 c++ 库代码,每个调用都有一些开销。这些可以加起来取决于你在做什么。此外,opencv 还利用了一些处理器优化,例如 SIMD 和 NEON。

这是一个具体的例子,我通过遍历像素实现了自己的阈值函数。然后我使用opencv的内置阈值函数。我打印每个函数的时间并比较最终结果以验证它们是否相同。

img = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE)
thresh = 128
thresh_loops = img.copy()

# implement threshold with loops
t1 = cv2.getTickCount()
for c in range(img.shape[0]):
    for r in range(img.shape[1]):
        if thresh_loops[c,r] > thresh:
            thresh_loops[c,r] = 255
        else:
            thresh_loops[c,r] = 0
t2 = cv2.getTickCount()
print((t2-t1)/cv2.getTickFrequency())

# use the threshold function
t1 = cv2.getTickCount()
thr, thresh_fun = cv2.threshold(img, thresh, 255, cv2.THRESH_BINARY)
t2 = cv2.getTickCount()
print((t2-t1)/cv2.getTickFrequency())

print(np.all(thresh_loops == thresh_fun)) # verify the same result

我在 720p 图像(720x1280 - 或大约 100 万像素)上运行,在我的机器上,第一个函数也是 2.319724256 秒,第二个函数需要 0.013217389 秒。所以第二个函数大约快 200 倍!如果您使用 Java 或其他调用 OpenCV 库(或任何其他 C 库)的语言,您将遇到这个问题。

将其作为学习 api 的良好动力。

我还要补充一点,如果您在 Python 中使用 OpenCV 进行图像处理,您还应该学习 Numpy api,因为矩阵 (Mat) 类表示为 numpy 数组。通过了解numpy api,您也可以获得巨大的加速。

【讨论】:

    【解决方案2】:

    一年前,我从我心爱的 Matlab 转到了 python。是的,你是对的,Matlab 比 python 快,通常至少快 3 倍或更多。

    我找到了两种保存 python 的方法

    1. 尝试阅读 Numpy Functional programming Routines 并用那里的方法替换一些 for 循环。它们比在 for 循环中切片 ndarray 快得多。

    2. 尝试多处理。我知道 Matlab parfor 也比 python 中的任何并行计算包更好。尝试“joblib”或“多处理”。他们可能会有所帮助。

    【讨论】:

      猜你喜欢
      • 2012-09-16
      • 2020-11-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-27
      • 1970-01-01
      • 2020-08-01
      相关资源
      最近更新 更多