%% MATLAB 3D viewer demo 2 % % In this example, we will demonstrate the surface rendering capabilities % of the 3D viewer. % % Rather than using an existing dataset, we will create a dummy one, in the % shape of multiple balls or octahedrons. The balls will be created one by % one, from a volume where all pixels are 0, but within the object volume, % whose location and size is set randomly. From this volume, we ask the 3D % viewer to create an iso-surface (one for each object), and to display it % in the 3D universe, with a random color. %% % Let us define the size of our target image volume. Not too big to save % memory. width = 128; height = 128; depth = 64; %% % Here we determine how many objects we want, and their mean size. We will % generate them randomly. nballs = 10; radius = 20; %% % We pre-allocate the image volume. I = zeros(width, height, depth, 'uint8'); %% % To simplify the object creation step, we create the grid containing each % pixel coordinates. [X, Y, Z] = meshgrid(1:width, 1:height, 1:depth); %% % Since we want to add the objects in live mode, we need to create and show % the universe before creating and adding the balls. So we call Miji first, Miji(false) %% % Then deal with the 3D universe. universe = ij3d.Image3DUniverse(); universe.show(); %% % Now add the objects one by one, in a loop. for i = 1 : nballs %% % Determine the ball center and radius randomly. x = round( width * rand ); y = round( height * rand ); z = round( depth * rand ); r = round( radius * (1 + randn/2) ); intensity = 255; %% % Logical indexing: we find the pixel indices that are within the % object's volume. % This gives you a ball % index = (X-x).^2 + (Y-y).^2 + (Z-z).^2 < r^2; % This gives you an octaedron index = abs(X-x) + abs(Y-y) + abs(Z-z) < r; %% % Then we set the intensity of these pixels to 'intensity' (here, 255) % and the value of pixels outside the object volume to 0. I(~index) = 0; I(index) = intensity; %% % We now export this MATLAB volume to a new ImagePlus image, without % displaying it. imp = MIJ.createImage(['Ball ' int2str(i)], I, false); %% % It is possible to specify the color of the iso-surface at creation, % but the 3D viewer expects a |Color3f| object, which is part of the % |org.scijava.vecmath package|. We determine its actual color % randomly again. color = org.scijava.vecmath.Color3f(rand, rand, rand); %% % Finally, we add the object to the 3D universe, in the shape of an % iso-surface. Arguments meaning is detailed below. c = universe.addMesh(imp, ... - this is the source ImagePlus color, ... - this is the destination color ['Ball ' int2str(i)], ... - the name of the iso-surface 1, ... - the threshold, see below [true true true], ... - what channels to display 1 ... - the resampling factor ); %% % Ok, so the meanings of the |imp|, |color| and |name| arguments are % trivial. The |threshold| value, here set to 1, is important for this % display mode. % % Isosurface rendering uses the fast marching cube algorithm, which % assumes that there is a threshold that separates the background from % the foreground. In our case, it is easy to determine, since pixels % out of the ball have a 0 intensity, and inside the ball they have an % intensity of 255. So any threshold value between these two numbers % would have worked. % % The array containing the 3 boolean values is used to specify what % channels will be included in the surface rendering, if you feed it a % color image. In our case, we simply set them all to true and do not % care much. Finally, the resampling factor is used to win some time % and memory at the expense of precision. If set to more than 1, the % image is downsampled before the marching cube algorithm is applied, % resulting in less meshes obtained in smaller time. %% % Now, this individual step is going to take some time, so it is very % likely that you see each ball appearing one by one. That is because % computing the surface mesh is expensive, so the rendering lags a bit % behind the command. end %% % That's it. Note that some of our objects might be clipped because they % cross the boundaries of the volume we defined in the variable |I|. % % % % <> %% % % _Jean-Yves Tinevez \ - July 2011_