OpenCV 性能测量与提升
【目标】
- 代码耗时测试
- 一些提升代码性能的技巧
- cv2.getTickCount, cv2.getTickFrequency等等
【代码】
import cv2
"""
读入图片并执行中值滤波N次,测试耗时
"""
# 读入图片
img1 = cv2.imread('messi5.jpg')
# 在需要测试函数或者代码片段的前后加上 cv2.getTickCount()
e1 = cv2.getTickCount()
for i in range(5,49,2):
img1 = cv2.medianBlur(img1,i)
e2 = cv2.getTickCount()
t = (e2 - e1)/cv2.getTickFrequency()
print( t )
0.336590686 s
cv2.getTickCount()
返回的是时钟周期数,在函数前后调用它可以 通过(e2 - e1)
获得消耗的时钟周期数。
cv2.getTickFrequency()
时钟周期的频率(或者说每秒时钟周期数),所以最后的单位是秒
。 如果转换成毫秒
,就乘以1000
。
调用 Python 的 time 模块
import cv2
import time
"""
读入图片并执行中值滤波N次,测试耗时
"""
# 读入图片
img1 = cv2.imread('messi5.jpg')
# 在需要测试函数或者代码片段的前后加上 cv2.getTickCount()
# e1 = cv2.getTickCount()
e1 = time.time()
for i in range(5,49,2):
img1 = cv2.medianBlur(img1,i)
# e2 = cv2.getTickCount()
e2 = time.time()
# t = (e2 - e1)/cv2.getTickFrequency()
# print( t )
print(e2 - e1)
0.33676838874816895 s
不同的地方是 time 的精度更高
【接口】
// 返回时钟刻度
int64 cv::getTickCount();
// 返回时钟频率(每秒)
double cv::getTickFrequency ();
# // 返回时钟刻度
cv2.getTickCount() -> retval
# // 返回时钟频率(每秒)
cv2.getTickFrequency() -> retval
【扩展】
可以用 cv2.useOptimized()
检查是否开启了优化,如果为 False, 则通过 cv2.setUseOptimized(True)
设置,默认是开启的。
%timeit
可以测试单行代码的效率
x = 5
%timeit y=x**2
# 213 ns ± 4.16 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)
%timeit y=x^2
# 48.6 ns ± 1.45 ns per loop (mean ± std. dev. of 7 runs, 10,000,000 loops each)
%timeit y=x*x
# 40.1 ns ± 1.59 ns per loop (mean ± std. dev. of 7 runs, 10,000,000 loops each)
NOTE: Python的标量运算比 NumPy 要快,NumPy 适合对那些大型的数组的运算,优势更明显。
OpenCV的速度比NumPy要快,一般情况下,首选OpenCV的函数。
// 输出CMake output 的编译信息
const String& cv::getBuildInformation ();
// 返回编译期间启用的CPU功能列表
std::string cv::getCPUFeaturesLine();
// 返回 CPU 时钟刻度数
int64 cv::getCPUTickCount();
// 根据CPU功能序号返回名称
String cv::getHardwareFeatureName(int feature)
// 返回CPU核心数
int cv::getNumberOfCPUs();
// 返回CPU线程数
int cv::getNumThreads();
// 在并行时,返回线程索引
int cv::getThreadNum();
// 返回 主版本号
int cv::getVersionMajor ();
// 返回 次版本号
int cv::getVersionMinor ();
// 返回 修正号
int cv::getVersionRevision();
// 返回版本号字符串
String cv::getVersionString ();
# // 输出CMake output 的编译信息
cv2.getBuildInformation() -> retval
# // 返回编译期间启用的CPU功能列表
cv2.getCPUFeaturesLine() -> retval
# SSE SSE2 SSE3 *SSE4.1 *SSE4.2 *FP16 *AVX *AVX2 *AVX512-SKX?
# // 返回 CPU 时钟刻度数
cv2.getCPUTickCount() -> retval
# 11422541228929925
# // 根据CPU功能序号返回名称
cv2.getHardwareFeatureName( feature ) -> retval
# // 返回CPU核心数
cv2.getNumberOfCPUs() -> retval
# 12
# // 返回CPU线程数
cv2.getNumThreads() -> retval
# 12
# // 在并行时,返回线程索引
cv2.getThreadNum() -> retval
# -1564290240
# // 返回 主版本号
cv2.getVersionMajor() -> retval
# 4
# // 返回 次版本号
cv2.getVersionMinor() -> retval
# 6
# // 返回 修正号
cv2.getVersionRevision() -> retval
# 0
# // 返回版本号字符串
cv2.getVersionString() -> retval
# 4.6.0
关于优化
- 避免在
Python
中使用循环,尤其是多重循环,非常耗时;- 尽量将算法和代码向量化,因为
NumPy
和OpenCV
对向量运算进行了大量的优化;- 利用缓存一致性;
- 不要将
array
拷贝除非有必要,尽量使用views
,array
的拷贝非常耗时;
如果代码还是比较耗时,那么可以利用Cython
使其更快。
Python代码优化
Timing and Profiling in IPython