; $Id: //depot/Release/ENVI50_IDL82/idl/idldir/lib/noise_slur.pro#1 $
;
; Copyright (c) 2006-2012, Exelis Visual Information Solutions, Inc. All
; rights reserved. Unauthorized reproduction is prohibited.
;+
; NAME:
; NOISE_SLUR
;
; PURPOSE:
; Introduce noise into an image by picking randomly selected
; pixels to be replaced by a neighboring pixel from a random
; location in the row above. This is meant to simulate a
; downward melting effect. There is an 80% chance of using the
; pixel directly above for replacement and a 10% chance of using
; either of the pixels to the above left and above right.
; The probability of replacing a pixel is controlled by a
; parameter which controls the amount of noise introduced
; into the image.
;
; CATEGORY:
; Image Processing.
;
; CALLING SEQUENCE:
; Result = NOISE_SLUR(Image [, Randomization][, ])
;
; INPUTS:
; Image: A 2D or 3D array of any basic type containing the
; input image.
; 2D arrays are treated as single channel images.
; For 3D arrays, the first dimension contains the
; color channels forming a pixel (Pixel Interleave).
;
; Randomization: A floating-point scalar in the range 0.0-1.0
; that specifies the probability of picking each
; pixel for replacement. 0.0 means there is no
; chance of replacement and 1.0 means that the
; pixel is always replaced, IDL clamps the
; incoming value to the range 0.0-1.0.
; Note that this value specifies the probability
; of replacement for each pixel. It does not
; necessarily mean that a particular percentage of
; the pixels are replaced. The default value is 0.5.
;
; KEYWORDS:
; ITERATIONS: The number of times to apply the noise filter.
; Increasing the number of iterations increases
; the distance pixels can move.
;
; SEED: The seed value for the random number generator.
; This keyword is used in the same way as the SEED
; argument for RANDOMU.
;
;
; OUTPUTS:
; The result is an array of the same type and dimensions
; as the input array.
;
; SIDE EFFECTS:
; None.
;
; RESTRICTIONS:
; None.
;
; PROCEDURE:
;
; EXAMPLE CALLING SEQUENCE:
;
; The following sequence will introduce noise to a test image.
;
; fn = FILEPATH('rose.jpg', SUBDIR=['examples','data'])
; READ_JPEG, fn, image
; result = NOISE_SLUR(image, 0.5, ITER=10)
; tv, result, /true
;
; MODIFICATION HISTORY:
; Nov 2006 - Initial Version
;-
function noise_slur, in_arr, $
randomization_in, $
ITERATIONS=iter_in, $
SEED=seed
compile_opt idl2
on_error, 2 ;Return to caller if an error occurs
CATCH, err ;Catch so we can identify ourself
if err ne 0 then begin
CATCH, /CANCEL
MESSAGE, !ERROR_STATE.MSG
endif
;; Obtain dimension info
n_dims = SIZE(in_arr, /N_DIMENSIONS)
dims = SIZE(in_arr, /DIMENSIONS)
;; Check arguments and keywords
if n_dims ne 2 and n_dims ne 3 then $
MESSAGE, 'Image array must have 2 or 3 dimensions'
if N_ELEMENTS(randomization_in) eq 0 then randomization=0.5 $
else randomization = (randomization_in > 0.0) < 1.0
iter = N_ELEMENTS(iter_in) gt 0 ? iter_in[0] : 1
;; Figure out the number of channels in a pixel.
;; For 2 dim arrays, the array is considered single channel
n_chan = n_dims eq 2 ? 1 : dims[0]
;; This is the number of pixels
n = PRODUCT(dims) / n_chan
;; Reshape to a vector of pixels
result = REFORM(in_arr, n_chan, n)
;; Figure out the width (row length) of the image
width = n_dims eq 2 ? dims[0] : dims[1]
;; Set up the linear array offset for each of the possible replacements,
;; weighting so that we use the pixel directly above 8/10 of the time,
;; and the pixels to the UL and UR 10% of the time. Also, make an entry
;; for 'no replacement'.
offsets = LONG([0, width-1, width+1, width, width, $
width, width, width, width, width, width])
for i=0L, iter-1 do begin
;; Find the pixels that need to be replaced
ind = WHERE(RANDOMU(seed, n, DOUBLE=n gt 1e7) le randomization)
if ind[0] ne -1 then begin
;; Make array of indicies into the offsets table.
;; Start out with all offsets pointing to the 'no replace' entry
off_ind = BYTARR(n)
;; Change ONLY the offsets selected for replacement with
;; a random number between 1 and 10, inclusive
off_ind[ind] = RANDOMU(seed, N_ELEMENTS(ind)) * 10 + 1
;; Prevent going off the top edge
tmp = off_ind[n-width:*]
ind = WHERE(tmp gt 0)
if ind[0] ne -1 then tmp[ind] = 0
off_ind[n-width:*] = tmp
;; Prevent going off the left edge
tmp = off_ind[0:*:width]
ind = WHERE(tmp eq 1)
if ind[0] ne -1 then tmp[ind] = 0
off_ind[0:*:width] = tmp
;; Prevent going off the right edge
tmp = off_ind[width-1:*:width]
ind = WHERE(tmp eq 2)
if ind[0] ne -1 then tmp[ind] = 0
off_ind[width-1:*:width] = tmp
;; Add the offsets to the "straight copy" index vector
ind = LINDGEN(n) + offsets[off_ind]
;; Use these indices to build new array
result = result[*, ind]
endif
endfor
;; Reshape back to original
result = REFORM(result, dims, /OVERWRITE)
RETURN, result
end