Mercurial > hg > octave-image
changeset 687:316123753f9f
imnoise fixes and cleaning
* don't complain for images of class double/single outside range [0 1]
* use randp instead of poissrnd (faster)
* simpler code flow for all types of noise
* keep the image class when adding salt & pepper noise
* extended help text
author | carandraug |
---|---|
date | Wed, 05 Dec 2012 01:51:51 +0000 |
parents | 327a072f6480 |
children | 9c42e8039a1d |
files | inst/imnoise.m |
diffstat | 1 files changed, 73 insertions(+), 55 deletions(-) [+] |
line wrap: on
line diff
--- a/inst/imnoise.m +++ b/inst/imnoise.m @@ -1,6 +1,7 @@ ## Copyright (C) 2000 Paul Kienzle <pkienzle@users.sf.net> ## Copyright (C) 2004 Stefan van der Walt <stefan@sun.ac.za> ## Copyright (C) 2012 Carlo de Falco +## Copyright (C) 2012 Carnë Draug <carandraug@octave.org> ## ## This program is free software; you can redistribute it and/or modify it under ## the terms of the GNU General Public License as published by the Free Software @@ -16,23 +17,27 @@ ## this program; if not, see <http://www.gnu.org/licenses/>. ## -*- texinfo -*- -## @deftypefn {Function File} {@var{B} =} imnoise (@var{A}, @var{type}) +## @deftypefn {Function File} {@var{B} =} imnoise (@var{A}, @var{type}) ## @deftypefnx {Function File} {@var{B} =} imnoise (@dots{}, @var{options}) -## Add noise to image @var{A}. +## Add noise to image. +## +## @deftypefnx {Function File} {@var{B} =} imnoise (@var{A}, "gaussian", @var{mean}, @var{variance}) +## Additive gaussian noise with @var{mean} and @var{variance} defaulting to 0 +## and 0.01. ## -## @table @code -## @item imnoise (A, 'gaussian' [, mean [, var]]) -## additive gaussian noise: @var{B} = @var{A} + noise -## defaults to mean=0, var=0.01 -## @item imnoise (A, 'salt & pepper' [, density]) -## lost pixels: A = 0 or 1 for density*100% of the pixels -## defaults to density=0.05, or 5% -## @item imnoise (A, 'speckle' [, var]) -## multiplicative gaussian noise: @var{B} = @var{A} + @var{A}*noise -## defaults to var=0.04 -## @end table +## @deftypefnx {Function File} {@var{B} =} imnoise (@var{A}, "poisson") +## Creates poisson noise in the image using the intensity value of each pixel as +## mean. ## -## @seealso{rand, randn} +## @deftypefnx {Function File} {@var{B} =} imnoise (@var{A}, "salt & pepper", @var{density}) +## Create "salt and pepper"/"lost pixels" in @var{density}*100 percent of the +## image. @var{density} defaults to 0.05. +## +## @deftypefnx {Function File} {@var{B} =} imnoise (@var{A}, "speckle", @var{variance}) +## Multiplicative gaussian noise with @var{B} = @var{A} + @var{A} * noise with +## mean 0 and @var{variance} defaulting to 0.04. +## +## @seealso{rand, randn, randp} ## @end deftypefn function A = imnoise (A, stype, a, b) @@ -41,62 +46,75 @@ if (nargin < 2 || nargin > 4) print_usage; - elseif (!isimage (A)) + elseif (! isimage (A)) error ("imnoise: first argument must be an image."); - elseif (!ischar (stype)) + elseif (! ischar (stype)) error ("imnoise: second argument must be a string with name of noise type."); endif - in_class = class (A); - switch tolower (stype) - case {"gaussian", "salt & pepper", "salt and pepper", "speckle"} - A = im2double (A); - if (!is_double_image (A)) - ## FIXME we should probably return an error not a warning but may want to keep - ## this for backwards compatibility. Maybe temporarily only. What does matlab do? - warning ("imnoise: image should be in [0,1] range.") - endif - - switch tolower (stype) - case {"gaussian"} - if (nargin < 3), a = 0.0; endif - if (nargin < 4), b = 0.01; endif - A = A + (a + randn (size (A)) * sqrt (b)); - ## Variance of Gaussian data with mean 0 is E[X^2] - case {"salt & pepper", "salt and pepper"} - if (nargin < 3), a = 0.05; endif - noise = rand (size (A)); - A(noise <= a/2) = 0; - A(noise >= 1-a/2) = 1; - case {"speckle"} - if (nargin < 3), a = 0.04; endif - A = A .* (1 + randn (size (A)) * sqrt (a)); - endswitch - - A(A>1) = 1; - A(A<0) = 0; + in_class = class (A); + fix_class = false; # for cases when we need to use im2double - ## we probably should do this in a safer way... but hardcoding the list of - ## im2xxxx functions might not be a good idea since it then it requires to be - ## added here if a new im2xxx function is implemented - A = feval (["im2" in_class], A); - - case {"poisson"} + switch (lower (stype)) + case "poisson" switch (in_class) case ("double") - A = poissrnd (A * 1e12) / 1e12; + A = randp (A * 1e12) / 1e12; case ("single") - A = single (poissrnd (A * 1e6) / 1e6); + A = single (randp (A * 1e6) / 1e6); case {"uint8", "uint16"} - A = cast (poissrnd (A), in_class); + A = cast (randp (A), in_class); otherwise A = imnoise (im2double (A), "poisson"); + fix_class = true; endswitch - + + case "gaussian" + A = im2double (A); + fix_class = true; + if (nargin < 3), a = 0.00; endif + if (nargin < 4), b = 0.01; endif + A = A + (a + randn (size (A)) * sqrt (b)); + ## Variance of Gaussian data with mean 0 is E[X^2] + + case {"salt & pepper", "salt and pepper"} + if (nargin < 3), a = 0.05; endif + noise = rand (size (A)); + if (isfloat (A)) + black = 0; + white = 1; + else + black = intmin (in_class); + white = intmax (in_class); + endif + A(noise <= a/2) = black; + A(noise >= 1-a/2) = white; + + case "speckle" + A = im2double (A); + fix_class = true; + if (nargin < 3), a = 0.04; endif + A = A .* (1 + randn (size (A)) * sqrt (a)); + otherwise error ("imnoise: unknown or unimplemented type of noise `%s'", stype); endswitch + if (fix_class) + ## we probably should do this in a safer way... but hardcoding the list of + ## im2xxxx functions might not be a good idea since it then it requires to + ## be added here if a new im2xxx function is implemented + A = feval (["im2" in_class], A); + elseif (isfloat (A)) + ## this includes not even cases where the noise made it go outside of the + ## [0 1] range, but also images that were already originally outside that + ## range. This is by design and matlab compatibility. And we do this after + ## fixing class because the im2XX functions already take care of such + ## adjustemt + A(A < 0) = cast (0, class (A)); + A(A > 1) = cast (1, class (A)); + endif + endfunction %!assert(var(imnoise(ones(10)/2,'gaussian')(:)),0.01,0.005) # probabilistic @@ -132,4 +150,4 @@ %! A = imnoise (.5 * ones (100, 'single'), 'poisson'); %! subplot (2, 2, 4) %! imshow (A) -%! title ('single image with poisson noise') \ No newline at end of file +%! title ('single image with poisson noise')