我正在嘗試使用 NumPy 模擬下雨,他們說影像超過一千字,所以這里有一個超過兩千字的描述:


我已經寫了代碼,但是我覺得我的實作效率低下,所以我想知道 NumPy 是否有任何可以加快行程的內置函式:
import numpy as np
from PIL import Image
from random import random, randbytes
def rain(width, strikes=360, color=True, lw=3):
assert not width % 16
height = int(width * 9 / 16)
img = np.zeros((height, width, 3), dtype=np.uint8)
half = height / 2
for i in range(strikes):
x = round(random() * width)
y = round(height - random() * half)
x1 = min(x lw, width - 1)
if color:
rgb = list(randbytes(3))
else:
rgb = (178, 255, 255)
img[0:y, x:x1] = rgb
return img
img1 = Image.fromarray(rain(1920))
img1.show()
img1.save('D:/rain.jpg', format='jpeg', quality=80, optimize=True)
img2 = Image.fromarray(rain(1920, color=False))
img2.show()
img2.save('D:/rain_1.jpg', format='jpeg', quality=80, optimize=True)
uj5u.com熱心網友回復:
我能夠提高 2 到 4 倍的速度。
由于雨滴不會停在影像的上半部分,因此可以在所有罷工結束后從下半部分伸出上半部分。
由于廣播元組相對較慢,請改用 32 位格式顏色。
def rain(width=1920, strikes=360, color=True, lw=3):
assert not width % 16
height = int(width * 9 / 16)
img = np.zeros((height, width), dtype=np.uint32)
half = height / 2
upper_bottom = int(half) - 1
alpha = 255 << 24
# Paint background.
# The upper half will always be overwritten and can be skipped.
img[upper_bottom:] = alpha
for i in range(strikes):
x = round(random() * width)
y = round(height - random() * half)
x1 = min(x lw, width - 1)
if color:
# Pack color into int. See below for details.
rgb = int.from_bytes(randbytes(3), 'big') alpha
else:
# This is how to pack color into int.
r, b, g = 178, 255, 255
rgb = r (g << 8) (b << 16) alpha
# Only the lower half needs to be painted in this loop.
img[upper_bottom:y, x:x1] = rgb
# The upper half can simply be stretched from the lower half.
img[:upper_bottom] = img[upper_bottom]
# Unpack uint32 to uint8 x4 without deep copying.
img = img.view(np.uint8).reshape((height, width, 4))
return img
筆記:
- 位元組順序被忽略。可能無法在某些平臺上運行。
- 如果影像寬度非常大,性能會大大降低。
- 如果您要轉換
img為PIL.Image,請比較它的性能,因為它也得到了改進。
由于雨水相互重疊(這使得移除 for-loop 變得很困難),并且由于罷工次數不多(這使得改進的空間很小),我發現很難進一步優化。希望這已經足夠了。
uj5u.com熱心網友回復:
因此,使用 NumPy 加速代碼的最簡單方法是利用廣播和逐元素操作,這樣可以避免效率較低的 for 回圈。下面是我的寫法:
def rain(width, strikes=360, color=True, lw=3):
assert not width % 16
height = width * 9 // 16
inds = np.indices(height)
img = np.zeros((height, width, 3), dtype=np.uint8)
half = height/2
# randint from NumPy lets you
# define a lower and upper bound,
# and number of points.
y = randint(half, height, size=width)
mask = inds[:,None] <= y[None,:]
if color:
rgb = randint(0, 255, size=(width, 3))
else:
rgb = (178, 255, 255)
img[mask[:,:,None]] = rgb
return img
注意:我在手機上寫了所有這些,所以我沒有機會測驗它。請隨意這樣做并修復我的代碼,或對錯誤發表評論。希望這可以幫助。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/479469.html
上一篇:熊貓置換范圍內的值以創建垃圾箱
