Rudin-Osher-Fatemi Total Variation Denoising using Split Bregman
imnoise.c
Go to the documentation of this file.
1 
15 #include <stdio.h>
16 #include <string.h>
17 #include "imageio.h"
18 #include "randmt.h"
19 
21 #define DISPLAY_SCALING 255
22 
24 #define JPEGQUALITY 95
25 
26 
27 void PrintHelpMessage()
28 {
29  puts("Image noise simulator, P. Getreuer, 2012\n\n"
30  "Syntax: imnoise <model>:<sigma> <input> <output>\n");
31  puts("where <input> and <output> are "
32  READIMAGE_FORMATS_SUPPORTED " images.\n");
33  puts(
34  "The <model> argument denotes the noise model. The parameter <sigma>\n"
35  "is the noise level, which is defined to be the square root of the\n"
36  "expected mean squared error.\n");
37  puts(
38  "The pixel intensities are denoted below by X[n] and Y[n], and they\n"
39  "are scaled as values between 0 and 255. Values of Y[n] outside of\n"
40  "this range are saturated.\n");
41  puts(
42  " gaussian:<sigma> Additive white Gaussian noise\n"
43  " Y[n] ~ Normal(X[n], sigma^2)\n"
44  " p(Y[n]|X[n]) = exp( -|Y[n] - X[n]|^2/(2 sigma^2) )\n");
45  puts(
46  " laplace:<sigma> Laplace noise\n"
47  " Y[n] ~ Laplace(X[n], sigma/sqrt(2))\n"
48  " p(Y[n]|X[n]) = exp( -|Y[n] - X[n]| sqrt(2)/sigma )\n");
49  puts(
50  " poisson:<sigma> Poisson noise\n"
51  " Y[n] ~ Poisson(X[n]/a) a\n"
52  " where a = 255 sigma^2 / (mean value of X)\n");
53  puts("Example:\n"
54  " imnoise laplace:10 input.bmp noisy.bmp\n");
55 }
56 
57 void GaussianNoise(float *Image, long NumEl, float Sigma);
58 void LaplaceNoise(float *Image, long NumEl, float Sigma);
59 void PoissonNoise(float *Image, long NumEl, float Sigma);
60 int IsGrayscale(const float *Image, long NumPixels);
61 
62 
63 int main(int argc, char **argv)
64 {
65  const char *Model, *InputFile, *OutputFile;
66  char *ParamString;
67  float *Image;
68  float Param;
69  long NumPixels, NumEl;
70  int Width, Height, NumChannels, Status = 1;
71 
72  if(argc != 4 || !(ParamString = strchr(argv[1], ':')))
73  {
75  return 0;
76  }
77 
78  *ParamString = '\0';
79 
80  /* Read command line arguments */
81  Model = argv[1];
82  Param = (float)(atof(ParamString + 1) / DISPLAY_SCALING);
83  InputFile = argv[2];
84  OutputFile = argv[3];
85 
86  /* Read the input image */
87  if(!(Image = (float *)ReadImage(&Width, &Height, InputFile,
88  IMAGEIO_RGB | IMAGEIO_PLANAR | IMAGEIO_FLOAT)))
89  goto Catch;
90 
91  NumPixels = ((long)Width) * ((long)Height);
92  NumChannels = (IsGrayscale(Image, NumPixels)) ? 1 : 3;
93  NumEl = NumChannels * NumPixels;
94 
95  /* Initialize random number generator */
97 
98  if(!strcmp(Model, "gaussian"))
99  GaussianNoise(Image, NumEl, Param);
100  else if(!strcmp(Model, "laplace"))
101  LaplaceNoise(Image, NumEl, Param);
102  else if(!strcmp(Model, "poisson"))
103  PoissonNoise(Image, NumEl, Param);
104  else
105  {
106  fprintf(stderr, "Unknown noise model, \"%s\".\n", Model);
107  goto Catch;
108  }
109 
110  /* Write noisy and denoised images */
111  if(!WriteImage(Image, Width, Height, OutputFile,
112  ((NumChannels == 1) ? IMAGEIO_GRAYSCALE : IMAGEIO_RGB)
113  | IMAGEIO_PLANAR | IMAGEIO_FLOAT, JPEGQUALITY))
114  {
115  fprintf(stderr, "Error writing to \"%s\".\n", OutputFile);
116  goto Catch;
117  }
118 
119  Status = 0;
120 Catch:
121  Free(Image);
122  return Status;
123 }
124 
125 
126 void GaussianNoise(float *Image, long NumEl, float Sigma)
127 {
128  long n;
129 
130  for(n = 0; n < NumEl; n++)
131  Image[n] += (float)(Sigma*rand_normal());
132 }
133 
134 
135 void LaplaceNoise(float *Image, long NumEl, float Sigma)
136 {
137  const float Mu = (float)(M_1_SQRT2 * Sigma);
138  long n;
139 
140  for(n = 0; n < NumEl; n++)
141  Image[n] += (float)(rand_exp(Mu) * ((rand_unif() < 0.5) ? -1 : 1));
142 }
143 
144 
145 void PoissonNoise(float *Image, long NumEl, float Sigma)
146 {
147  double a, Mean = 0;
148  long n;
149 
150  for(n = 0; n < NumEl; n++)
151  Mean += Image[n];
152 
153  Mean /= NumEl;
154  a = Sigma * Sigma / ((Mean > 0) ? Mean : (0.5/255));
155 
156  for(n = 0; n < NumEl; n++)
157  Image[n] = (float)(rand_poisson(Image[n] / a) * a);
158 }
159 
160 
161 int IsGrayscale(const float *Image, long NumPixels)
162 {
163  const float *Red = Image;
164  const float *Green = Image + NumPixels;
165  const float *Blue = Image + 2*NumPixels;
166  long n;
167 
168  for(n = 0; n < NumPixels; n++)
169  if(Red[n] != Green[n] || Red[n] != Blue[n])
170  return 0;
171 
172  return 1;
173 }