Image3D¶
Status: Stable
documented, exercised by the test suite and/or worked examples, with no known limitations recorded.
Description¶
Image3D[data]
is a volumetric image, normalising to Image3D[data, type]. The data is a depth x height x width array of voxels, or depth x height x width x channels for colour, so it is indexed data[[z, y, x]] with slices outermost. ImageDimensions reports {width, height, depth} -- FULLY REVERSED from that order, which is Mathematica's convention. Type inference and the accessors match Image: ImageQ is False for a volume (use Image3DQ), while ImageDimensions, ImageChannels, ImageType and ImageData all accept either rank.
Examples (71)¶
Every input below was run against the current Mathilda build and its output recorded.
Basic Examples (14)¶
Uniform noise fills the volume to its boundary, so the block shows what it holds
Three channels, one per axis: the faces of the block are three colour gradients
In[3]:= Image3D[Table[{N[x/16], N[y/16], N[z/16]}, {z, 1, 16}, {y, 1, 16}, {x, 1, 16}], "Real"]
Out[3]= -Image-
In[4]:= ball = Image3D[Table[N[Boole[(x - 16)^2 + (y - 16)^2 + (z - 16)^2 <= 100]], {z, 1, 32}, {y, 1, 32}, {x, 1, 32}], "Real"];
In[5]:= shell = Image3D[Table[N[Mod[Floor[Sqrt[(x - 16.)^2 + (y - 16.)^2 + (z - 16.)^2]/3], 2]], {z, 1, 32}, {y, 1, 32}, {x, 1, 32}], "Real"];
In[6]:= cube = Image3D[Table[If[Mod[Quotient[x - 1, 4] + Quotient[y - 1, 4] + Quotient[z - 1, 4], 2] == 0, 0., 1.], {z, 1, 32}, {y, 1, 32}, {x, 1, 32}], "Real"];
In[7]:= ball
Out[7]= -Image-
In[8]:= ImageDimensions[ball]
Out[8]= {32, 32, 32}
In[9]:= Dimensions[ImageData[ball]]
Out[9]= {32, 32, 32}
In[10]:= ImageChannels[ball]
Out[10]= 1
In[11]:= ImageType[ball]
Out[11]= "Real"
In[12]:= Image3DQ[ball]
Out[12]= True
In[13]:= shell
Out[13]= -Image-
In[14]:= cube
Out[14]= -Image-
Scope (28)¶
In[15]:= colvol = Image3D[Table[{N[x/16], N[y/16], N[z/16]}, {z, 1, 16}, {y, 1, 16}, {x, 1, 16}], "Real"];
In[16]:= bitvol = Image3D[Table[Boole[Mod[x + y + z, 2] == 0], {z, 1, 8}, {y, 1, 8}, {x, 1, 8}]];
In[17]:= rampz = Image3D[Table[N[(z - 1)/31], {z, 1, 32}, {y, 1, 24}, {x, 1, 24}], "Real"];
In[18]:= ball = Image3D[Table[N[Boole[(x - 16)^2 + (y - 16)^2 + (z - 16)^2 <= 100]], {z, 1, 32}, {y, 1, 32}, {x, 1, 32}], "Real"];
In[19]:= shell = Image3D[Table[N[Mod[Floor[Sqrt[(x - 16.)^2 + (y - 16.)^2 + (z - 16.)^2]/3], 2]], {z, 1, 32}, {y, 1, 32}, {x, 1, 32}], "Real"];
In[20]:= cube = Image3D[Table[If[Mod[Quotient[x - 1, 4] + Quotient[y - 1, 4] + Quotient[z - 1, 4], 2] == 0, 0., 1.], {z, 1, 32}, {y, 1, 32}, {x, 1, 32}], "Real"];
In[21]:= colvol
Out[21]= -Image-
In[22]:= ImageChannels[colvol]
Out[22]= 3
In[23]:= bitvol
Out[23]= -Image-
In[24]:= ImageType[bitvol]
Out[24]= "Bit"
In[25]:= rampz
Out[25]= -Image-
In[26]:= ImageDimensions[rampz]
Out[26]= {24, 24, 32}
In[27]:= GaussianFilter[ball, 2]
Out[27]= -Image-
In[28]:= MeanFilter[ball, 1]
Out[28]= -Image-
In[29]:= MedianFilter[ball, 1]
Out[29]= -Image-
In[30]:= Dilation[ball, 2]
Out[30]= -Image-
In[31]:= Erosion[ball, 2]
Out[31]= -Image-
In[32]:= Opening[ball, 2]
Out[32]= -Image-
In[33]:= Closing[ball, 2]
Out[33]= -Image-
In[34]:= Binarize[shell]
Out[34]= -Image-
In[35]:= LocalAdaptiveBinarize[shell, 3]
Out[35]= -Image-
In[36]:= DistanceTransform[ball]
Out[36]= -Image-
In[37]:= ImagePad[cube, 2]
Out[37]= -Image-
In[38]:= ImageReflect[cube, Front]
Out[38]= -Image-
In[39]:= ColorConvert[colvol, "Grayscale"]
Out[39]= -Image-
In[40]:= DerivativeFilter[cube, {0, 0, 1}]
Out[40]= -Image-
In[41]:= CornerFilter[ball, 2]
Out[41]= -Image-
In[42]:= ImageCorners[ball]
Out[42]= {{9, 16, 9}, {16, 9, 9}, {16, 23, 9}, {23, 16, 9}, {9, 16, 23}, {9, 23, 16}, {16, 9, 23}, {16, 23, 23}, {23, 16, 23}, {23, 23, 16}, {9, 9, 16}, {23, 9, 16}, {7, 12, 16}, {25, 12, 16}, {12, 16, 7}, {12, 16, 25}, {16, 12, 7}, {16, 12, 25}, {16, 25, 20}, {20, 16, 7}, {20, 16, 25}, {7, 20, 16}, {12, 7, 16}, {12, 25, 16}, {16, 7, 12}, {16, 20, 7}, {16, 20, 25}, {16, 25, 12}, {20, 7, 16}, {20, 25, 16}, {25, 20, 16}, {7, 16, 12}, {7, 16, 20}, {16, 7, 20}, {25, 16, 12}, {25, 16, 20}, {7, 19, 13}, {13, 13, 7}, {13, 13, 25}, {13, 25, 13}, {19, 13, 7}, {19, 13, 25}, {19, 25, 13}, {25, 19, 13}, {7, 13, 13}, {25, 13, 13}, {7, 13, 19}, {7, 19, 19}, {25, 13, 19}, {25, 19, 19}, {13, 7, 19}, {13, 19, 7}, {13, 19, 25}, {13, 25, 19}, {19, 7, 19}, {19, 19, 7}, {19, 19, 25}, {19, 25, 19}, {13, 7, 13}, {19, 7, 13}, {6, 16, 16}, {16, 6, 16}, {16, 16, 6}, {16, 16, 26}, {16, 26, 16}, {26, 16, 16}, {10, 10, 10}, {10, 22, 10}, {22, 10, 10}, {22, 22, 10}, {10, 10, 22}, {10, 22, 22}, {22, 10, 22}, {22, 22, 22}}
Applications (8)¶
In[43]:= ball = Image3D[Table[N[Boole[(x - 16)^2 + (y - 16)^2 + (z - 16)^2 <= 100]], {z, 1, 32}, {y, 1, 32}, {x, 1, 32}], "Real"];
In[44]:= shell = Image3D[Table[N[Mod[Floor[Sqrt[(x - 16.)^2 + (y - 16.)^2 + (z - 16.)^2]/3], 2]], {z, 1, 32}, {y, 1, 32}, {x, 1, 32}], "Real"];
In[45]:= Image[Part[ImageData[ball], 16]]
Out[45]= -Image-
In[46]:= Image[Part[ImageData[GaussianFilter[ball, 2]], 16]]
Out[46]= -Image-
In[47]:= Image[Join[Part[ImageData[shell], 8], Part[ImageData[shell], 16], Part[ImageData[shell], 24], 2]]
Out[47]= -Image-
In[48]:= Total[Flatten[ImageData[ball]]]
Out[48]= 4169.0
In[49]:= Total[Flatten[ImageData[ball] - ImageData[Erosion[ball, 1]]]]
Out[49]= 1640.0
In[50]:= Max[Flatten[ImageData[DistanceTransform[ball]]]]
Out[50]= 10.0499
Properties & Relations (12)¶
In[51]:= ball = Image3D[Table[N[Boole[(x - 16)^2 + (y - 16)^2 + (z - 16)^2 <= 100]], {z, 1, 32}, {y, 1, 32}, {x, 1, 32}], "Real"];
In[52]:= cube = Image3D[Table[If[Mod[Quotient[x - 1, 4] + Quotient[y - 1, 4] + Quotient[z - 1, 4], 2] == 0, 0., 1.], {z, 1, 32}, {y, 1, 32}, {x, 1, 32}], "Real"];
In[53]:= colvol = Image3D[Table[{N[x/16], N[y/16], N[z/16]}, {z, 1, 16}, {y, 1, 16}, {x, 1, 16}], "Real"];
In[54]:= ImageDimensions[ball] === {32, 32, 32}
Out[54]= True
In[55]:= Reverse[ImageDimensions[ball]] === Dimensions[ImageData[ball]]
Out[55]= True
In[56]:= ImageData[ImageReflect[ImageReflect[cube, Front], Front]] === ImageData[cube]
Out[56]= True
In[57]:= ImageData[Dilation[ball, 0]] === ImageData[ball]
Out[57]= True
In[58]:= ImageData[Opening[Opening[ball, 2], 2]] === ImageData[Opening[ball, 2]]
Out[58]= True
In[59]:= ImageDimensions[GaussianFilter[ball, 2]] === ImageDimensions[ball]
Out[59]= True
In[60]:= ImageChannels[ColorConvert[colvol, "Grayscale"]] === 1
Out[60]= True
In[61]:= Image3DQ[ball] && Not[ImageQ[ball]]
Out[61]= True
In[62]:= Max[Flatten[ImageData[CornerFilter[Image3D[Table[If[x <= 16, 0., 1.], {z, 1, 16}, {y, 1, 16}, {x, 1, 16}], "Real"], 2]]]]
Out[62]= 0.0
Neat Examples (5)¶
In[63]:= shell = Image3D[Table[N[Mod[Floor[Sqrt[(x - 16.)^2 + (y - 16.)^2 + (z - 16.)^2]/3], 2]], {z, 1, 32}, {y, 1, 32}, {x, 1, 32}], "Real"];
In[64]:= cube = Image3D[Table[If[Mod[Quotient[x - 1, 4] + Quotient[y - 1, 4] + Quotient[z - 1, 4], 2] == 0, 0., 1.], {z, 1, 32}, {y, 1, 32}, {x, 1, 32}], "Real"];
In[65]:= shell
Out[65]= -Image-
In[66]:= Image[Part[ImageData[shell], 16]]
Out[66]= -Image-
In[67]:= Image[Part[ImageData[Dilation[cube, 1]], 16]]
Out[67]= -Image-
Applications (4)¶
In[68]:= ImageDimensions[Image3D[{{{0., 1.}, {1., 0.}}, {{1., 0.}, {0., 1.}}}]]
Out[68]= {2, 2, 2}
In[69]:= Image3DQ[Image3D[{{{0., 1.}}, {{1., 0.}}}]]
Out[69]= True
In[70]:= ImageQ[Image3D[{{{0., 1.}}, {{1., 0.}}}]]
Out[70]= False
In[71]:= ImageType[Image3D[{{{0, 1}}, {{1, 0}}}, "Bit"]]
Out[71]= "Bit"
Implementation notes¶
Algorithm. builtin_image3d is img_construct(res, "Image3D", vol = true) —
the volumetric twin of Image, sharing one constructor so the two ranks cannot
drift apart. Image3D[data] normalises to the canonical Image3D[data, type]:
the data is a depth × height × width array of voxels (or
depth × height × width × channels for colour), so it is indexed data[[z, y,
x]] with slices outermost. Type inference matches Image: all-integer voxels in
{0, 1} give "Bit", all-integer in 0..255 give "Byte", anything else
"Real"; a stated type coerces the data to it (round and clip for an integer
type). Image3D[volume, type] converts an existing volume between types,
preserving brightness. The data is canonicalised onto the visible NDArray surface
with stored values preserved exactly (img_typed_storage), and malformed input
(ragged, non-numeric, complex) is left unevaluated. Validity is tested by
Image3DQ, not ImageQ (which is False for a volume). The one trap the header
flags: ImageDimensions reports {width, height, depth} — fully reversed
from the z, y, x storage order, which is Mathematica's convention.
Data structures. A canonical Image3D[data, type] node whose data is a
packed NDArray (a flat depth · height · width · channels buffer, row-major,
channels innermost) with a dtype that follows the pixel type ("Bit"/"Byte"
hold integers, "Real" holds float64). image3d_info reads depth, height,
width, channels and type without copying; image3d_load materialises a flat
unit-scale buffer for the filters. Image3D is on pack.c's AWARE list.
Complexity / limits. O(depth · height · width · channels) to canonicalise
and infer. An already-canonical volume on the NDArray surface is returned
unchanged (NULL) so the evaluator reaches a fixed point. ImageQ,
ImageDimensions, ImageChannels, ImageType and ImageData all accept either
rank; only ImageQ/Image3DQ are rank-specific.
Attributes: Protected.
References¶
See also: ImageDimensions, ImageQ, Image3DQ, Image, ImageData, ImageChannels, ImageType
- Source:
src/image.c - Specification:
docs/spec/builtins/image-processing.md - Tests:
tests/test_image.c
Notes & additional examples¶
Notes¶
Image3D[data] is a volumetric image, normalising to Image3D[data, type]. The
data is a depth × height × width array of voxels (or depth × height × width ×
channels for colour), indexed data[[z, y, x]] with slices outermost.
ImageDimensions reports {width, height, depth} — fully reversed from that
storage order, which is Mathematica's convention and the 3-D version of the same
transpose the 2-D accessors carry. Type inference and coercion match Image:
all-integer voxels in {0, 1} give "Bit", in 0..255 give "Byte", else
"Real", and a stated integer type rounds and clips. ImageQ is False for a
volume — use Image3DQ to test validity — while ImageDimensions,
ImageChannels, ImageType and ImageData all accept either rank.