在圖像處理中每秒鐘都要做大量的運(yùn)算,所以你的程序不僅要能給出正確的結(jié)果,同時(shí)還必須要快。所以這節(jié)將要學(xué)習(xí):
? 檢測(cè)程序的效率
? 一些能夠提高程序效率的技巧
?
1.使用 OpenCV 檢測(cè)程序效率
cv2.getTickCount() 函數(shù)
返回從參考點(diǎn)到這個(gè)函數(shù)被執(zhí)行的時(shí)鐘數(shù)。所以當(dāng)你在一個(gè)函數(shù)執(zhí)行前后都調(diào)用它的話,你就會(huì)得到這個(gè)函數(shù)的執(zhí)行時(shí)鐘數(shù)。
cv2.getTickFrequency()
返回時(shí)鐘頻率,或者說(shuō)每秒鐘的時(shí)鐘數(shù)。
另外:也可以導(dǎo)入time模塊,使用 time.time()函數(shù) 計(jì)算函數(shù)運(yùn)行時(shí)間。示例代碼如下:
import cv2
import time
img = cv2.imread(r'D:\OpenCV_Python\chepai.jpg')
# t1 = time.time()
e1 = cv2.getTickCount()
# 使用窗口大小分別為3,5,7,9的核函數(shù)對(duì)圖像進(jìn)行中值濾波
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 中的默認(rèn)優(yōu)化
OpenCV 中的很多函數(shù)都被優(yōu)化過(guò)(使用 SSE2, AVX 等)。也包含一些沒(méi)有被優(yōu)化的代碼。如果我們的系統(tǒng)支持優(yōu)化的話要盡量利用這一點(diǎn)。在編譯時(shí)優(yōu)化是被默認(rèn)開(kāi)啟的。因此 OpenCV 運(yùn)行的就是優(yōu)化后的代碼,如果你把優(yōu)化關(guān)閉的話就只能執(zhí)行低效的代碼了。你可以使用
函數(shù) cv2.useOptimized( )
來(lái)查看優(yōu)化是否被開(kāi)啟了,使用
函數(shù) cv2.setUseOptimized( )
來(lái)開(kāi)啟優(yōu)化。讓我們來(lái)看一個(gè)簡(jiǎn)單的例子吧。
?
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
看見(jiàn)了嗎,優(yōu)化后中值濾波的速度是原來(lái)的兩倍。如果你查看源代碼的話,你會(huì)發(fā)現(xiàn)中值濾波是被 SIMD 優(yōu)化的。所以你可以在代碼的開(kāi)始處開(kāi)啟優(yōu)化(你要記住優(yōu)化是默認(rèn)開(kāi)啟的)。
?
3.在 IPython 中檢測(cè)程序效率
有時(shí)你需要比較兩個(gè)相似操作的效率,這時(shí)你可以使用 IPython 為你提供的魔法命令
%timeit
。他會(huì)讓代碼運(yùn)行好幾次從而得到一個(gè)準(zhǔn)確的(運(yùn)行)時(shí)間。它也可以被用來(lái)測(cè)試單行代碼的。
例如,你知道下面這同一個(gè)數(shù)學(xué)運(yùn)算用哪種行式的代碼會(huì)執(zhí)行的更快嗎?
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
竟然是第一種寫(xiě)法,它居然比 Nump 快了 20 倍。如果考慮到數(shù)組構(gòu)建的話,能達(dá)到 100 倍的差。
注意: Python 的標(biāo)量計(jì)算比 Nump 的標(biāo)量計(jì)算要快。對(duì)于僅包含一兩個(gè)元素的操作 Python 標(biāo)量比 Numpy 的數(shù)組要快。但是當(dāng)數(shù)組稍微大一點(diǎn)時(shí)Numpy更有優(yōu)勢(shì)。
再看個(gè)例子,比較一下 cv2.countNonZero() 和 np.count_nonzero()的計(jì)算速度。
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
看見(jiàn)了吧, OpenCV 的函數(shù)是 Numpy 函數(shù)的 25 倍。
注意:
一般情況下 OpenCV 的函數(shù)要比 Numpy 函數(shù)快
。所以對(duì)于相同的操作最好使用 OpenCV 的函數(shù)。當(dāng)然也有例外,尤其是當(dāng)使用 Numpy 對(duì)視圖(而非復(fù)制)進(jìn)行操作時(shí)。
?
4.更多 IPython 的魔法命令
還有幾個(gè)魔法命令可以用來(lái)檢測(cè)程序的效率, profiling, line profiling,內(nèi)存使用等。他們都有完善的文檔。所以這里只提供了超鏈接:
1. Python Optimization Techniques
2. Scipy Lecture Notes - Advanced Numpy
3. Timing and Profiling in IPython
?
5.效率優(yōu)化技術(shù)
有些技術(shù)和編程方法可以讓我們最大的發(fā)揮 Python 和 Numpy 的威力。我們這里僅僅提一下相關(guān)的,你可以通過(guò)超鏈接查找更多詳細(xì)信息。我們要說(shuō)的最重要的一點(diǎn)是:首先用簡(jiǎn)單的方式實(shí)現(xiàn)你的算法(結(jié)果正確最重要),當(dāng)結(jié)果正確后,再使用上面的提到的方法找到程序的瓶頸來(lái)優(yōu)化它。
1. 盡量避免使用循環(huán),尤其雙層三層循環(huán),它們天生就是非常慢的。
2. 算法中盡量使用向量操作,因?yàn)?Numpy 和 OpenCV 都對(duì)向量操作進(jìn)行了優(yōu)化。
3. 利用高速緩存一致性。
4. 沒(méi)有必要的話就不要復(fù)制數(shù)組。使用視圖來(lái)代替復(fù)制。數(shù)組復(fù)制是非常浪費(fèi)資源的。
就算進(jìn)行了上述優(yōu)化,如果你的程序還是很慢,或者說(shuō)大的循環(huán)不可避免的話,你你應(yīng)該嘗試使用其他的包,比如說(shuō) Cython,來(lái)加速你的程序。
?
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061
微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元

