|
31 | 31 |
|
32 | 32 | import java.util.Random; |
33 | 33 |
|
| 34 | +import net.imglib2.Localizable; |
34 | 35 | import net.imglib2.RandomAccessibleInterval; |
35 | 36 | import net.imglib2.loops.LoopBuilder; |
36 | 37 | import net.imglib2.type.numeric.RealType; |
37 | 38 |
|
| 39 | +import net.imglib2.util.Intervals; |
| 40 | +import org.scijava.common3.MersenneTwisterFast; |
38 | 41 | import org.scijava.function.Computers; |
| 42 | +import org.scijava.ops.spi.Nullable; |
39 | 43 |
|
40 | 44 | /** |
41 | 45 | * Contains Ops designed to add noise to populated images. |
@@ -165,6 +169,60 @@ public static <I extends RealType<I>, O extends RealType<O>> void addNoise(final |
165 | 169 | public final Computers.Arity1<RandomAccessibleInterval<I>, RandomAccessibleInterval<O>> addPoissonNoiseIntervalSeedless = (input, |
166 | 170 | output) -> addPoissonNoise(input, new Random(0xabcdef1234567890L), output); |
167 | 171 |
|
| 172 | + // -- UNIFORM NOISE -- // |
| 173 | + |
| 174 | + /** |
| 175 | + * Sets the real component of an output real number to the addition of the real |
| 176 | + * component of an input real number with an amount of uniform noise. |
| 177 | + * |
| 178 | + * Note that this Op has changed relative to the older implementations; before |
| 179 | + * it operated on RealTypes, we now only provide the operation on |
| 180 | + * {@link RandomAccessibleInterval}s. This is due to the nature of {@link Random}: The old |
| 181 | + * implementation saved a {@link Random} and used it on each {@link RealType} |
| 182 | + * passed to the Op. This provided no deterministic output, as the same input |
| 183 | + * would yield two different outputs if called in succession. Thus in this |
| 184 | + * iteration of the Op we make it a requirement that the input must be an |
| 185 | + * {@link RandomAccessibleInterval}. Since the {@link Random} is created upon every call of the |
| 186 | + * Op it ensures that given the same seed and input data the output will always |
| 187 | + * be the same. |
| 188 | + * |
| 189 | + * @param input the input {@link RandomAccessibleInterval} |
| 190 | + * @param rangeMin the "most negative" value that can be added to each element |
| 191 | + * @param rangeMax the "most positive" value that can be added to each element |
| 192 | + * @param seed the seed to the random number generator |
| 193 | + * @param output the output {@link RandomAccessibleInterval} |
| 194 | + * @implNote op names='filter.addUniformNoise', type=Computer |
| 195 | + */ |
| 196 | + public static <I extends RealType<I>> void compute( // |
| 197 | + RandomAccessibleInterval<I> input, // |
| 198 | + I rangeMin, // |
| 199 | + I rangeMax, // |
| 200 | + @Nullable Long seed, // |
| 201 | + RandomAccessibleInterval<I> output // |
| 202 | + ) { |
| 203 | + // Set seed to default if necessary |
| 204 | + if (seed == null) { |
| 205 | + seed = 0xabcdef1234567890L; |
| 206 | + } |
| 207 | + // Construct the Random Number Generator |
| 208 | + MersenneTwisterFast rng = new MersenneTwisterFast(seed); |
| 209 | + // Find the range |
| 210 | + I range = rangeMax.createVariable(); |
| 211 | + range.set(rangeMax); |
| 212 | + range.sub(rangeMin); |
| 213 | + |
| 214 | + // Loop over the images |
| 215 | + LoopBuilder.setImages(input, output).forEachPixel( (i, o) -> { |
| 216 | + // Random value = next double * range |
| 217 | + o.set(range); |
| 218 | + o.mul(rng.nextDouble(true, true)); |
| 219 | + // Add the range minimum |
| 220 | + o.add(rangeMin); |
| 221 | + // Add the original value |
| 222 | + o.add(i); |
| 223 | + }); |
| 224 | + |
| 225 | + } |
168 | 226 | // -- Static utility methods -- |
169 | 227 |
|
170 | 228 | // Runs the below method on every element of the input iterables. |
|
0 commit comments