python - 如何在大型数组中更快地生成随机点?
问题描述
我正在尝试在 3d 辣椒状形状内生成随机点,但是当 arr_size 很大时,生成这些点需要很长时间。
arr_size 是 (30,30,30) 在 3d 形状内生成 1000 个随机点需要很短的时间,但是当 arr_size = (265,490,286) 时需要很长时间。
from matplotlib import pyplot as plt
import numpy as np
def create_bin_pepper(arr_size, center):
coords = np.ogrid[:arr_size[0], :arr_size[1], :arr_size[2]]
c = 10
a1 = np.random.randint(low=5,high=10)
b1 = np.random.randint(low=7,high=10)
a2 = np.random.randint(low=5,high=10)
b2 = np.random.randint(low=7,high=10)
a3 = np.random.randint(low=5,high=10)
b3 = np.random.randint(low=7,high=10)
ellipse1 = ((np.square(coords[0] - center[0]))/np.square(a1) + (np.square(coords[1]-center[1]))/np.square(b1) + (np.square(coords[2]-center[2]))/np.square(c) <= 1)
ellipse2 = ((np.square(coords[0] - center[0]-3))/np.square(a2) + (np.square(coords[1]-center[1]-5))/np.square(b2) + (np.square(coords[2]-center[2]))/np.square(c) <= 1)
ellipse3 = ((np.square(coords[0] - center[0]+3))/np.square(a3) + (np.square(coords[1]-center[1]-5))/np.square(b3) + (np.square(coords[2]-center[2]))/np.square(c) <= 1)
pepper = ellipse1|ellipse2|ellipse3
pepper2 = np.where(pepper==1,230,pepper)
for im in range(0,1000):
#r2=1
centre_x1 = np.random.randint(low=center[0]-a1+4,high=center[0]+a1-4)#low=11,high=20
centre_y1 = np.random.randint(low=center[1]-b1+4,high=center[1]+b1-4)#low=15,high=23
centre_z1 = np.random.randint(low=center[2]-c+4,high=center[2]+c-4)#low=10,high=20
centre_x2 = np.random.randint(low=center[0]-a2+4,high=center[0]+a2-4)#low=11,high=20
centre_y2 = np.random.randint(low=center[1]-b2+4,high=center[1]+b2-4)#low=15,high=23
centre_z2 = np.random.randint(low=center[2]-c+4,high=center[2]+c-4)#low=10,high=20
centre_x3 = np.random.randint(low=center[0]-a3+4,high=center[0]+a3-4)#low=11,high=20
centre_y3 = np.random.randint(low=center[1]-b3+4,high=center[1]+b3-4)#low=15,high=23
centre_z3 = np.random.randint(low=center[2]-c+4,high=center[2]+c-4)#low=10,high=20
inside_ellipse1 = ((np.square(coords[0] - centre_x1))/np.square(a1) + (np.square(coords[1]-centre_y1))/np.square(b1) + (np.square(coords[2]-centre_z1))/np.square(c) <= (1/((np.square(a1))*(np.square(b1))*(np.square(c)))))
inside_ellipse2 = ((np.square(coords[0] - centre_x2-3))/np.square(a2) + (np.square(coords[1]-centre_y2-5))/np.square(b2) + (np.square(coords[2]-centre_z2))/np.square(c) <= (1/((np.square(a2))*(np.square(b2))*(np.square(c)))))
inside_ellipse3 = ((np.square(coords[0] - centre_x3+3))/np.square(a3) + (np.square(coords[1]-centre_y3-5))/np.square(b3) + (np.square(coords[2]-centre_z3))/np.square(c) <= (1/((np.square(a3))*(np.square(b3))*(np.square(c)))))
pepper2 = inside_ellipse1 | inside_ellipse2 | inside_ellipse3 | pepper2
pepper3 = np.where((pepper2!=230)&(pepper2!=0),160,pepper2)
return pepper3
arr_size = (265,490,286)
sphere_center1 = (133,216,40)
pepper = create_bin_pepper(arr_size,sphere_center1)
axis = pepper[:,:,40]
plt.imshow(axis,cmap='gray')#,interpolation='bicubic'
plt.show()
解决方案
np.random.rand
您可以通过在与 arr_size 形状相同的数组上使用并用椭圆和条件掩盖它来生成接近 1000 个点< 1000 / (area of ellipses)
:
from matplotlib import pyplot as plt
import numpy as np
POINTS = 1000
def ellipse(coords, center, offset):
a = np.random.randint(low=5, high=10)
b = np.random.randint(low=7, high=10)
c = 10
xs, ys, zs = coords
cx, cy, cz = center
ox, oy, oz = offset
return ((xs - cx - ox) / a)**2 + ((ys - cy - oy) / b)**2 + ((zs - cz - oz) / c)**2 <= 1
def create_bin_pepper(arr_size, center):
x, y, z = arr_size
coords = np.ogrid[:x, :y, :z]
ellipses = [ellipse(coords, center, offset) for offset in ((0, 0, 0), (3, 5, 0), (-3, 5, 0))]
ellipses = np.logical_or.reduce(ellipses)
area = ellipses.sum()
random_points = np.where(ellipses, np.random.rand(*arr_size) < POINTS / area, 0)
return random_points
arr_size = (300, 300, 300)
sphere_center = (150, 150, 150)
pepper = create_bin_pepper(arr_size, sphere_center)
print(pepper.sum())
这应该接近您需要生成的点数
推荐阅读
- json - 反序列化包含 $ref 的 Json
- tensorflow - 如何使用 Tensorflow aocr API 从 SavedModel 生成注意掩码?
- vba - VBA动态获取所有枚举值作为数组
- jboss - How to configure ActiveMQ Artemis as a broker in JBoss 4?
- powershell - PowerShell 中的 should -Throw 方法
- skia - lld-link: error: could not open 'icuuc': no such file or directory
- excel - Excel conditional formating columns based on formula
- rest - 如何为 keycloak 客户端秘密 REST 调用获取未混淆的客户端秘密
- android - 如何知道用户是否使用了 Google Play 结算库的免费试用版?
- amazon-web-services - Kubernetes YAML file - convert Azure to AWS ("file share" volume segment)