Xmipp  v3.23.11-Nereus
transform_add_noise.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  *
3  * Authors: Carlos Oscar S. Sorzano (coss@cnb.csic.es)
4  *
5  * Unidad de Bioinformatica of Centro Nacional de Biotecnologia , CSIC
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20  * 02111-1307 USA
21  *
22  * All comments concerning this program package may be sent to the
23  * e-mail address 'xmipp@cnb.csic.es'
24  ***************************************************************************/
25 
26 #include <random>
28 #include "core/xmipp_error.h"
29 #include "core/xmipp_image.h"
30 
32 {
33 private:
34  const std::string TYPE_POISSON = "poisson";
35 
36 protected:
37  double param1, param2;
38  double df, limit0, limitF;
40  std::string noise_type;
41 
42  void defineParams()
43  {
46  //Usage
47  addUsageLine("Add random noise to the input images.");
48  addUsageLine("Noise can be generated using uniform, gaussian or t-student distributions.");
49  //Parameters
50  addParamsLine("--type <rand_mode> : Type of noise to add");
51  addParamsLine(" where <rand_mode>");
52  addParamsLine(" gaussian <stddev> <avg=0.> :Gaussian distribution parameters");
53  addParamsLine(" student <df> <stddev> <avg=0.> :t-student distribution parameters");
54  addParamsLine(" uniform <min> <max> :Uniform distribution parameters");
55  addParamsLine(" " + TYPE_POISSON + " <min> <max> :Poission distribution. Each pixel i of output is generated as poisson(ref-input[i])");
56  addParamsLine(" [--limit0 <float> ] :Crop noise histogram below this value ");
57  addParamsLine(" [--limitF <float> ] :Crop noise histogram above this value ");
58  //Examples
59  addExampleLine("Add noise to a single image, writing in different image:", false);
60  addExampleLine("xmipp_transform_add_noise -i cleanImage.spi --type gaussian 10 5 -o noisyGaussian.spi");
61  addExampleLine("+++Following =cleanImage.spi= at left and =noisyGaussian.spi= at right: %BR%", false);
62  addExampleLine("+++%ATTACHURL%/cleanImage.jpg %ATTACHURL%/noisyGaussian.jpg %BR%", false);
63  addExampleLine("Add uniform noise to a volume, overriding input volume:", false);
64  addExampleLine("xmipp_transform_add_noise -i g0ta.vol -uniform -0.1 0.1");
65 
66  }
67 
68  void readParams()
69  {
71  do_limit0 = checkParam("--limit0");
72  if (do_limit0)
73  limit0 = getDoubleParam("-limit0");
74  do_limitF = checkParam("--limitF");
75  if (do_limitF)
76  limitF = getDoubleParam("--limitF");
77 
79  df = 3.;
80  noise_type = getParam("--type");
81 
82  if (noise_type == "gaussian")
83  {
84  param2 = getDoubleParam("--type", 1);
85  param1 = getDoubleParam("--type", 2);
86  }
87  else if (noise_type == "student")
88  {
89  df = getDoubleParam("--type", 1);
90  param1 = getDoubleParam("--type", 2);
91  param2 = getDoubleParam("--type", 3);
92  }
93  else if (noise_type == "uniform")
94  {
95  param1 = getDoubleParam("--type", 1);
96  param2 = getDoubleParam("--type", 2);
97  }
98  else if (TYPE_POISSON == noise_type)
99  {
100  param1 = getDoubleParam("--type", 1);
101  param2 = getDoubleParam("--type", 2);
102  }
103  else
104  REPORT_ERROR(ERR_ARG_INCORRECT, "Unknown noise type");
105  }
106 
107  void show()
108  {
110  if (noise_type == "gaussian")
111  std::cout << "Noise avg=" << param1 << std::endl
112  << "Noise stddev=" << param2 << std::endl;
113  else if (noise_type == "student")
114  std::cout << "Degrees of freedom= "<< df << std::endl
115  << "Noise avg=" << param1 << std::endl
116  << "Noise stddev=" << param2 << std::endl;
117  else if (noise_type == "uniform")
118  std::cout << "Noise min=" << param1 << std::endl
119  << "Noise max=" << param2 << std::endl;
120  else if (TYPE_POISSON == noise_type)
121  std::cout << "Mean background=" << param1 << std::endl
122  << "Mean foreground=" << param2 << std::endl;
123  if (do_limit0)
124  std::cout << "Crop noise histogram below=" << limit0 << std::endl;
125  if (do_limitF)
126  std::cout << "Crop noise histogram above=" << limitF << std::endl;
127  }
128 
129  template<typename T>
130  void limit(Image<T> &img) {
131  if (do_limit0) {
132  const size_t count = img.data.nzyxdim;
133  for (size_t i = 0; i < count; ++i) {
134  img.data[i] = XMIPP_MAX(img.data[i], limit0);
135  }
136  }
137  if (do_limitF) {
138  const size_t count = img.data.nzyxdim;
139  for (size_t i = 0; i < count; ++i) {
140  img.data[i] = XMIPP_MIN(img.data[i], limitF);
141  }
142  }
143  }
144 
145  void processImage(const FileName &fnImg, const FileName &fnImgOut, const MDRow &rowIn, MDRow &rowOut)
146  {
147 
148  if (TYPE_POISSON == noise_type) {
149  Image<float> img;
150  img.read(fnImg);
151  std::random_device rd;
152  std::mt19937 gen(rd());
153  Image<int> res(img.data.xdim, img.data.ydim, img.data.zdim, img.data.ndim);
154  const size_t count = res.data.nzyxdim;
155  const float gap = param1 - param2;
156  auto dist = std::poisson_distribution<>(0);
157  for (size_t i = 0; i < count; ++i) {
158  float mean = param1 - gap * img.data[i];
159  if (dist.mean() != mean) { // reuse distribution, if possible
160  dist = std::poisson_distribution<>(mean);
161  }
162  res.data[i] = dist(gen);
163  }
164  limit(res);
165  res.write(fnImgOut);
166  } else {
167  Image<double> img;
168  img.read(fnImg);
169  img().addNoise(param1, param2, noise_type, df);
170  limit(img);
171  img.write(fnImgOut);
172  }
173 
174  }
175 
176 }
177 ;//end of class ProgAddNoise
#define XMIPP_MAX(x, y)
Definition: xmipp_macros.h:193
double getDoubleParam(const char *param, int arg=0)
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211
void write(const FileName &name="", size_t select_img=ALL_IMAGES, bool isStack=false, int mode=WRITE_OVERWRITE, CastWriteMode castMode=CW_CAST, int _swapWrite=0)
#define i
MultidimArray< T > data
Definition: xmipp_image.h:55
const char * getParam(const char *param, int arg=0)
Incorrect argument received.
Definition: xmipp_error.h:113
void addExampleLine(const char *example, bool verbatim=true)
void limit(Image< T > &img)
std::string noise_type
#define XMIPP_MIN(x, y)
Definition: xmipp_macros.h:181
void show() const override
bool checkParam(const char *param)
int read(const FileName &name, DataMode datamode=DATA, size_t select_img=ALL_IMAGES, bool mapData=false, int mode=WRITE_READONLY)
bool each_image_produces_an_output
Indicate that an output is produced for each image in the input.
void addUsageLine(const char *line, bool verbatim=false)
void processImage(const FileName &fnImg, const FileName &fnImgOut, const MDRow &rowIn, MDRow &rowOut)
void addParamsLine(const String &line)