Я сгенерировал координаты цилиндра. Его две грани соединяют две заданные произвольные точки.
Можно ли построить трехмерную маску из заполненного цилиндра из координат со стандартными библиотеками Python? Создание 2D-маски кажется достаточно простым, но я сталкиваюсь с некоторыми трудностями с 3D.
Здесь код для генерации цилиндра, взятый из здесь и здесь :
import scipy
import scipy.linalg
import numpy as np
import nibabel as nib
import matplotlib
matplotlib.use('TkAgg')
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
# defining mask
shape = (100, 100, 100)
image = np.zeros(shape=shape)
# set radius and centres values
r = 3
start = [30, 45, 60]
end = [40, 58, 70]
p1 = np.array(start)
p2 = np.array(end)
# # calculate p2-p1 distance
# dx = p2[0] - p1[0]
# dy = p2[1] - p1[1]
# dz = p2[2] - p1[2]
# dist = math.sqrt(dx**2 + dy**2 + dz**2)
# vector in direction of axis
v = p2 - p1
# find magnitude of vector
mag = scipy.linalg.norm(v)
# unit vector in direction of axis
v = v / mag
# make some vector not in the same direction as v
not_v = np.array([1, 0, 0])
if (v == not_v).all():
not_v = np.array([0, 1, 0])
# make vector perpendicular to v
n1 = np.cross(v, not_v)
# normalize n1
n1 /= scipy.linalg.norm(n1)
# make unit vector perpendicular to v and n1
n2 = np.cross(v, n1)
#surface ranges over t from 0 to length of axis and 0 to 2*pi
t = np.linspace(0, mag, 100)
theta = np.linspace(0, 2 * np.pi, 100)
rsample = np.linspace(0, r, 2)
#use meshgrid to make 2d arrays
t, theta2 = np.meshgrid(t, theta)
rsample, theta = np.meshgrid(rsample, theta)
# generate coordinates for surface
# "Tube"
X, Y, Z = [p1[i] + v[i] * t + r * np.sin(theta2) * n1[i] + r * np.cos(theta2) * n2[i] for i in [0, 1, 2]]
# "Bottom"
X2, Y2, Z2 = [p1[i] + rsample[i] * np.sin(theta) * n1[i] + rsample[i] * np.cos(theta) * n2[i] for i in [0, 1, 2]]
# "Top"
X3, Y3, Z3 = [p1[i] + v[i] * mag + rsample[i] * np.sin(theta) * n1[i] + rsample[i] * np.cos(theta) * n2[i] for i in [0, 1, 2]]
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot_surface(X, Y, Z)
ax.plot_surface(X2, Y2, Z2)
ax.plot_surface(X3, Y3, Z3)
plt.show()
Мне нужна 3D-маска, чтобы выбрать все значения внутри цилиндра 3D-изображения. Форма маски и изображения одинаковы.