1 #include <tclap/CmdLine.h> 15 template <
class ComponentType,
unsigned int InputDim>
19 typedef itk::Image<ComponentType,InputDim> InputImageType;
21 typedef typename NoiseFilterType::OutputImageType OutputImageType;
23 typename NoiseFilterType::Pointer mainFilter = NoiseFilterType::New();
24 mainFilter->SetNumberOfWorkUnits(args.
nthreads);
25 mainFilter->SetInput(anima::readImage<InputImageType>(args.
input));
26 mainFilter->SetNoiseSigma(args.
sigma);
28 mainFilter->SetNumberOfReplicates(args.
nreplicates);
32 anima::writeImage<OutputImageType>(args.
output, mainFilter->GetOutput(0));
35 std::size_t pointLocation = args.
output.find_last_of(
".");
36 std::string filePrefix = args.
output.substr(0, pointLocation);
37 std::string fileExtension = args.
output.substr(pointLocation);
39 if (fileExtension ==
".gz")
41 pointLocation = filePrefix.find_last_of(
".");
42 filePrefix = filePrefix.substr(0, pointLocation);
43 fileExtension = filePrefix.substr(pointLocation) +
".gz";
49 ss << std::setw(3) << std::setfill(
'0') << (i + 1);
50 std::string tmpStr = ss.str();
51 anima::writeImage<OutputImageType>(filePrefix + tmpStr + fileExtension, mainFilter->GetOutput(i));
56 template <
class ComponentType >
63 int main(
int argc,
char **argv)
65 TCLAP::CmdLine cmd(
"INRIA / IRISA - VisAGeS/Empenn Team",
' ',ANIMA_VERSION);
67 TCLAP::ValueArg<std::string> inArg(
"i",
"inputfile",
"Input image on which to add noise.",
true,
"",
"input image",cmd);
68 TCLAP::ValueArg<std::string> outArg(
"o",
"outputfile",
"Output image. If number of replicates is 1, it is used as provided for saving the noisy dataset with the corresponding file name. If number of replicates > 1, the extension is extracted as desired output file format and the file name without extension is used as base file name for all replicates.",
true,
"",
"output file prefix",cmd);
69 TCLAP::ValueArg<std::string> refArg(
"r",
"reference",
"Masked reference image over which the average SNR is defined.",
true,
"",
"reference image",cmd);
71 TCLAP::ValueArg<double> snrArg(
"s",
"snr",
"Average SNR in dB over the reference image (default: 25dB).",
false,25.0,
"mean snr",cmd);
72 TCLAP::ValueArg<unsigned int> repArg(
"n",
"num-replicates",
"Number of independent noisy datasets to generate (default: 1).",
false,1,
"number of replicates",cmd);
74 TCLAP::SwitchArg gaussArg(
"G",
"gauss-noise",
"Adds Gaussian noise instead of Rician noise.",cmd,
false);
75 TCLAP::SwitchArg matchArg(
"M",
"match-snr",
"Make Gaussian noise comparable to Rician noise in terms of SNR.",cmd,
false);
76 TCLAP::SwitchArg verboseArg(
"V",
"verbose",
"Outputs noise calculations to the console.",cmd,
false);
78 TCLAP::ValueArg<unsigned int> nbpArg(
"p",
"numberofthreads",
"Number of threads to run on (default : all cores).",
false,itk::MultiThreaderBase::GetGlobalDefaultNumberOfThreads(),
"number of threads",cmd);
84 catch (TCLAP::ArgException& e)
86 std::cerr <<
"Error: " << e.error() <<
"for argument " << e.argId() << std::endl;
91 double snr = std::pow(10.0, snrArg.getValue() / 20.0);
94 typedef itk::Image<double,3> Input3DImageType;
95 typedef itk::ImageRegionConstIterator<Input3DImageType> Input3DIteratorType;
97 Input3DImageType::Pointer referenceImage = anima::readImage<Input3DImageType>(refArg.getValue());
98 Input3DIteratorType refItr(referenceImage, referenceImage->GetLargestPossibleRegion());
100 double meanReferenceValue = 0;
101 unsigned int numNonZeroVoxels = 0;
103 while (!refItr.IsAtEnd())
105 double referenceValue = refItr.Get();
107 if (referenceValue == 0)
113 meanReferenceValue *= (numNonZeroVoxels / (numNonZeroVoxels + 1.0));
114 meanReferenceValue += referenceValue / (numNonZeroVoxels + 1.0);
120 double riceSigmaParameter = meanReferenceValue / snr;
123 double snrValue = meanReferenceValue / riceSigmaParameter;
124 double laguerreArgument = -1.0 * snrValue * snrValue / 2.0;
126 double riceMeanValue = riceSigmaParameter * std::sqrt(M_PI / 2.0) * laguerreValue;
127 double riceStdValue = 2.0 * riceSigmaParameter * riceSigmaParameter + meanReferenceValue * meanReferenceValue - M_PI * riceSigmaParameter * riceSigmaParameter * laguerreValue * laguerreValue / 2.0;
128 if (riceStdValue < 0.0)
130 std::cerr <<
"The evaluation of the Kummer M function was too imprecise and produced a negative variance." << std::endl;
133 riceStdValue = std::sqrt(riceStdValue);
136 double effSnrValue = riceMeanValue / riceStdValue;
139 double gaussSigmaParameter = (matchArg.isSet()) ? meanReferenceValue / effSnrValue : riceSigmaParameter;
142 double noiseSigmaParameter = (gaussArg.isSet()) ? gaussSigmaParameter : riceSigmaParameter;
144 if (verboseArg.isSet())
147 std::cout <<
" - User-defined average SNR: " << snrArg.getValue() <<
" dB." << std::endl;
148 std::cout <<
" - Reference image used for noise variance calculation: " << refArg.getValue() << std:: endl;
149 std::cout <<
" - Average signal in foreground voxels of the reference image: " << meanReferenceValue << std::endl;
150 std::cout <<
" - Resulting coil standard deviation (Rice sigma parameter): " << riceSigmaParameter << std::endl;
151 std::cout <<
" - Mean value of Rice distribution: " << riceMeanValue << std::endl;
152 std::cout <<
" - Standard deviation of Rice distribution: " << riceStdValue << std::endl;
153 std::cout <<
" - Effective average SNR: " << 20.0 * std::log10(effSnrValue) <<
" dB." << std::endl;
155 if (gaussArg.isSet())
156 std::cout <<
" - Noise distribution: Gaussian" << std::endl;
158 std::cout <<
" - Noise distribution: Rician" << std::endl;
160 std::cout <<
" - Resulting noise sigma parameter: " << noiseSigmaParameter << std::endl;
164 itk::ImageIOBase::Pointer
imageIO = itk::ImageIOFactory::CreateImageIO(inArg.getValue().c_str(),itk::ImageIOFactory::ReadMode);
168 std::cerr <<
"Itk could not find a suitable IO factory for the input" << std::endl;
173 imageIO->SetFileName(inArg.getValue());
174 imageIO->ReadImageInformation();
178 args.
input = inArg.getValue();
179 args.
output = outArg.getValue();
180 args.
sigma = noiseSigmaParameter;
189 catch (itk::ExceptionObject &err)
191 std::cerr << err << std::endl;
int main(int argc, char **argv)
void retrieveNbDimensions(itk::ImageIOBase::Pointer imageIO, const arguments &args)
void addNoise(itk::ImageIOBase::Pointer imageIO, const arguments &args)
itk::ImageIOBase::Pointer imageIO
#define ANIMA_RETRIEVE_COMPONENT_TYPE(imageIO, function,...)
double GetKummerFunctionValue(const double &x, const double &a, const double &b, const unsigned int maxIter, const double tol)
Computes the confluent hypergeometric function 1F1 also known as the Kummer function M...
#define ANIMA_RETRIEVE_NUMBER_OF_DIMENSIONS(imageIO, ComponentType, function,...)