矢量化,代碼示例 - 在你的timeit
或測試效果zmq.Stopwatch()
Reported to have 22.14 seconds >> 0.1624 seconds speedup!
當你的代碼似乎環路剛剛超過RGBA [X,Y],讓我告訴了「矢量化「 - 代碼的語法,受益於numpy
矩陣操作實用程序(忘記RGB/YUV操作(最初基於OpenCV而不是PIL),但重新使用矢量化語法方法以避免for-loop並使其適應您的微積分的高效工作。錯誤的操作順序可能會使處理時間增加一倍以上。
並使用測試/優化/重新測試循環加速。
如需測試,請使用標準python timeit
如果[msec]
分辨率就足夠了。
如果您需要進入[usec]
分辨率,請轉到zmq.StopWatch()
。
# Vectorised-code example, to see the syntax & principles
# do not mind another order of RGB->BRG layers
# it has been OpenCV traditional convention
# it has no other meaning in this demo of VECTORISED code
def get_YUV_U_Cb_Rec709_BRG_frame(brgFRAME): # For the Rec. 709 primaries used in gamma-corrected sRGB, fast, VECTORISED MUL/ADD CODE
out = numpy.zeros( brgFRAME.shape[0:2])
out -= 0.09991/255 * brgFRAME[:,:,1] # // Red
out -= 0.33601/255 * brgFRAME[:,:,2] # // Green
out += 0.436 /255 * brgFRAME[:,:,0] # // Blue
return out
# normalise to <0.0 - 1.0> before vectorised MUL/ADD, saves [usec] ...
# on 480x640 [px] faster goes about 2.2 [msec] instead of 5.4 [msec]
在你的情況下,使用dtype = numpy.int
,猜測它應該更快MUL
首先ambient[:,:,0]
最後DIV
正常化arr[:,:,:3] /= 255
# test if this goes even faster once saving the vectorised overhead on matrix DIV
arr[:,:,0] = color[:,:,0] * ambient[:,:,0]/255 # MUL remains INT, shall precede DIV
arr[:,:,1] = color[:,:,1] * ambient[:,:,0]/255 #
arr[:,:,2] = color[:,:,2] * ambient[:,:,0]/255 #
arr[:,:,3] = shine[:,:,0] # STO alpha
它那麼如何可以看看你的算法中?
一個不需要有彼得·傑克遜的令人印象深刻的預算和計劃的時間一次,跨區卷和執行的巨大的數字運算能力超過3年在新西蘭的機庫,由SGI工作站一羣人滿爲患,因爲他生產「指環王「全數字母版製作流水線,通過逐幀像素操作,意識到大規模生產管線中的毫秒級,微秒級甚至納秒級無關緊要。
因此,深呼吸並測試並重新測試,以便將您的實際圖像處理性能優化到您的項目所需的水平。
希望這可以幫助你在此:
# OPTIONAL for performance testing -------------# ||||||||||||||||||||||||||||||||
from zmq import Stopwatch # _MICROSECOND_ timer
# # timer-resolution step ~ 21 nsec
# # Yes, NANOSECOND-s
# OPTIONAL for performance testing -------------# ||||||||||||||||||||||||||||||||
arr = np.zeros((height, width, 4), dtype = int)
aStopWatch = zmq.Stopwatch() # ||||||||||||||||||||||||||||||||
# /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\# <<< your original code segment
# aStopWatch.start() # |||||||||||||__.start
# for i in range( width ):
# for j in range(height):
# ambient_mod = ambient[i,j][0]/255.0
# arr[j, i, :] = [ color[i,j][0] * ambient_mod, \
# color[i,j][1] * ambient_mod, \
# color[i,j][2] * ambient_mod, \
# shine[i,j][0] \
# ]
# usec_for = aStopWatch.stop() # |||||||||||||__.stop
# print 'Converting Color Map to image'
# print ' FOR processing took ', usec_for, ' [usec]'
# /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\# <<< proposed alternative
aStopWatch.start() # |||||||||||||__.start
# reduced numpy broadcasting one dimension less # ref. comments below
arr[:,:, 0] = color[:,:,0] * ambient[:,:,0] # MUL ambient[0] * [{R}]
arr[:,:, 1] = color[:,:,1] * ambient[:,:,0] # MUL ambient[0] * [{G}]
arr[:,:, 2] = color[:,:,2] * ambient[:,:,0] # MUL ambient[0] * [{B}]
arr[:,:,:3] /= 255 # DIV 255 to normalise
arr[:,:, 3] = shine[:,:,0] # STO shine[ 0] in [3]
usec_Vector = aStopWatch.stop() # |||||||||||||__.stop
print 'Converting Color Map to image'
print ' Vectorised processing took ', usec_Vector, ' [usec]'
return Image.fromarray(arr.astype(np.uint8))
你熟悉'numpy'工作得更快,當您試圖在整個陣列上一次(或至少整個矢量在一次操作思路),而不是循環個別元素?這個問題似乎是這個問題的一個典型例子。 – Marius 2014-09-30 01:40:48
我忘了在頂部顯示我的導入聲明。這是正確的用法。有更多我應該使用Numpy的? – David 2014-09-30 04:44:38
你應該試着對整個'color'和'shine'數組執行你的乘法,除法等操作,而不是對它們的單個元素進行操作,並且同樣用類似'ambient_mod_arr = ambient [:,創建一個'ambient_mod'數組來創建' ,0]/255.0'。這種方法很難讓你的頭腦開始,也很難讓我在單一的答案中解釋,但這對於高效地使用numpy非常重要。 – Marius 2014-09-30 06:47:21