comp.lang.idl-pvwave archive
Messages from Usenet group comp.lang.idl-pvwave, compiled by Paulo Penteado

Home » Public Forums » archive » Re: Finding the median of a set of images
Show: Today's Messages :: Show Polls :: Message Navigator
E-mail to friend 
Switch to threaded view of this topic Create a new topic Submit Reply
Re: Finding the median of a set of images [message #6115] Wed, 24 April 1996 00:00
Dyer Lytle is currently offline  Dyer Lytle
Messages: 11
Registered: April 1996
Junior Member
Last week I wrote:

>
> Does anyone have an algorithm for finding the median at each pixel
> position for a set of equal size 2-D images? Currently the only way
> I have to do this is to extract all the values for a given pixel
> position into a 1-D array and find the median on that. Doing it
> pixel by pixel like this is inefficient in IDL so I am looking for an
> *array* based algorithm that would find all the medians in parallel.


Well, I wrote an array based median routine based on an algorithm from
"Numerical Recipies, The Art of Scientific Computing" by Press,
Flannery, Teukolsky, and Vettering on pages 460-462. This is an
iterative median finder and I added sigma pixel rejection.

Unfortunately, it is much slower than doing it pixel by pixel! There
are two reasons for this, one is that I have to do a *lot* of array
comparisons and the other is that some pixels take *many* iterations
to converge. On average, convergence should only take log N passes
through the data, but when you have, say, 65,536 medians to be
calculated, (256 x 256 image), there are always a few that take much
longer then log N passes to converge.

I'll include the function below, if anyone has any tricks to try to
speed up the code significantly, I'd love to hear about them.

It was interesting.....

Cheers,

-Dyer

--
------------------------
Dyer Lytle
dlytle@as.arizona.edu
HST NICMOS Project
Steward Observatory
University of Arizona
------------------------


;+
; Name:
; immedian
;
; Purpose:
; This function finds the median at each pixel position for an array
; of images. Allow iterative pixel rejection if nsig is specified.
;
; Category:
; images, statistics
;
; Calling Sequence:
; medimage = immedian(in, nsig, minpix)
;
; Inputs:
; in: A 3D array from which to form a median image along the 3rd axis.
; nsig: The number of sigmas to use for iterative pixel rejection
; minpix: The minumum number of pixels to allow for finding a median
;
; Outputs:
; medimage: A 2D array containing the median data.
;
; Modification History:
; 18, April, 1996, Written by Dyer Lytle, HST NICMOS project
; (algorithm from "Numerical Recipies, The Art of
; Scientific Computing" by Press, Flannery,
; Teukolsky, and Vettering, pp 460-462)
;-
;
;
;on_error, 2 ; Return to caller if an error occurs

function immedian, in, nsig, minpix

; Find the size of the arrays.
tmp = size(in)
dims = tmp(0)
dim1 = tmp(1)
dim2 = tmp(2)
dim3 = tmp(3)

; Create mask array to mark rejected values.
rmask = bytarr(dim1,dim2,dim3)

; Return w/ error message if input array incorrect.
if (dims ne 3 or dim3 lt 3) then begin
print, 'immedian: Input array must be 3D'
print, 'and the third dimension must be larger than 2.'
return, 1
endif

; Define a few constants.
big = 1.0e30
afac = 1.05
amp = 1.05

; Initialization and allocation
a = 0.5 * (in(*,*,0) + in(*,*,dim3-1)) ; first guess for the median
eps = abs(in(*,*,dim3-1)-in(*,*,0)) ; first guess at point spacing
ap = fltarr(dim1,dim2) ; upper bound on the median
am = fltarr(dim1,dim2) ; lower bound on the median
sum = fltarr(dim1,dim2)
sumx = fltarr(dim1,dim2)

np = intarr(dim1,dim2) ; number of points above the current guess
nm = intarr(dim1,dim2) ; number of points below the current guess
xp = fltarr(dim1,dim2) ; value of the point above and closest to the guess
xm = fltarr(dim1,dim2) ; value of the point below and closest to the guess

nextit: ; next sigma iteration, initialize boundarys
ap(*,*) = big
am(*,*) = -big

one: ; next median iteration, initialize various arrays
sum(*,*) = 0.0
sumx(*,*) = 0.0
np(*,*) = 0
nm(*,*) = 0
xp(*,*) = big
xm(*,*) = -big

; For all the images in the 3rd dimension.
for j=1,dim3 do begin
xx=in(*,*,j-1)

np = np + 1 * (xx gt a) * (rmask(*,*,j-1) ne 1)
mask1 = xx lt xp and xx gt a
mask2 = xx ge xp or xx lt a or rmask(*,*,j-1) eq 1
xp = xp * mask2 + xx * mask1
nm = nm + 1 * (xx lt a)
mask1 = xx gt xm and xx lt a
mask2 = xx le xm or xx gt a or rmask(*,*,j-1) eq 1
xm = xm * mask2 + xx * mask1

; Prepare for the division below for calculating 'dum'.
tmpdum = eps+abs(xx-a)
tmpwhere = where(xx eq a,cnt)
if (cnt gt 0) then tmpdum(tmpwhere) = 10.0 ; random value to avoid div by 0
dum = 1./tmpdum

sum = sum + dum * (xx ne a) * (rmask(*,*,j-1) ne 1)
sumx = sumx + xx * dum * (xx ne a) * (rmask(*,*,j-1) ne 1)

endfor

; Check to see if we are done finding median.
tmp = where((abs(nm-np) gt 2),count)
where_nc = (abs(nm-np) gt 2)
if (count eq 0) then begin ; got the median! (for all pixels)
; For even N the median is always an average.
if ((dim3 mod 2) eq 0) then begin
xmed = 0.5*(xp+xm) * (np eq nm) + $
0.5*(a+xp) * (np gt nm) + $
0.5*(xm+a) * (np lt nm)
; For odd N median is always one point.
endif else begin
xmed = a * (np eq nm) + $
xp * (np gt nm) + $
xm * (np lt nm)
endelse

; If nsig is zero then don't do sigma rejection, just return.
; Otherwise, if nsig is greater than zero, goto sigma rejection.
if (nsig gt 0) then begin
goto, nextsig
endif else begin
goto,fin
endelse
endif

; If we got here, median for some pixels not done yet,
; recalculate and reiterate. (Guess is too low or too high.)

mask1 = (np-nm) ge 2
mask2 = (np-nm) lt 2
mask3 = (nm-np) ge 2
mask4 = (nm-np) lt 2

; New best guess.
aa = (xp+((sumx/sum-a*((sumx/sum-a) gt 0)))*amp)*mask1 + $ ; guess was low
(xm+((sumx/sum-a*((sumx/sum-a) lt 0)))*amp)*mask3 + $ ; guess was high
a * (abs(nm-np) lt 2) ; don't really need this last term...

; Don't let it exceed boundaries.
aa = 0.5*(a+ap)*(aa gt ap) + 0.5*(a+am)*(aa lt am) + $
aa * (aa lt ap and aa gt am)

; Calculate new boundaries.
am = am * mask2 + a * mask1
ap = ap * mask4 + a * mask3

; And a new smoothing factor.
eps = afac*abs(aa-a) * (where_nc eq 1) + eps * (where_nc eq 0)
a = aa * (where_nc eq 1) + a * (where_nc eq 0)

; Iterate median once again.
goto, one

nextsig: ; next sigma iteration

; Calculate standard deviations.
; IDL's MOMENT routine only works on 1-D arrays so write our own...

mean = total(in,3)/dim3 ; calculate all the means
mean3 = rebin(mean,dim1,dim2,dim3) ; rebin to 3D for variance calculation

; Calculate variance and standard deviation. (same var equation as IDL moment)
var = (1./(dim3-1))*(total((in-mean3)^2,3)-(1./dim3)*total((in-mea n3)^2,3))
stdv = sqrt(var)

; 2D array containing number of 'good' values for each pixel before rejection.
oldmaskcount = dim3-total(rmask,3)

; Reject points. Points that are more that nsig standard deviations
; from the median have their mask values set to one.
tmp = where(in gt rebin((xmed+nsig*stdv),dim1,dim2,dim3) or $
in lt rebin((xmed-nsig*stdv),dim1,dim2,dim3),cnt)
if (cnt gt 0) then rmask(tmp) = 1 ; tmp contains list of places where true

; 2D array containg number of 'good' values for each pixel after rejection.
newmaskcount = dim3-total(rmask,3)

; How many places still have more than minpix pixels and
; had a point rejected?
tmp = where(newmaskcount gt minpix and (oldmaskcount - newmaskcount) gt 0,ct)

; If no points rejected or numpts le minpix for all array points, done.
; Else, iterate once again.
if (ct eq 0) then begin
goto, fin
endif else begin
goto, nextit
endelse

fin:

; Attempt to recover memory by setting arrays to scalers. (does this work?)
rmask = 0
np = 0
nm = 0
xp = 0
xm = 0
a = 0
aa = 0
an = 0
ap = 0
eps = 0
mask1 = 0
mask2 = 0
mask3 = 0
mask4 = 0
mean = 0
mean3 = 0
var = 0
stdv = 0
oldmaskcount = 0
newmaskcount = 0

; Successful return.
return, xmed

end
  • Attachment: immedian.pro
    (Size: 6.45KB, Downloaded 66 times)
Re: Finding the median of a set of images [message #6136 is a reply to message #6115] Fri, 19 April 1996 00:00 Go to previous message
peter is currently offline  peter
Messages: 80
Registered: February 1994
Member
Joseph M Zawodny (j.m.zawodny@larc.nasa.gov) wrote:

: I think that this should be native to IDL and not require a
: CALL_EXTERNAL call. I also think that MEDIAN should be modified to add
: this functionality in exactly the same way TOTAL was modified to sum over
: requested dimensions of a multi dimensional array. My particular need
: is to compute the median profile (one dimesional rather than two) of a
: set of profiles. RSI has already solved the basic problem when they
: enhanced TOTAL and so it should be relatively straight forward to add
: this to MEDIAN (and MEAN and STDDEV and ...).

and FFT and ...

Peter

--------------------------------
Peter Webb, HP Labs Medical Dept
E-Mail: peter_webb@hpl.hp.com
Phone: (415) 813-3756
Re: Finding the median of a set of images [message #6138 is a reply to message #6136] Fri, 19 April 1996 00:00 Go to previous message
Joseph M Zawodny is currently offline  Joseph M Zawodny
Messages: 24
Registered: March 1996
Junior Member
David Foster wrote:
>
> Dyer Lytle <dlytle@as.arizona.edu> wrote:
>>
>> Hello all,
>>
>> Does anyone have an algorithm for finding the median at each pixel
>> position for a set of equal size 2-D images? Currently the only way
>> I have to do this is to extract all the values for a given pixel
>> position into a 1-D array and find the median on that.
>
> This sounds like a good candidate for using CALL_EXTERNAL to
> call a routine coded in C or Fortran! If someone can think
> of an array-based way to do this in IDL I would be very
> impressed.
>
> If you are unfamiliar with using CALL_EXTERNAL zap me an
> email and I'll send you some sample code using C routines.
> The manual also has some examples, in the Advanced Development
> Guide (RSI will send you one [free!] by request only).
>
> Sorry this isn't what you wanted to hear.

I think that this should be native to IDL and not require a
CALL_EXTERNAL call. I also think that MEDIAN should be modified to add
this functionality in exactly the same way TOTAL was modified to sum over
requested dimensions of a multi dimensional array. My particular need
is to compute the median profile (one dimesional rather than two) of a
set of profiles. RSI has already solved the basic problem when they
enhanced TOTAL and so it should be relatively straight forward to add
this to MEDIAN (and MEAN and STDDEV and ...).

Just $0.02
--
Work: Dr. Joseph M. Zawodny Play: Joe Zawodny
NASA Langley Research Center KO4LW@amsat.org
E-mail: J.M.Zawodny@LaRC.NASA.gov zawodny@exis.net
Re: Finding the median of a set of images [message #6139 is a reply to message #6136] Fri, 19 April 1996 00:00 Go to previous message
steinhh is currently offline  steinhh
Messages: 260
Registered: June 1994
Senior Member
In article <4l6221$bl9@news1.ucsd.edu>, David Foster <foster@bial1.ucsd.edu> writes:
|>
|> Dyer Lytle <dlytle@as.arizona.edu> wrote:
|> >
|> > Hello all,
|> >
|> > Does anyone have an algorithm for finding the median at each pixel
|> > position for a set of equal size 2-D images? Currently the only way
|> > I have to do this is to extract all the values for a given pixel
|> > position into a 1-D array and find the median on that.
|>
|> This sounds like a good candidate for using CALL_EXTERNAL to
|> call a routine coded in C or Fortran! If someone can think
|> of an array-based way to do this in IDL I would be very
|> impressed.
|>

I agree that this is an excellent candidate for a CALL_EXTERNAL
routine for maximum performance, but there is an array-based way
to do this, by using the second argument to the MEDIAN
function to calculate the median of each set of N consecutive
points (one point from each of the N images), after rearranging
the image pixels.

The problem is that for each final image point, N medians are
calculated for N data points each, whilst the looping
method calculates only one median per image point (from N data
points). The array version scales as N^2, and the looping version
as N. For N greater than about 5, looping is faster!

For very few images, however, the array based operation is quicker,
perhaps by a factor of 2.5, but the actual numbers will vary from
machine to machine.

There's also a problem with calculating the median of the last
image point whenever there's an even number of images. This
point should perhaps be calculated explicitly after doing the
array operation

Stein Vidar Haugan

------------------------------------------
;; Median of N images
PRO medin,n,sz

IF N_ELEMENTS(n) NE 1 THEN n = 3
IF N_ELEMENTS(sz) NE 1 THEN sz = 100

n = LONG(n)
sz = LONG(sz)

s1 = sz
s2 = sz

;; N images (s1 x s2)
ims = randomn(seed,s1,s2,n)

;; Looping version

m1 = fltarr(s1,s2)
FOR i=0L,s2-1 DO BEGIN
FOR j=0L,s1-1 DO BEGIN
m1(j,i) = MEDIAN(ims(j,i,*))
END
END

;; Array based version (one loop, I know, but the
;; killer wrt time is the MEDIAN operation (N*N complexity))

mmm = fltarr(N*s1*s2,/nozero) ; Working space
ix = LINDGEN(s1*s2)*N
FOR imno = 0,N-1 DO mmm(ix+imno) = ims(*,*,imno) ; Rearranging the images

;; Calculate median of each set of N consecutive points
m2 = MEDIAN(mmm,N)
;; Pick out the interesting one
m2 = REFORM(m2(ix+N/2),s1,s2,/overwrite)

;; Point out that last pixel may differ.

iix = WHERE(m2 NE m1, count)
PRINT,count
IF count NE 0 THEN PRINT,"Images differ in pixel number:",iix
END
Re: Finding the median of a set of images [message #6142 is a reply to message #6136] Thu, 18 April 1996 00:00 Go to previous message
David Foster is currently offline  David Foster
Messages: 341
Registered: January 1996
Senior Member
Dyer Lytle <dlytle@as.arizona.edu> wrote:
>
> Hello all,
>
> Does anyone have an algorithm for finding the median at each pixel
> position for a set of equal size 2-D images? Currently the only way
> I have to do this is to extract all the values for a given pixel
> position into a 1-D array and find the median on that.

This sounds like a good candidate for using CALL_EXTERNAL to
call a routine coded in C or Fortran! If someone can think
of an array-based way to do this in IDL I would be very
impressed.

If you are unfamiliar with using CALL_EXTERNAL zap me an
email and I'll send you some sample code using C routines.
The manual also has some examples, in the Advanced Development
Guide (RSI will send you one [free!] by request only).

Sorry this isn't what you wanted to hear.

Dave Foster
UCSD Brain Image Analysis Lab
foster@bial1.ucsd.edu
  Switch to threaded view of this topic Create a new topic Submit Reply
Previous Topic: High color on window95
Next Topic: Correlation analysis routine

-=] Back to Top [=-
[ Syndicate this forum (XML) ] [ RSS ] [ PDF ]

Current Time: Wed Oct 08 15:11:28 PDT 2025

Total time taken to generate the page: 0.01022 seconds