Median Search Demo  0.4
Median search demo (lib used by adaptive median image filter)
medians_1D.c
Go to the documentation of this file.
1 /***********************************************************************
2  * $RCSfile$
3  *
4  * These are speed-optimized C routines for a 1-dimensional median
5  * search. QuickSelect and Wirth are the fastest for nominal size
6  * input data, but require a copy of the array in memory. Torben
7  * is much slower in general, but operates on a read-only data set
8  * of arbitrary size. There are other more optimized routines for
9  * hard real-time applications.
10  *
11  * $Log$
12  * Revision 1.7 2005/09/26 02:57:49 sarnold
13  * changed macros to functions (makes swig happy)
14  *
15  * Revision 1.6 2005/09/23 05:50:54 sarnold
16  * updated to doxygen-style comments
17  *
18  * Revision 1.5 2005/09/22 02:14:02 sarnold
19  * added swig info and updated make file
20  *
21  * Revision 1.4 2005/08/28 07:03:53 sarnold
22  * more fine-tuning
23  *
24  * Revision 1.3 2005/08/27 00:29:34 sarnold
25  * header and comment cleanup
26  *
27  * Revision 1.2 2005/08/26 21:29:54 sarnold
28  * minor fixes and cleanup
29  *
30  * Revision 1.1.1.1 2005/08/26 20:18:07 sarnold
31  * initial 1-D median filter demo
32  *
33  * Stephen Arnold <stephen.arnold42 _at_ gmail.com>
34  * $Date$
35  *
36  **********************************************************************/
37 
38 static const char rcsid[] =
39  "$Id";
40 
41 #include "medians_1D.h"
42 
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <unistd.h>
46 
48 
52 void swap(pixelvalue *a, pixelvalue *b) {
54  register pixelvalue t;
55  t=*a; *a=*b; *b=t;
56  return;
57 }
58 
60 
66 pixelvalue
67 #ifdef __GNUC__
68 __attribute__((__no_instrument_function__))
69 #endif
70 quick_select(pixelvalue a[], int n) {
71  int low, high ;
72  int median;
73  int middle, ll, hh;
74 
75  low = 0 ; high = n-1 ; median = (low + high) / 2;
76  for (;;) {
77  if (high <= low) /* One element only */
78  return a[median] ;
79 
80  if (high == low + 1) { /* Two elements only */
81  if (a[low] > a[high])
82  swap(&a[low], &a[high]) ;
83  return a[median] ;
84  }
85 
86  /* Find median of low, middle and high items; swap into position low */
87  middle = (low + high) / 2;
88  if (a[middle] > a[high]) swap(&a[middle], &a[high]) ;
89  if (a[low] > a[high]) swap(&a[low], &a[high]) ;
90  if (a[middle] > a[low]) swap(&a[middle], &a[low]) ;
91 
92  /* Swap low item (now in position middle) into position (low+1) */
93  swap(&a[middle], &a[low+1]) ;
94 
95  /* Nibble from each end towards middle, swapping items when stuck */
96  ll = low + 1;
97  hh = high;
98  for (;;) {
99  do ll++; while (a[low] > a[ll]) ;
100  do hh--; while (a[hh] > a[low]) ;
101 
102  if (hh < ll)
103  break;
104 
105  swap(&a[ll], &a[hh]) ;
106  }
107 
108  /* Swap middle item (in position low) back into correct position */
109  swap(&a[low], &a[hh]) ;
110 
111  /* Re-set active partition */
112  if (hh <= median)
113  low = ll;
114  if (hh >= median)
115  high = hh - 1;
116  }
117 }
118 
120 
126 pixelvalue
127 #ifdef __GNUC__
128 __attribute__((__no_instrument_function__))
129 #endif
130 kth_smallest(pixelvalue a[], int n, int k) {
131  register int i,j,l,m ;
132  register pixelvalue x ;
133 
134  l=0 ; m=n-1 ;
135  while (l<m) {
136  x=a[k] ;
137  i=l ;
138  j=m ;
139  do {
140  while (a[i]<x) i++ ;
141  while (x<a[j]) j-- ;
142  if (i<=j) {
143  swap(&a[i],&a[j]) ;
144  i++ ; j-- ;
145  }
146  } while (i<=j) ;
147  if (j<k) l=i ;
148  if (k<i) m=j ;
149  }
150  return a[k] ;
151 }
152 
154 
159 pixelvalue
160 #ifdef __GNUC__
161 __attribute__((__no_instrument_function__))
162 #endif
163 wirth(pixelvalue a[], int n) {
164  return kth_smallest(a,n,(((n)&1)?((n)/2):(((n)/2)-1)));
165 }
166 
168 
174 pixelvalue
175 #ifdef __GNUC__
176 __attribute__((__no_instrument_function__))
177 #endif
178 torben(pixelvalue m[], int n) {
179  int i, less, greater, equal, half;
180  pixelvalue min, max, guess, maxltguess, mingtguess;
181 
182  half = (n+1)/2 ;
183  min = max = m[0] ;
184  for (i=1 ; i<n ; i++) {
185  if (m[i]<min) min=m[i];
186  if (m[i]>max) max=m[i];
187  }
188 
189  while (1) {
190  guess = (min+max)/2;
191  less = 0; greater = 0; equal = 0;
192  maxltguess = min ;
193  mingtguess = max ;
194  for (i=0; i<n; i++) {
195  if (m[i]<guess) {
196  less++;
197  if (m[i]>maxltguess) maxltguess = m[i] ;
198  } else if (m[i]>guess) {
199  greater++;
200  if (m[i]<mingtguess) mingtguess = m[i] ;
201  } else equal++;
202  }
203  if (less <= half && greater <= half) break ;
204  else if (less>greater) max = maxltguess ;
205  else min = mingtguess;
206  }
207  if (less >= half) return maxltguess;
208  else if (less+equal >= half) return guess;
209  else return mingtguess;
210 }
211 
pixelvalue wirth(pixelvalue a[], int n)
Function wrapper for kth_smallest to get Wirth's median.
Definition: medians_1D.c:163
pixelvalue torben(pixelvalue m[], int n)
Function implementing Torben's algorithm.
Definition: medians_1D.c:178
void swap(pixelvalue *a, pixelvalue *b)
Pixel-swapping macro.
Definition: medians_1D.c:53
pixelvalue kth_smallest(pixelvalue a[], int n, int k)
Function implementing kth_smallest() for Wirth macro.
Definition: medians_1D.c:130
static const char rcsid[]
Definition: medians_1D.c:38
pixelvalue quick_select(pixelvalue a[], int n)
Function implementing quickselect algorithm.
Definition: medians_1D.c:70