File: MedianFilter.h

package info (click to toggle)
transcend 0.3.dfsg2-2
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 5,768 kB
  • sloc: cpp: 26,891; ansic: 693; sh: 210; makefile: 96; perl: 67
file content (159 lines) | stat: -rw-r--r-- 3,540 bytes parent folder | download | duplicates (30)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/*
 * Modification History
 *
 * 2001-May-15     Jeremy Tavan
 * Created.
 * 
 * 2001-May-16     Jeremy Tavan
 * Modified to use the much faster quick_select 
 * median-finding algorithm.
 *
 * 2001-May-17   Jaosn Rohrer
 * Tried to optimize by moving stuff out of the inner-inner loop.
 * It helped a bit, but not much.
 *
 */
 
 
#ifndef MEDIAN_FILTER_INCLUDED
#define MEDIAN_FILTER_INCLUDED
 
#include "minorGems/graphics/ChannelFilter.h" 
#include "quickselect.h"


int medianFilterCompareInt( const void *x, const void *y );

/**
 * Median convolution filter.
 *
 * @author Jeremy Tavan 
 */
class MedianFilter : public ChannelFilter { 

 public:
								
  /**
   * Constructs a median filter.
   *
   * @param inRadius the radius of the box in pixels.
   */
  MedianFilter( int inRadius );
								
								
  /**
   * Sets the box radius.
   *
   * @param inRadius the radius of the box in pixels.
   */
  void setRadius( int inRadius );
								
								
  /**
   * Gets the box radius.
   *
   * @return the radius of the box in pixels.
   */
  int getRadius();
								
								
  // implements the ChannelFilter interface
  void apply( double *inChannel, int inWidth, int inHeight );

 private:
  int mRadius;
};
				
				
				
inline MedianFilter::MedianFilter( int inRadius ) 
  : mRadius( inRadius ) {				
				
}



inline void MedianFilter::setRadius( int inRadius ) {
  mRadius = inRadius;
}



inline int MedianFilter::getRadius() {
  return mRadius;
}				
				
				
				
inline void MedianFilter::apply( double *inChannel, 
																 int inWidth, int inHeight ) {

  // pre-compute an integer version of the channel for the
  // median alg to use
  int numPixels = inWidth * inHeight;
  int *intChannel = new int[ numPixels ];
  for( int p=0; p<numPixels; p++ ) {
	  intChannel[p] = (int)( 1000 * inChannel[p] );
	  }


  
  double *medianChannel = new double[ inWidth * inHeight ];
//  printf("inWidth = %d, inHeight = %d\n", inWidth, inHeight);	
//  printf("mRadius = %d\n",mRadius);
  for( int y=0; y<inHeight; y++ ) {
    int yIndexContrib = y * inWidth;
								
    int startBoxY = y - mRadius;
    int endBoxY = y + mRadius;
								
    if( startBoxY < 0 ) {
      startBoxY = 0;
    }
    if( endBoxY >= inHeight ) {
      endBoxY = inHeight - 1;
    }
								
    int boxSizeY = endBoxY - startBoxY + 1;
								

    for( int x=0; x<inWidth; x++ ) {
      int startBoxX = x - mRadius;
      int endBoxX = x + mRadius;
									
      if( startBoxX < 0 ) {
				startBoxX = 0;
      }
      if( endBoxX >= inWidth ) {
				endBoxX = inWidth - 1;
      }
												
      int boxSizeX = endBoxX - startBoxX + 1;
      int *buffer = new int[boxSizeX * boxSizeY];
      											
      // sum all pixels in the box around this pixel
      for( int boxY = startBoxY; boxY<=endBoxY; boxY++ ) {
				int yBoxIndexContrib = boxY * inWidth;
				int yBoxContrib = boxSizeX * ( boxY-startBoxY );

				for( int boxX = startBoxX; boxX<=endBoxX; boxX++ ) {		
				  //buffer[boxSizeX*(boxY-startBoxY)+(boxX-startBoxX)] = (int)(1000.0 * inChannel[yBoxIndexContrib + boxX]);
				  buffer[ yBoxContrib + ( boxX-startBoxX ) ] = intChannel[ yBoxIndexContrib + boxX ];	
				}
      }
      
      medianChannel[ yIndexContrib + x ] = (double)quick_select( buffer, boxSizeX*boxSizeY ) / 1000.0;

      delete [] buffer;
    }
  }
  

  // copy blurred image back into passed-in image
  memcpy( inChannel, medianChannel, sizeof(double) * inWidth * inHeight );
  
  delete [] medianChannel;
  delete [] intChannel;
}

#endif