问题描述
给定一个3D numpy形状的数组(256、256、256),我该如何在内部制作实心球体形状?下面的代码生成一系列递增和递减的圆,但在其他两个维度上查看时,它们是菱形的.
Given a 3D numpy array of shape (256, 256, 256), how would I make a solid sphere shape inside? The code below generates a series of increasing and decreasing circles but is diamond shaped when viewed in the two other dimensions.
def make_sphere(arr, x_pos, y_pos, z_pos, radius=10, size=256, plot=False):
val = 255
for r in range(radius):
y, x = np.ogrid[-x_pos:n-x_pos, -y_pos:size-y_pos]
mask = x*x + y*y <= r*r
top_half = arr[z_pos+r]
top_half[mask] = val #+ np.random.randint(val)
arr[z_pos+r] = top_half
for r in range(radius, 0, -1):
y, x = np.ogrid[-x_pos:size-x_pos, -y_pos:size-y_pos]
mask = x*x + y*y <= r*r
bottom_half = arr[z_pos+r]
bottom_half[mask] = val#+ np.random.randint(val)
arr[z_pos+2*radius-r] = bottom_half
if plot:
for i in range(2*radius):
if arr[z_pos+i].max() != 0:
print(z_pos+i)
plt.imshow(arr[z_pos+i])
plt.show()
return arr
推荐答案
EDIT :pymrt.geometry
已被删除,以支持 raster_geometry
.
EDIT: pymrt.geometry
has been removed in favor of raster_geometry
.
免责声明:我是pymrt
和raster_geometry
的作者.
如果只需要球体,则可以使用pip
可安装的模块pymrt
,尤其是pymrt.geometry.sphere()
,例如:
If you just need to have the sphere, you can use the pip
-installable module pymrt
, and particularly pymrt.geometry.sphere()
, e.g:
import pymrt as mrt
import pymrt.geometry
arr = mrt.geometry.sphere(3, 1)
array([[[False, False, False],
[False, True, False],
[False, False, False]],
[[False, True, False],
[ True, True, True],
[False, True, False]],
[[False, False, False],
[False, True, False],
[False, False, False]]], dtype=bool)
在内部,这是作为n维超椭球体生成器实现的,您可以检查其源代码以获取详细信息.简而言之,(简化的)代码将如下所示:
internally, this is implemented as an n-dimensional superellipsoid generator, you can check its source code for details.Briefly, the (simplified) code would reads like this:
import numpy as np
def sphere(shape, radius, position):
# assume shape and position are both a 3-tuple of int or float
# the units are pixels / voxels (px for short)
# radius is a int or float in px
semisizes = (radius,) * 3
# genereate the grid for the support points
# centered at the position indicated by position
grid = [slice(-x0, dim - x0) for x0, dim in zip(position, shape)]
position = np.ogrid[grid]
# calculate the distance of all points from `position` center
# scaled by the radius
arr = np.zeros(shape, dtype=float)
for x_i, semisize in zip(position, semisizes):
# this can be generalized for exponent != 2
# in which case `(x_i / semisize)`
# would become `np.abs(x_i / semisize)`
arr += (x_i / semisize) ** 2
# the inner part of the sphere will have distance below 1
return arr <= 1.0
并对其进行测试:
arr = sphere((256, 256, 256), 10, (127, 127, 127))
# this will save a sphere in a boolean array
# the shape of the containing array is: (256, 256, 256)
# the position of the center is: (127, 127, 127)
# if you want is 0 and 1 just use .astype(int)
# for plotting it is likely that you want that
# just for fun you can check that the volume is matching what expected
np.sum(arr)
# gives: 4169
4 / 3 * np.pi * 10 ** 3
# gives: 4188.790204786391
# (the two numbers do not match exactly because of the discretization error)
我无法了解您的代码的工作原理,但是要检查它实际上是否在产生球体(使用您的数字),您可以尝试:
I am failing to get how your code exactly works, but to check that this is actually producing spheres (using your numbers) you could try:
import pymrt as mrt
import pymrt.geometry
arr = mrt.geometry.sphere(256, 10, 0.5)
# plot in 3D
import matplotlib.pyplot as plt
from skimage import measure
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1, projection='3d')
verts, faces, normals, values = measure.marching_cubes(arr, 0.5, (2,) * 3)
ax.plot_trisurf(
verts[:, 0], verts[:, 1], faces, verts[:, 2], cmap='Spectral',
antialiased=False, linewidth=0.0)
plt.show()
这篇关于如何在3D Numpy数组中生成球体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!