在圖像處理中每秒鐘都要做大量的運算,所以你的程序不僅要能給出正確的結果,同時還必須要快。所以這節將要學習:
? 檢測程序的效率
? 一些能夠提高程序效率的技巧
?
1.使用 OpenCV 檢測程序效率
cv2.getTickCount() 函數
返回從參考點到這個函數被執行的時鐘數。所以當你在一個函數執行前后都調用它的話,你就會得到這個函數的執行時鐘數。
cv2.getTickFrequency()
返回時鐘頻率,或者說每秒鐘的時鐘數。
另外:也可以導入time模塊,使用 time.time()函數 計算函數運行時間。示例代碼如下:
import cv2
import time
img = cv2.imread(r'D:\OpenCV_Python\chepai.jpg')
# t1 = time.time()
e1 = cv2.getTickCount()
# 使用窗口大小分別為3,5,7,9的核函數對圖像進行中值濾波
for k in range(3, 11, 2):
img1 = cv2.medianBlur(img, k)
e2 = cv2.getTickCount()
# t2 = time.time()
time1 = (e2-e1) / cv2.getTickFrequency()
# time2 = t2-t1
print(time1)
# print(time2)
?
2.OpenCV 中的默認優化
OpenCV 中的很多函數都被優化過(使用 SSE2, AVX 等)。也包含一些沒有被優化的代碼。如果我們的系統支持優化的話要盡量利用這一點。在編譯時優化是被默認開啟的。因此 OpenCV 運行的就是優化后的代碼,如果你把優化關閉的話就只能執行低效的代碼了。你可以使用
函數 cv2.useOptimized( )
來查看優化是否被開啟了,使用
函數 cv2.setUseOptimized( )
來開啟優化。讓我們來看一個簡單的例子吧。
?
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 優化的。所以你可以在代碼的開始處開啟優化(你要記住優化是默認開啟的)。
?
3.在 IPython 中檢測程序效率
有時你需要比較兩個相似操作的效率,這時你可以使用 IPython 為你提供的魔法命令
%timeit
。他會讓代碼運行好幾次從而得到一個準確的(運行)時間。它也可以被用來測試單行代碼的。
例如,你知道下面這同一個數學運算用哪種行式的代碼會執行的更快嗎?
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 對視圖(而非復制)進行操作時。
?
4.更多 IPython 的魔法命令
還有幾個魔法命令可以用來檢測程序的效率, profiling, line profiling,內存使用等。他們都有完善的文檔。所以這里只提供了超鏈接:
1. Python Optimization Techniques
2. Scipy Lecture Notes - Advanced Numpy
3. Timing and Profiling in IPython
?
5.效率優化技術
有些技術和編程方法可以讓我們最大的發揮 Python 和 Numpy 的威力。我們這里僅僅提一下相關的,你可以通過超鏈接查找更多詳細信息。我們要說的最重要的一點是:首先用簡單的方式實現你的算法(結果正確最重要),當結果正確后,再使用上面的提到的方法找到程序的瓶頸來優化它。
1. 盡量避免使用循環,尤其雙層三層循環,它們天生就是非常慢的。
2. 算法中盡量使用向量操作,因為 Numpy 和 OpenCV 都對向量操作進行了優化。
3. 利用高速緩存一致性。
4. 沒有必要的話就不要復制數組。使用視圖來代替復制。數組復制是非常浪費資源的。
就算進行了上述優化,如果你的程序還是很慢,或者說大的循環不可避免的話,你你應該嘗試使用其他的包,比如說 Cython,來加速你的程序。
?
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
