I have a series of axisymmetric images of a jellyfish swimming in fluid. Overlaid on these images are plots of the Lagrangian coherent structures associated with swimming, which highlight the fluid transport and mixing: A plot of the jellyfish bell kinematics and the Lagrangian coherent structures

Since these images are axisymmetric, I was wondering: is there a way that I can revolve a single two-dimensional image about its x axis, so as to create a three-dimensional surface, and then visualize this as a volumetric render? If possible, I'd like to retain the same colors as in the two-dimensional image, as they are significant. As well, I'd like to create a cut-away that removes a fourth of the volume, like in the following image: A three-dimensional plot of the jellyfish bell kinematics and the Lagrangian coherent structures

I'm aware of the following posts: How to show solid bodies using volumetric rendering? and How to create blurred Graphics3D objects?. However, they don't cover a crucial step: how to do the x-axis revolution.

  • $\begingroup$ mathematica.stackexchange.com/questions/11654/… provides the revolution, although I don't really follow what should be drawn in 3D. $\endgroup$
    – Öskå
    Commented Aug 11, 2014 at 0:05
  • $\begingroup$ It would be useful if you could provide the grayscale and the overlaid coloured components separately. $\endgroup$
    – Szabolcs
    Commented Aug 11, 2014 at 0:47
  • $\begingroup$ @Szabolcs: I likely won't be able to post the separated images until tomorrow. I doubt that I'll be able to get physical access to my lab workstation this late in the evening. $\endgroup$
    – isledge
    Commented Aug 11, 2014 at 1:22

1 Answer 1


This is not a full solution, but here's a start. It would be useful if you could provide the grayscale and the overlaid coloured components separately because it looks like the grayscale part should control the opacity and the colours need to be added afterwards.

Get the image:

source = Import["https://i.sstatic.net/W76CQ.jpg"];

Reflect because we will rotate around the top edge. Negate because white in the original needs to be transparent.

img = ColorNegate@ImageReflect[source, Top -> Bottom]

Aspect ratio:

len = Divide @@ N@ImageDimensions[img]

Interpolating functions, one per channel:

{r, g, b} = ListInterpolation[#, {{0, 1}, {0, len}}] & /@ ImageData /@ ColorSeparate[img];

In a full solution each would be converted to 3D, then combined using ColorCombine.

Rotate to generate 3D data:

step = 0.02;
data = Table[With[{rad = Sqrt[x^2 + y^2]}, If[rad > 1, 0, g[rad, z]]], {x, -1, 1, step}, {y, -1, 1, step}, {z, 0, len, step}]; // AbsoluteTiming

This took about 30 seconds on my machine. Increase step when experimenting to reduce resolution and let the computation finish faster.


Image3D[data, ClipRange -> {All, {0, 1/step}, {0, 1/step}}, ColorFunction -> "RainbowOpacity"]

This is a single channel image, so I used a colour function that makes it easier to see what's going on.

Ideally you'd compute this for the grayscale background, which will serve as the opacity channel, then for the red-blue overlay (red and blue channels), then finally ColorCombine.

  • $\begingroup$ I just wanted to pass along that this looks absolutely amazing! I'm still interested in seeing what the visualization looks like without a colormap applied to it. As such, I'll make sure and separate out the data tomorrow afternoon/evening and update my post. $\endgroup$
    – isledge
    Commented Aug 11, 2014 at 1:45
  • $\begingroup$ @isledge I'm not going to be here for two days, but the information in this answer should be a good start .. $\endgroup$
    – Szabolcs
    Commented Aug 11, 2014 at 2:01
  • $\begingroup$ Also, out of curiosity, did you use step = 0.02 when making the above image? I ask because it led to a number of jagged artifacts around certain edges (i.sstatic.net/l3NJq.jpg). I ultimately changed the variable value to step = 0.01 to improve the overall quality. However, I didn't know if there was some sort of post-processing technique that you were applying. $\endgroup$
    – isledge
    Commented Aug 11, 2014 at 2:21
  • $\begingroup$ @isledge I used 0.02 first, then later changed the image to a 0.01 one. Using such a small step size really requires either a better (faster) implementation, or parallelization. Parallelization has the problem described under "Possible Issues" in the DistributeDefinitions doc page. So at this point it gets a bit non-trivial. If you have trouble, I'll be back in two days to help ... $\endgroup$
    – Szabolcs
    Commented Aug 11, 2014 at 3:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.