目标
在图像处理中,由于您每秒都要进行大量的运算,所以您的代码不仅要提供正确的结果,同时还必须要快。所以在本章中,你将学习
- 衡量你代码的性能。
- 提高代码性能的一些技巧。
- 你会看到这些函数:cv.getTickCount,cv.getTickFrequency等。
除了OpenCV,Python还提供了一个有助于测量执行时间的模块time。另一个模块profile有助于获得有关代码的详细报告,例如代码中每个函数占用了多少时间,函数被调用了多少次等等。但是,如果您使用的是IPython,则所有这些功能都集成在一个用户友好方式。我们会看到一些重要的内容,有关更多详细信息,请查看其他资源部分中的链接。
用OpenCV测量性能
cv.getTickCount函数返回从参考点到调用此函数时,被执行的时钟数。所以如果你在一个函数执行前后调用它,你会得到用于执行这个函数的时钟周期数。
cv.getTickFrequency函数返回时钟周期的频率或每秒钟的时钟周期数。因此,您可以按照下面的方式得到一个函数运行了多少秒:
程序:import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
e1 = cv.getTickCount()
# your code execution
e2 = cv.getTickCount()
time = (e2 - e1)/ cv.getTickFrequency()
print(time)
我们将用下面的例子来演示。以下示例应用中值滤波,奇数大小的内核范围为5至49.(不要担心结果如何,这不是我们的目标):
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
img1 = cv.imread('lena.jpg')
e1 = cv.getTickCount()
for i in range(5,49,2):
img1 = cv.medianBlur(img1,i)
e2 = cv.getTickCount()
t = (e2 - e1)/cv.getTickFrequency()
print( t )
注意你可以用time模块实现上述功能。使用time.time()函数而不是cv.getTickCount。可以比较下两者的区别。
OpenCV中的默认优化
OpenCV很多函数都使用SSE2,AVX等了进行优化。当然它也包含了一些未优化的代码。所以如果我们的系统支持这些优化的话,我们应该利用它们(几乎所有的现代处理器都支持它们)。编译时优化是默认启用的。因此,OpenCV运行的就是优化后的代码,否则它会运行未优化的代码。您可以使用cv.useOptimized()检查优化是否启用,并使用cv.setUseOptimized()启用/禁用它。我们来看一个简单的例子。
程序:
cv.setUseOptimized(False)
print(cv.useOptimized())
带有%等是Ipython专有的命令。
测量IPython中的性能
有时您可能需要比较两个类似操作的效率。IPython为您提供了一个魔法命令timeit来执行此操作。它会让代码运行好几次以获得更准确的结果。它也适用于测量单行代码。
例如,你知道下列哪种加法操作更好:
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; 与Numpy相比,y = x * x是最快的,速度约快20倍。如果您考虑创建数组,它可能会快达100倍。很酷,对吧?*(Numpy开发者正在处理这个问题)*
- 注意
- Python标量操作比Numpy标量操作更快。因此对于包含一个或两个元素的操作,Python标量比Numpy数组要好。当数组的大小稍大一点时,Numpy就会占上风。
我们将再尝试一个例子。这一次,我们将比较同一图像的cv.countNonZero()和np.count_nonzero()的性能。计算非零数组的元素。
程序:
看,OpenCV功能比Numpy功能快25倍。
- 注意
- 通常,OpenCV功能比Numpy功能更快。因此,对于相同的操作,OpenCV功能是首选。But, there can be exceptions, especially when Numpy works with views instead of copies.
更多IPython魔术命令
还有其他几个魔术命令来检测程序的效率,profiling,line profiling,内存使用等。它们都有详细记录。所以这里只提供那些文档的链接。建议有兴趣的读者试用一下。
性能优化技术
有几种技术和编码方法可以发挥Python和Numpy的最高性能。这里只注明相关的内容,并将链接提供给重要来源。这里要注意的主要问题是:首先尝试以简单的方式实现算法。当他正常工作后,再使用上面提高的方法找到程序的瓶颈,并优化它们。
- 尽可能避免在Python中使用循环,特别是二/三循环等。它们本质上很慢。
- 因为Numpy和OpenCV针对向量操作进行了优化,所以可以尽可能地向最大程度地矢量化算法/代码。
- 利用缓存一致性。
- 除非需要,否则不要复制阵列的副本。尝试使用视图(Views)代替,阵列复制是一项代价高昂的操作。
即使在完成所有这些操作之后,如果代码仍然很慢,或者使用大循环是不可避免的,请使用Cython等其他库来加快速度。
其他资源
- Python Optimization Techniques
- Scipy Lecture Notes - Advanced Numpy
- Timing and Profiling in IPython