最详细的Python OpenCV速度提升全汇总!

Python OpenCV速度提升全汇总

前言

周更周更,希望能做到有质量的周更。最近好忙啊,在弄图像算法专利Kaggle的比赛,还有工作上的事情。闲话打住,说说自己吃饭的家伙,OpenCV和python。这篇主要汇总OpenCV python项目中对速度的提升的方法。个人经验,如有问题欢迎评论或者私聊

整体思路

要缩短代码运行的时间,那么我们首先要知道改哪里。我们需要分析代码运行时间。找出在哪里修改,而修改整体思路分为两步,减少路程增加速度减少路程就是减少代码里不必要的操作,用简单的方法实现你的算法,每个项目的代码都不一样,这个只能靠自己。另一个是增加速度,增加代码运行速度,这个方法比较共通。我会在下面一一列出,希望没有遗漏,从而解决您的问题。

具体步骤

分析代码运行时间(必要)

分析代码运行时间,这样你才能找出在哪里修改你的代码。
1.最简单的

import time
t1=time.time()
test_work=[x**2 for x in range(1,1000000,3)]
t2=time.time()
print(t2-t1)
#0.11789417266845703

2.jupyter环境(IPython)
IPython的功能比较强大
它的“魔法”命令(‘magic’ commands)可以轻松实现分析代码运行时间这个功能
先贴一个三个链接
IPython官方文档内置魔术命令的介绍
IPython(jupyter环境)中的”魔法“命令 %time,%timeit,%%time,%%timeit
IPython中的时序和性能分析
强烈建议大家进去看看,第一个和第三个。只想了解%time和%timeit的可以看第二个。

简要的说一下。
时间分析里的
%time:查看脚本运行需要多长时间
%timeit:查看脚本平均运行多个运行所花费的时间
%prun:查看脚本中每个函数运行了多长时间
%lprun:查看函数中每行花费了多长时间

内存分析里的:
%mprun:查看脚本逐行使用多少内存
%memit:查看脚本总体使用多少内存

python加速

这个就有的说了,一搜各种方法都出来了。这里对我启发比较大的是这篇文章。24式加速你的Python(小结)
这里先总结,并说下自己的感受供各位参考,其中的部分内容之后可以再写(shui)一篇博客了。

关于查找的建议

1.用set而非list进行查找
(准确的说是查找在set中的速度更快,list中的查找会随着list本身的增大而变慢,数据量大时,更改后效果显著)
2.用dict而非两个list进行匹配查找(数据量大时,更改后效果显著)

关于循环的建议

1.优先使用for循环而不是while循环(只快一点
2.在循环体中避免重复计算(减少不必要的操作

关于函数的建议

1.用循环机制代替递归函数(更改后效果显著)
2.用缓存机制加速递归函数(更改后效果显著)
3.用numba加速Python函数(万金油的加速效果显著)
numba是一个用于编译Python数组和数值计算函数的编译器,这个编译器能够大幅提高直接使用Python编写的函数的运算速度。
numba使用LLVM编译器架构将纯Python代码生成优化过的机器码,通过一些添加简单的注解,将面向数组和使用大量数学的python代码优化到与c,c++和Fortran类似的性能,而无需改变Python的解释器。
直接贴官方文档
Numba documentation
最关键的是使用简单,不过如果函数只打算用一两次,那还是没必要去用的。

关于使用标准库函数进行加速的建议

1.使用collections.Counter加速计数(数据量大时,更改后效果优秀)
2.使用collections.ChainMap加速字典合并(数据量大时,更改后效果显著)

关于使用高阶函数进行加速的建议

1.使用map代替推导式进行加速(数据量大时,更改后效果显著)
2.使用filter代替推导式进行加速(数据量大时,更改后效果显著)

关于使用numpy向量化进行加速的建议

1.使用np.array代替list(数据量大时,更改后效果显著)

2.使用np.ufunc代替math.func(数据量大时,更改后效果显著)

3.使用np.where代替if(数据量大时,更改后效果显著)

关于加速Pandas的建议

1.使用csv文件读写代替excel文件读写(数据量大时,更改后效果显著)
2.使用pandas多进程工具pandarallel(多进程工具)

关于使用dask加速的建议

Dask是一款用于分析计算的灵活并行计算库。
Dask由两部分组成:
针对计算优化的动态任务调度。这与Airflow,Luigi,Celery或Make类似,但针对交互式计算工作负载进行了优化。
“大数据”集合, 像并行数组,数据框和列表一样,它们将通用接口(如NumPy,Pandas或Python迭代器)扩展到大于内存或分布式环境。 这些并行集合运行在动态任务调度器之上。
贴两个链接
Dask教程
Dask官方文档
1.使用dask加速dataframe
2.使用dask.delayed进行加速

关于应用多线程多进程加速

1.应用多线程加速IO密集型任务
2.应用多进程加速CPU密集型任务

OpenCV加速

OpenCV文档的建议

这里的建议直接引用一下官方的文档,下面是翻译。
出自这里OpenCV的性能测量和改进技术

这里要注意的主要事情是,首先尝试以一种简单的方式实现该算法。工作正常后,对其进行概要分析,找到瓶颈并对其进行优化。
1.尽量避免在Python中使用循环,尤其是双/三重循环等。它们本来就很慢。
2.由于Numpy和OpenCV已针对向量运算进行了优化,因此将算法/代码向量化到最大程度。
3.利用缓存一致性。
4.除非需要,否则切勿制作数组的副本。尝试改用视图。阵列复制是一项昂贵的操作。
即使完成所有这些操作后,如果您的代码仍然很慢,或者不可避免地需要使用大循环,请使用Cython等其他库来使其更快。

Numpy文档的建议

而在Numpy中在它的文档的2.4.4建议也类似。
出自这里Numpy优化代码
1.向量化循环
查找避免使用numpy数组进行for循环的技巧。为此,掩码和索引数组可能很有用。
2.广播(Broadcasting)
在合并数组之前,请使用广播(Broadcasting)对数组进行尽可能小的操作。
3.就地操作(In place operations)
In place operations
a *= 0比a = 0 * a 快
4.易于存储(Be easy on the memory):使用视图(views),而不是副本(copies)。
5.当心缓存效果:进行分组时,内存访问成本更低:连续访问大型阵列比随机访问要快得多。除其他外,这意味着较小的步幅更快。
6.使用编译后的代码
一旦确定所有高级优化都已被采用,最后的选择就是将热点(hot spots:花费大部分时间的几行代码或函数)转移到已编译的代码中。对于已编译的代码,首选的选择是使用 Cython:在已编译的代码中转换现有的Python代码很容易,并且很好地利用 numpy支持会 在numpy数组上产生有效的代码,例如通过展开循环。

最后提一下的是OpenCV里默认的优化。
许多OpenCV功能已使用SSE2,AVX等进行了优化。它还包含未优化的代码。因此,如果我们的系统支持这些功能,则应该利用它们(几乎所有现代处理器都支持它们)。默认在编译时启用。因此,如果已启用,OpenCV将运行优化的代码,否则将运行未优化的代码。您可以使用cv2.useOptimized()来检查是否启用/禁用它,并使用cv2.setUseOptimized()来启用/禁用它。

cv2.useOptimized()
#Out[33]: True
#默认是开启的
cv2.setUseOptimized(False)
cv2.useOptimized()
#Out[35]: False
#使用cv2.setUseOptimized(False)就可以禁用优化了

还有OpenCV里的很多函数,个人推荐使用前看下文档,参数的选择也是挺关键的优化步骤。

结束语

写完了,这篇总结自己也学习了很多,尽量做到详细。Python的速度确实是它的劣势,不过人生苦短,我选它。如果有不清楚的地方,欢迎留言或者私聊哦,笔者看到后一定会回复的。如果这篇文章对你有帮助,麻烦点个赞。谢谢!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章