7

Imagine I have a stack of image frames, $(f_1, ..., f_N) \in F$, where each $f_i$ has the same set of $(x,y)$ dimensions. Using these frames, I'd like to create an image where each pixel in the image consists of the standard deviation of the values at the corresponding pixel position in each of the $f_i$.

Unfortunately, the following procedure is painfully slow (when applied to a $256 \times 256$ pixel image):

SDImage = ImageData@FrameStack[[1]];
  For[a = 1, a <= ImageDimensions[FrameStack[[1]]][[1]], a++,
    For[b = 1, b <= ImageDimensions[FrameStack[[1]]][[2]], b++,
     SDImage[[a, b]] = StandardDeviation[Table[ImageData[FrameStack[[k]]][[a, b]], {k, 1, Length[FrameStack]}]];
     Print[SDImage[[a, b]]];
    ];
  ];

SDImage = Image[SDImage]  

Is there a faster method of doing this, or perhaps a built in tool (like in ImageJ)?

Sparse Pine
  • 1,133
  • 6
  • 13

3 Answers3

8

Assuming you have loaded a stack of images and stored in a variable called imageStack you can do the following to compute the standard deviation image over the entire stack:

imageStack = Import["ExampleData/CTengine.tiff"];
xyStd = Image@Thread[StandardDeviation[ImageData /@ imageStack], {1}];

This gives you the standard deviation image in z direction of the stack. For the upper example xyStd gives the following image:

Standard deviation image of engine example.

Edit

As Kuba pointed out, a better solution would be:

StandardDeviation[ImageData /@ imageStack]
g3kk0
  • 3,318
  • 17
  • 37
6

This is about 100 times faster than g3kk0's answer on my machine---the results are identical:

imageStack = Image[ColorCombine@Import["ExampleData/CTengine.tiff", "ImageList"], "Real"];
ImageApply[StandardDeviation, imageStack]
Matthias Odisio
  • 1,246
  • 9
  • 11
2

I wondered whether the built-in StandardDeviationFilter would work here (on Alexander's imageStack).

 StandardDeviationFilter[
 Image3D[
  imageStack, 
  ColorFunction -> "LowRange"],
 {Length[imageStack], 1, 1}]

filtered engine

It kind of works - but it's probably not the solution you're looking for.

cormullion
  • 24,243
  • 4
  • 64
  • 133
  • That's a good suggestion - but I previously tried this, and in my particular case, the results are radically different. – Sparse Pine Jul 27 '13 at 12:30
  • @SparsePine Oh. – cormullion Jul 27 '13 at 12:32
  • Perhaps this is better StandardDeviationFilter[Image3D[imageStack], {Ceiling@Length[imageStack]/2, 0, 0}] -- the last arguments are radii. But it's several times slower than Alexander Schmitz's. – Michael E2 Jul 27 '13 at 12:42
  • @cormullion Sorry, I think I came off as a bit rude there. That really wasn't my intention. I just meant to say that I tried the filter, and it just didn't work very well in my particular case. Thank you for your answer! – Sparse Pine Jul 27 '13 at 12:53
  • @SparsePine No, I didn't think that... I was just surprised that you'd tried it. It's always worth mentioning what you've tried (and providing a small sample of your data). Image3d isn't very quick or dependable on my machine anyway... – cormullion Jul 27 '13 at 13:03
  • @cormullion: I'm not quite sure about that, but doesn't the StandardDeviationFilter give something different in theory than taking the standard deviation over the stack? If the r parameter is set to one this means a 3x3 neighborhood and would explain the slightly blurred looking image in your answer. – g3kk0 Jul 27 '13 at 19:49
  • @AlexanderSchmitz I'm not sure, I just looked up StandardDeviation in the online help. Michael's version is better, and taking the first image of the stack using Image3DSlices (you're looking at the whole stack here) gets quite close. Anyway, it was just a detour worth taking.. :) – cormullion Jul 27 '13 at 20:03
  • @cormullion: it always is ;) – g3kk0 Jul 27 '13 at 20:17