18

8

I'm simulating some images corrupted with Poisson noise, but I'm encountering a few problems with performance. According to the documentation on `ImageEffect`

, one can add Poisson noise according to the following rule:

Loading up an example image, and running the code:

```
man256 = ImageAdjust[ImageResize[ExampleData[{"TestImage", "Man"}], {256, 256}]];
ImageAdjust[ImageEffect[man256, {"PoissonNoise", 0.8}]] // AbsoluteTiming
(* 10.839 seconds *)
```

Subsequently running it again in the same kernel, it only takes 0.196 seconds. Meanwhile, the Gaussian noise effect:

```
ImageAdjust[ImageEffect[man256, {"GaussianNoise", 4.}]] // AbsoluteTiming
(* 0.014 seconds *)
```

And then running it again once more, it only takes 0.006 seconds.

I tried defining my own functions for adding Poisson and Gaussian noise for comparison. Note that I define the amount of Poisson noise slightly differently to the Mathematica method (in a way that actually makes more sense to me).

```
addPoissonNoise[x_, peak_] :=
Block[{imagedata},
imagedata = peak*ImageData[x];
Map[If[# == 0., 0., RandomVariate[PoissonDistribution[#]]] &, imagedata, {2}]
];
addGaussianNoise[x_, sig_] :=
Block[{imagedata},
imagedata = ImageData[x];
Map[# + RandomVariate[NormalDistribution[0., sig]] &, imagedata, {2}]
];
ImageAdjust[Image[addPoissonNoise[man256, 40.]]] // AbsoluteTiming
(* 6.495 seconds *)
ImageAdjust[Image[addGaussianNoise[man256, 4.]]] // AbsoluteTiming
(* 0.007 seconds *)
```

So on an initial run, my code is faster than the built-in code in both cases. But on subsequent runs, it's slower than the built-in code. Considerably slower in the case of Poisson noise.

The Gaussian example is only for comparison - it's the Poisson noise I'm more interested in, and speeding up the **initial** run of the code, as ~10 seconds is considerably slower than I'd like, and in reality my images are bigger than 256x256 pixels.

Is there any way to speed-up the corruption of an image with Poisson noise?

**Update #1**

Replacing `Map`

with `ParallelMap`

speeds up my Poisson noise function, but it's still quite slow (taking about 1.89 seconds on my machine).

Avoiding multiple calls to `RandomVariate`

is hard to avoid, I think. It's a shame `PoissonDistribution`

can't be compiled (Which Distributions can be Compiled using RandomVariate).

**Update #2**

There's this question: Why is Poisson Random Deviate Generation so slow?

(For info, this is with v10 on Win8.1)

2Why not just generate a random image using Poisson, then add/multiply/subtract as appropriate from base image? Much faster. – ciao – 2014-07-29T23:09:08.247

2Forgive me if I'm wrong, but is that method appropriate for Poisson noise, which depends on the underlying pixel value of the base image? Or have I misunderstood? – dr.blochwave – 2014-07-30T09:14:06.860

1@rasher, as blochwave correctly states, the distribution parameter depends on the individual pixel values so you can't simply generate a whole array of random values from a single distribution. – Simon Woods – 2014-07-30T14:02:19.407

1You mention speeding up the initial run of the code, and that it's a shame that

`PoissonDistribution`

can't be compiled. In fact the delay on the initial run is caused by compiling code to provide the Poisson distribution :-) You can look at`Image`ColorOperationsDump`iImageEffectPoissonNoise`

to see how it works internally. – Simon Woods – 2014-07-30T14:46:28.553Indeed, as

`Information[Image`

ColorOperationsDump`PoissonNoise2D]`

shows, it involves`RandomReal[NormalDistribution[]]`

, which does compile. – dr.blochwave – 2014-07-30T14:56:52.660Thanks for noting the internal mechanism @SimonWoods - inspired me towards an answer! – dr.blochwave – 2014-07-30T16:54:50.723