OpenCV-Python11:程序性能检测及优化
目录
背景说明
????????在实际图像处理中程式每秒都要做大量的运算,为了体现程序的实用性,程序不仅要能给出正确的结果,同时还必须足够快。这就要求我们在同一硬体保证实现程序功能的前提下,能够对程式进行检测和优化,从而实现程式的最优化。
学习目标及环境
- 学会检测程序的效率
- 掌握能够提高程序效率的技巧
- 学习函数cv2.getTickCount,cv2.getTickFrequency
- Python =3.6.8? ? ? OpenCV-Python=3.4.2.16
Python程序性能检测方法及说明介绍
????????在Python中,可以使用一些工具和技术来检测和优化程序的性能。以下是几种常用的方法及其简要介绍:
- 时间测量
????????使用Python的time模块可以测量程序的执行时间。可以使用time.time()函数来获取当前时间戳,从而计算代码块的执行时间。
- cProfile模块
????????cProfile是Python的内置模块,可以用于分析程序的性能。它可以提供函数级别的统计信息,包括每个函数的执行时间和调用次数。
- line_profiler模块????????
????????line_profiler是一个第三方模块,可以用于分析代码的行级别性能。它可以显示每行代码的执行时间和调用次数,帮助找到代码中的瓶颈。
- memory_profiler模块
????????memory_profiler是一个第三方模块,可以用于分析程序的内存使用情况。它可以显示每个函数的内存占用量,帮助找到内存泄漏或过度分配的问题。
- 性能分析工具
????????除了Python内置的模块,还有一些第三方工具可以用于性能分析。例如,使用Py-Spy可以直接采样Python进程的堆栈,以获得函数调用的时间分布情况。
- 可视化工具
????????有一些可视化工具可以帮助分析程序的性能。例如,使用SnakeViz可以将cProfile和line_profiler的输出结果可视化,以便更直观地分析程序的性能。
????????在进行性能优化时,可以使用这些工具来找到程序的瓶颈,并进行相应的优化。然而,需要注意的是,性能优化并不是一种简单的任务,需要综合考虑算法、数据结构、并行化等多个方面的因素。因此,在进行性能优化时,需要综合考虑各种方法和工具,并进行合理的权衡和取舍。
OpenCV 检测程序效率?
cv2.getTickCount() :该函数返回从参考点到这个函数被执的时钟数。所以当你在一个函数执行前后都调用它的话,你就会得到这个函数的执行时间(时钟数)。
cv2.getTickFrequency(): 返回时钟频率或者说每秒钟的时钟数目。所以你可以按照下列的方式得到一个函数运行了多少秒:
# -*- coding: utf-8 -*-
"""
@author: Pegasus
"""
import cv2
import numpy as np
e1 = cv2.getTickCount()
# 在这里调用hello函数测试
print('hello world!')
e2 = cv2.getTickCount()
time = (e2 - e1)/ cv2.getTickFrequency()
print('运行时间为:',time)
注意:也可以用time 模块实现以上功能,但是调用函数是time.time() 而不是cv2.getTickCount()
OpenCV 中的默认优化?
OpenCV 中的很多函数都被优化过(使用SSE2,AVX 等)。也包含一些没有优化的代码。如果我们的系统支持优化的尽量利用这一点。在编译时优化是默认开启的。因此OpenCV 运行的就是优化后的代码,如果你把优化关闭的话就只能执行低效的代码了。你可以使用函数cv2.useOptimized()
来查看优化是否开启了,使用函数cv2.setUseOptimized() 来开启优化。我们来看一个简单的例子吧。
# -*- coding: utf-8 -*-
"""
Created on Thu Jan 9 21:08:41 2014
@author: duan
"""
import cv2
import numpy as np
# check if optimization is enabled
In [5]: cv2.useOptimized()
Out[5]: True
In [6]: %timeit res = cv2.medianBlur(img,49)
10 loops, best of 3: 34.9 ms per loop
# Disable it
In [7]: cv2.setUseOptimized(False)
In [8]: cv2.useOptimized()
Out[8]: False
In [9]: %timeit res = cv2.medianBlur(img,49)
10 loops, best of 3: 64.1 ms per loop
结果显示,优化后中值滤波的速度是原来的两倍。如果你查看源代码的话你会发现中值滤波是被SIMD 优化的。所以你可以在代码的开始处开启优化(你要记住优化是默认开启的)。
在IPython 中检测程序效率
????????有时你需要比较两个相似操作的效率,这时你可以使用IPython 为你提供的魔法命令%time。他会让代码运行好几次从而得到一个准确的运行时间,它也可以用来测试单行代码的。例如:你想知以下同一个数学运算用哪种方式的代码会执行的更快。
x = 5; y = x ? ?2
x = 5; y = x ? x
x = np.uint([5]); y = x ? x
y = np.squre(x)
我们可以在IPython 的Shell 中使用魔法命令找到答案。
import cv2
import numpy as np
In [10]: x = 5
In [11]: %timeit y=x**2
10000000 loops, best of 3: 73 ns per loop
In [12]: %timeit y=x*x
10000000 loops, best of 3: 58.3 ns per loop
In [15]: z = np.uint8([5])
In [17]: %timeit y=z*z
1000000 loops, best of 3: 1.25 us per loop
In [19]: %timeit y=np.square(z)
1000000 loops, best of 3: 1.16 us per loop
竟然是第一种写法,它居然比Nump 快了20 倍。如果考虑到数组构建的话能提高到100 倍的差。
注意:Python 的标量运算比Nump 的标量运算快。对于仅包含一两个元素的操作,Python 标量比Numpy 的数组快。但是当数组稍微大一点时Numpy 就会胜出了。?
我们来比较一下cv2.countNonZero() 和np.count_nonzero()。
import cv2
import numpy as np
In [35]: %timeit z = cv2.countNonZero(img)
100000 loops, best of 3: 15.8 us per loop
In [36]: %timeit z = np.count_nonzero(img)
1000 loops, best of 3: 370 us per loop
看见了吧,OpenCV 的函数是Numpy 函数的25 倍。注意:一般情况下OpenCV 的函数比Numpy 函数快。所以对于相同的操作最好使用OpenCV 的函数。当然也有例外,尤其是当使用Numpy 对视图
(而非复制)操作时。?
更多IPython 的魔法命令
还有几个魔法命令可以用来检测程序的效率,如profiling,line profiling,内存使用等。他们都有完善的文档。所以只提供了链接。感兴的可以自己学习一下。
效率优化技术
????????有些技术和编程方法可以帮助我们最大的发挥Python 和Numpy 的威力。在这里我们仅仅提一下相关的,你可以通过链接查找更多详细信息。
Python优化技术:?https://wiki.python.org/moin/PythonSpeed/PerformanceTips
Scipy和Numpy:http://scipy-lectures.org/advanced/advanced_numpy/index.html#advanced-numpy
我要说的最重要的一点是,要先用最简单的方式实现你的算法(因为结果正确最重要),当结果正确后,再使用上面的提到的方法找到程序的瓶颈来优它。面给出一些建议:
- 尽量避免使用循环,尤其双层三层循环,它们天生就是非常慢的。
- 算法中尽量使用向量操作,因为Numpy 和OpenCV 都对向量操作进行了优化。
- 利用高速缓存的一致性。
- ?没有必要的话就不要复制数组,使用视图来代替复制。数组复制是非常浪费源的。
- 如果进行了上诉优化,程序依然很慢或者有些需要无法避免,应该尝试一下使用其它的包比如?Cython来加速你的程序,或者从新设计一下算法流程及思路
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!