'Can a 3D numpy array be converted into a 3D image in Python?
I made the following virtual "room" in a 3D array and would like to visualize it. I can't find a way to do so, please assist. The idea is to see a "3D image" of the array as a plot where the different values have different colours or just greyscale intensities, so that you can see the "patient" and the "detector" inside the "room":
import numpy as np
# Diff. values in the Room define objects: 0 = walls, 1 = inside room, 2 = patient's tissue, 3 = bone, 4 = x-ray detector
Room = np.array([[[0.0 for i in range(0,101,1)] for j in range(0,101,1)] for k in range(0,101,1)]) #The entire room with walls
for i in range(1,100,1):
for j in range(1,100,1):
for k in range(1,100,1):
Room[i,j,k] +=1 # The room not counting the walls
for i in range(30,70,1):
for j in range(30,70,1):
for k in range(30,70,1):
Room[i,j,k] +=1 #The patient's body (tissue)
for i in range(50,55,1):
for j in range(50,55,1):
for k in range(50,55,1):
Room[i,j,k] +=1 #The patient's bone #1
for i in range(58,63,1):
for j in range(58,63,1):
for k in range(58,63,1):
Room[i,j,k] +=1 #The patient's bone #2
for i in range(88,92,1):
for j in range(10,90,1):
for k in range(10,90,1):
Room[i,j,k] +=1 # X-ray Detector
Solution 1:[1]
You can create a 3 dimensional mesh grid with the help of matplotlib and numpy. Here is an example of such a plot. You just want to feed in your X,Y, and Z values as lists
import numpy as np
import matplotlib.pyplot as plt
# Create figure and add axis
fig = plt.figure(figsize=(8,6))
ax = plt.subplot(111, projection='3d')
# Remove gray panes and axis grid
ax.xaxis.pane.fill = False
ax.xaxis.pane.set_edgecolor('white')
ax.yaxis.pane.fill = False
ax.yaxis.pane.set_edgecolor('white')
ax.zaxis.pane.fill = False
ax.zaxis.pane.set_edgecolor('white')
ax.grid(False)
# Remove z-axis
ax.w_zaxis.line.set_lw(0.)
ax.set_zticks([])
# Create meshgrid
X, Y = np.meshgrid(np.linspace(0, 2, len(afm_data)), np.linspace(0, 2, len(afm_data)))
# Plot surface
plot = ax.plot_surface(X=X, Y=Y, Z=Z, cmap='YlGnBu_r', vmin=0, vmax=200)
There is also an article on this topic by Towards Data Science: https://towardsdatascience.com/visualizing-three-dimensional-data-heatmaps-contours-and-3d-plots-with-python-bd718d1b42b4
Solution 2:[2]
Just re-adding this because the first answer got deleted before I had the chance to respond:
Are you looking for a volume rendering approach? There's a broad range of Python libraries with that functionality available. This is an example link.
For your concrete case, you can use e.g. plotly and I just wrote a quick script for your data based on their tutorial:
import numpy as np
import plotly.graph_objects as go
# Generate nicely looking random 3D-field
np.random.seed(0)
l = 5
X, Y, Z = np.mgrid[:l, :l, :l]
vol = np.zeros((l, l, l))
#pts = (l * np.random.rand(3, 15)).astype(np.int)
# Diff. values in the Room define objects: 0 = walls, 1 = inside room, 2 = patient's tissue, 3 = bone, 4 = x-ray detector
Room = np.array([[[0.0 for i in range(0,102,1)] for j in range(0,102,1)] for k in range(0,102,1)]) #The entire room with walls
for i in range(1,100,1):
for j in range(1,100,1):
for k in range(1,100,1):
Room[i,j,k] +=1 # The room not counting the walls
for i in range(30,70,1):
for j in range(30,70,1):
for k in range(30,70,1):
Room[i,j,k] +=1 #The patient's body (tissue)
for i in range(50,55,1):
for j in range(50,55,1):
for k in range(50,55,1):
Room[i,j,k] +=1 #The patient's bone #1
for i in range(58,63,1):
for j in range(58,63,1):
for k in range(58,63,1):
Room[i,j,k] +=1 #The patient's bone #2
for i in range(88,92,1):
for j in range(10,90,1):
for k in range(10,90,1):
Room[i,j,k] +=1 # X-ray Detector
pts = Room.reshape(3,353736).astype(np.int)
print( tuple(indices for indices in pts) )
vol[tuple(indices for indices in pts)] = 1
from scipy import ndimage
vol = ndimage.gaussian_filter(vol, 0.5)
vol /= vol.max()
fig = go.Figure(data=go.Volume(
x=X.flatten(), y=Y.flatten(), z=Z.flatten(),
value=vol.flatten(),
isomin=0.2,
isomax=0.7,
opacity=0.1,
surface_count=25,
))
fig.update_layout(scene_xaxis_showticklabels=False,
scene_yaxis_showticklabels=False,
scene_zaxis_showticklabels=False)
fig.show()
The output is given below. Not sure if this is what you had in mind.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Mr Developer |
| Solution 2 | SarahJuliet1510 |

