【python-opencv】性能衡量和提升技术

摘要:
IPython为你提供了一个神奇的命令计时器来执行此操作。我们将在IPythonshell中使用timeit得到答案。注意Python标量操作比Numpy标量操作快。这次,我们将比较cv.countNonZero和np.count_nonzero对于同一张图片的性能。因此,对于相同的操作,首选OpenCV功能。尽量避免在Python中使用循环,尤其是双/三重循环等。

在图像处理中,由于每秒要处理大量操作,因此必须使代码不仅提供正确的解决方案,而且还必须以最快的方式提供。因此,在本章中,你将学习

  • 衡量代码的性能。
  • 一些提高代码性能的技巧。
  • 你将看到以下功能:cv.getTickCountcv.getTickFrequency等。

除了OpenCV,Python还提供了一个模块time,这有助于衡量执行时间。另一个模块profile有助于获取有关代码的详细报告,例如代码中每个函数花费了多少时间,调用了函数的次数等。但是,如果你使用的是IPython,则所有这些功能都集成在用户友好的界面中方式。我们将看到一些重要的信息,有关更多详细信息,请查看“其他资源”部分中的链接。

1、使用opencv衡量性能

cv.getTickCount函数返回从参考事件(如打开机器的那一刻)到调用此函数那一刻之间的时钟周期数。因此,如果在函数执行之前和之后调用它,则会获得用于执行函数的时钟周期数。

cv.getTickFrequency函数返回时钟周期的频率或每秒的时钟周期数。因此,要找到执行时间(以秒为单位),你可以执行以下操作:

e1 =cv.getTickCount()
#你的执行代码
e2 =cv.getTickCount()
time = (e2 - e1)/ cv.getTickFrequency()

我们将通过以下示例进行演示。下面的示例应用中位数过滤,其内核的奇数范围为5到49。(不必担心结果会是什么样,这不是我们的目标):

img1 = cv.imread('messi5.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 )
#我得到的结果是0.521107655秒

注意你可以使用时间模块执行相同的操作。代替cv.getTickCount,使用time.time()函数。然后取两次相差。

2、opencv的默认优化

许多 OpenCV 函数都是使用 SSE2、 AVX 等进行优化的。 它还包含未优化的代码。因此,如果我们的系统支持这些特性,我们就应该利用它们(几乎所有现代的处理器都支持它们)。在编译时默认启用它。因此,如果启用了 OpenCV,它将运行优化的代码,否则它将运行未优化的代码。你可以使用cvUseoptimized检查是否启用 / 禁用和cvSetuseoptimized以启用 / 禁用它。让我们看一个简单的例子。

#检查是否启用了优化

#检查是否启用了优化
In [5]: cv.useOptimized()
Out[5]: True
In [6]: %timeit res = cv.medianBlur(img,49)
10 loops, best of 3: 34.9ms per loop
#关闭它
In [7]: cv.setUseOptimized(False)
In [8]: cv.useOptimized()
Out[8]: False
In [9]: %timeit res = cv.medianBlur(img,49)
10 loops, best of 3: 64.1 ms per loop

看,优化的中值滤波比未优化的版本快2倍。如果你检查其来源,你可以看到中值滤波是 SIMD 优化。因此,你可以使用它在代码顶部启用优化(请记住,它是默认启用的)

3、Ipython中衡量性能

有时你可能需要比较两个类似操作的性能。IPython为你提供了一个神奇的命令计时器来执行此操作。它会多次运行代码以获得更准确的结果。同样,它们适用于测量单行代码。

例如,你知道以下哪个加法运算更好,x = 5; y = x**2, x = 5; y = x*x, x = np.uint8([5]); y = x*xy = np.square(x)?我们将在IPython shell中使用timeit得到答案。

In [10]: x = 5
In [11]: %测时 y=x**2
10000000 loops, best of 3: 73ns per loop

In [12]: %测时 y=x*x
10000000 loops, best of 3: 58.3ns per loop

In [15]: z = np.uint8([5])

In [17]: %测时 y=z*z
1000000 loops, best of 3: 1.25us per loop

In [19]: %测时 y=np.square(z)
1000000 loops, best of 3: 1.16 us per loop

你可以看到x = 5; y = x * x最快,比Numpy快20倍左右。如果你还考虑阵列的创建,它可能会快100倍。酷吧?(大量开发人员正在研究此问题)

注意 Python标量操作比Numpy标量操作快。因此,对于包含一两个元素的运算,Python标量比Numpy数组好。当数组大小稍大时,Numpy会占优势。

我们将再尝试一个示例。这次,我们将比较cv.countNonZeronp.count_nonzero对于同一张图片的性能。

In [35]: %测时 z =cv.countNonZero(img) 
100000 loops, best of 3: 15.8us per loop
In [36]: %测时 z =np.count_nonzero(img) 
1000 loops, best of 3: 370 us per loop

看,OpenCV 函数比 Numpy 函数快近25倍。

注意通常,OpenCV函数比Numpy函数要快。因此,对于相同的操作,首选OpenCV功能。但是,可能会有例外,尤其是当Numpy处理视图而不是副本时。

4、性能优化技术

有几种技术和编码方法可以充分利用 Python 和 Numpy 的最大性能。这里只注明相关信息,并提供重要信息来源的链接。这里要注意的主要事情是,首先尝试以一种简单的方式实现算法。一旦它运行起来,分析它,找到瓶颈并优化它们。

  1. 尽量避免在Python中使用循环,尤其是双/三重循环等。它们本来就很慢。
  2. 由于Numpy和OpenCV已针对向量运算进行了优化,因此将算法/代码向量化到最大程度。
  3. 利用缓存一致性。
  4. 除非需要,否则切勿创建数组的副本。尝试改用视图。数组复制是一项昂贵的操作。

即使执行了所有这些操作后,如果你的代码仍然很慢,或者不可避免地需要使用大循环,请使用Cython等其他库来使其更快。

其他资源:

  1. Python优化技术:http://wiki.python.org/moin/PythonSpeed/PerformanceTips
  2. Scipy讲义- 高级Numpy:http://scipy-lectures.github.io/advanced/advanced_numpy/index.html#advanced-numpy
  3. IPython中的时序和性能分析:http://pynash.org/2013/03/06/timing-and-profiling/

摘自:http://woshicver.com/FourthSection/3_3_%E6%80%A7%E8%83%BD%E8%A1%A1%E9%87%8F%E5%92%8C%E6%8F%90%E5%8D%87%E6%8A%80%E6%9C%AF/

免责声明:文章转载自《【python-opencv】性能衡量和提升技术》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇redis学习(一)002.使用kubeadm安装kubernetes 1.17.0下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

python pandas 对带时间序列的数据进行重采样处理

今天老板要处理一批带有时间序列的数据,源数据为1秒钟一行的csv数据,处理之后变成15分钟一行的数据。 源数据示例如下: time B00 B01 ... RollMean2.5RollMean10 2018-05-31 09:44:39 15.212 5.071 .....

python基础(十三、综合应用

14.综合应用 - 名片管理系统 1)框架搭建 搭建名片管理系统框架结构 准备文件,确定文件名,保证能够在需要的位置编写代码 编写主运行循环,实现基本的用户输入和判断 (1)文件准备 ①新建cards_main.py,保存主程序功能代码 程序的入口 每一次启动名片管理系统都通过 main 这个文件启动 ②新建cards_tools.py,保存所有名片功能函...

五. python 字符串方法函数

一 .字符串方法函数 什么是字符串就是以 单引号或者双引号引起来的任意文本'ancask的库时时刻刻'"ABC事实就是惊声尖叫 1. 创建字符串: str1="abcde骨灰盒fgaa" str2="abcde吾问无为谓fgaa" str3="abcdefg少时诵诗书所所aa" 2.字符串运算连接 str6="SKSDK就是死你KsbDSKDKSKK" s...

python字典

概念 一种通过名字引用值的数据结构为映射,而字典是python中唯一内建的映射类型。字典由多个键与其对应的值构成,键/值也成为项。每个键值之间用冒号隔开,项之间用逗号隔开,整个字典是由一对大括号括起来。空字典不包括任何项。键可以是数字、字符串和元组,并且唯一,但值不唯一。 某些情况,字典比列表更加适用: 表示游戏棋盘的状态,每个键都是由坐标值组成的元...

python模块学习心得

初始模块 1.什么是模块 模块是用来实现某项功能的一大堆代码,为什么会有模块呢?过程式编程的时候为了减少程序员编程代码的重复性,就利用函数的调用减少了代码的重复性,但是某些时候程序会过于的庞大,我们会用到很多很多 的函数,同样是为了方便,我们就把某些函数在一起共同产生的一些功能放在同一个py文件里面,这个py文件就称为一个模块,或者多个py文件在一个文件夹...

python第一行注释是什么意思?

  很大多时候在开始学习python的时候,知道,#是注释的意思,但是每次写python的第一句都是提示 #!/usr/ ...不知是什么意思? 表示该文件是个.py程序,执行的时候需要python环境来执行。 这是脚本语言共同遵守的规则:当第一行为 #!/path/to/script/interpreter时,指定了用来执行本脚本的解释器。注意:1、必须...