开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 9 天,点击查看活动详情
目标
在图像处理中,由于每秒要处理大量操作,因此必须使代码不仅提供正确的解决方案,而且还必须以最快的方式提供。因此,在本章中,将学习
- 衡量代码的性能
- 一些提高代码性能的技巧
- 将看到以下函数:
cv2.getTickCount,cv2.getTickFrequency除了OpenCV,Python还提供了一个模块time,这有助于衡量执行时间。另一个模块profile有助于获取有关代码的详细报告,例如代码中每个函数花费了多少时间,调用了函数的次数等。 但是,如果使用的是IPython,则所有这些功能都集成在用户友好的界面中方式。将看到一些重要的信息,有关更多详细信息,请查看“ **其他资源”**部分中的链接
使用OpenCV衡量性能
cv2.getTickCount函数返回从参考事件(如打开机器的那一刻)到调用此函数那一刻之间的时钟周期数。因此,如果在函数执行之前和之后调用它,则会获得用于执行函数的时钟周期数。
cv2.getTickFrequency函数返回时钟周期的频率或每秒的时钟周期数。因此,要找到执行时间(以秒为单位),可以执行以下操作:
e1 = cv2.getTickCount()
img = cv2.imread('messi.png')
e2 = cv2.getTickCount()
time = (e2-e1)/cv2.getTickFrequency() # convert into second
print(time)
# 0.00460510975383286
注意 也可以使用时间模块time执行相同的操作。代替
cv2.getTickCount,使用time.time()函数。然后取两次相差
OpenCV中的默认优化
许多 OpenCV 函数都是使用 SSE2、 AVX 等进行优化的。 它还包含未优化的代码。因此,如果系统支持这些特性,就应该利用它们(几乎所有现代的处理器都支持它们)。在编译时默认启用它。因此,如果启用了 OpenCV,它将运行优化的代码,否则它将运行未优化的代码。你可以使用 cv2.Useoptimized 检查是否启用 / 禁用和cv2.Setuseoptimized以启用 / 禁用它。让我们看
一个简单的例子。
cv2.useOptimized()
%timeit res = cv2.medianBlur(img, 49)
cv2.setUseOptimized(False)
cv2.useOptimized()
%timeit res = cv2.medianBlur(img, 49)
cv2.setUseOptimized(True)
可以看到,优化的中值滤波比未优化的版本快2倍。如果检查其来源,可以看到中值滤波是 SIMD 优化。因此,可以使用它在代码顶部启用优化(请记住,它是默认启用的)
在IPython中衡量性能
有时可能需要比较两个类似操作的性能。IPython为你提供了一个神奇的命令计时器来执行此操作。它会多次运行代码以获得更准确的结果。同样,它们适用于测量单行代码。例如,你知道以下哪个加法运算更好, x = 5; y = x**2, x = 5; y = x*x, x = np.uint8([5]); y = x*x 或 y = np.square(x) 将在IPython shell中使用timeit得到答案。
x = 5
%timeit y = x**2
%timeit y = x*x
z = np.uint8([5])
%timeit y = z*z
%timeit y = np.square(z)
可以看到x = 5; y = x * x最快,比Numpy快8倍左右。如果你还考虑阵列的创建,它可能会快100倍。酷吧?(大量开发人员正在研究此问题)
注意 Python标量操作比Numpy标量操作快。因此,对于包含一两个元素的运算,Python标量比Numpy数组好。当数组大小稍大时,Numpy会占优势
再尝试一个示例。这次,将比较cv2.countNonZero和np.count_nonzero对于同一张图片的性能
其中 cv2.countNonZero只能针对灰度图
img = cv2.imread('messi.png', 0)
%timeit z = cv2.countNonZero(img)
%timeit z = np.count_nonzero(img)
可以看到,OpenCV 函数比 Numpy 函数快近25倍。
注意 通常,OpenCV函数比Numpy函数要快。因此,对于相同的操作,首选OpenCV。但可能会有例外,尤其是当Numpy处理视图而不是副本时。
更多IPython魔术命令
还有其他一些魔术命令可以用来测量性能,性能分析,行性能分析,内存测量等。它们都有很好的文档记录。因此,此处仅提供指向这些文档的链接。建议有兴趣的读者尝试一下。 性能优化技术 有几种技术和编码方法可以充分利用 Python 和 Numpy 的最大性能。这里只注明相关信息,并提供重要信息来源的链接。这里要注意的主要事情是,首先尝试以一种简单的方式实现算法。一旦它运行起来,分析它,找到瓶颈并优化它们。
-
尽量避免在Python中使用循环,尤其是双/三重循环等。它们本来就很慢
-
由于Numpy和OpenCV已针对向量运算进行了优化,因此将算法/代码向量化到最大程度
-
利用缓存一致性
-
除非需要,否则切勿创建数组的副本。尝试改用视图。数组复制是一项昂贵的操作。 即使执行了所有这些操作后,如果代码仍然很慢,或者不可避免地需要使用大循环,请使用Cython等其他库来使其更快。