2014
11-30

# Median Filter

Median filter is a cornerstone of modern image processing and is used extensively in

Given a black and white image of n by n pixels, the algorithm works as follow:
For each pixel p at the i�th row and the j�th column (1+ r <= i, j <= n � r), its gray level g[i,j] is replace by the median of gray levels of pixels in the (2r+1) by (2r+1) square centered at p. The square is called the filtering window and r is its radius.

Considering the above example, the gray level of the pixel at center will be changed from 150 to 124, which is the median of a filtering window of radius 1.

Note that the algorithm won’t be applied on the pixels near the boundary, for the filtering window lies outside the image. So you are actually asked to output the filtered sub-image which contains the pixels from (r+1, r+1) to (n-r, n-r).

The input contains several test cases.
For each test case:

(a) The first line contains two integers, n and r, meaning that the size of image is n * n (3 <= n <= 500) and the radius of filtering window is r ( 3 <= 2r + 1 <= n).

(b) The following n lines contains the n by n gray level matrix presenting the image

(c) The gray level ranges from 0 to 1000000 The input ends by double 0s.

The input contains several test cases.
For each test case:

(a) The first line contains two integers, n and r, meaning that the size of image is n * n (3 <= n <= 500) and the radius of filtering window is r ( 3 <= 2r + 1 <= n).

(b) The following n lines contains the n by n gray level matrix presenting the image

(c) The gray level ranges from 0 to 1000000 The input ends by double 0s.

3 1
1 1 1
1 1 1
1 1 1
3 1
1 9 6
4 5 2
3 7 8
3 1
0 0 0
255 255 255
0 255 0
5 1
0 0 1 1 0
1 0 1 0 1
0 0 1 1 1
1 1 1 0 1
1 0 0 0 1
0 0

1
5
0
0 1 1
1 1 1
1 0 1

Hint
The definition of “median”: One type of average, found by arranging the values in order and then selecting the one in the middle.
If the total number of values in the sample is even, then the median is the mean of the two middle numbers.
The median is a useful number in cases where the distribution has very large extreme values which would otherwise skew the data.



#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;

const int MAXN = 505;
const int MAXV = 1000050;

int old[MAXN][MAXN],ans[MAXN][MAXN];
int C[MAXV],Max;

void update(int p,int val)
{
while(p<=Max) {
C[p]+=val;
p+=p&-p;
}
}

int findK(int K)
{
int pos = 0,cnt = 0;
for(int i=20; i>=0; i--) {
pos+=(1<<i);
if(pos>=Max||cnt+C[pos]>=K)pos-=(1<<i);
else cnt+=C[pos];
}
return pos+1;
}

int main()
{
//freopen("input.txt", "r", stdin);
int n,r;
while(scanf("%d%d",&n,&r),n) {
Max = 0;
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++) {
scanf("%d",&old[i][j]);
old[i][j]++;
if(old[i][j]>Max)Max = old[i][j];
}

fill(C,C+Max+1,0);

for(int i=1; i<=2*r; i++)
for(int j=1; j<=2*r+1; j++)
update(old[i][j],1);

int mid = ((2*r+1)*(2*r+1)+1)/2;
for(int i=2*r+1; i<=n; i++) {
if(i&1) {
if(i-2*r-1>0)
for(int j=1; j<=2*r+1; j++) update(old[i-2*r-1][j],-1);
for(int j=1; j<=2*r+1; j++)update(old[i][j],1);
for(int j=2*r+1; j<=n; j++) {
ans[i-r][j-r] = findK(mid);
if(j+1<=n) {
for(int t=0; t<2*r+1; t++) {
update(old[i-t][j-2*r],-1);
update(old[i-t][j+1],1);
}
}
}
} else {
for(int j=n; j>=n-2*r; j--)update(old[i-2*r-1][j],-1);
for(int j=n; j>=n-2*r; j--)update(old[i][j],1);
for(int j=n-2*r; j; j--) {
ans[i-r][j+r] = findK(mid);
if(j>1) {
for(int t=0; t<2*r+1; t++) {
update(old[i-t][j+2*r],-1);
update(old[i-t][j-1],1);
}
}
}
}
}
for(int i=r+1; i<=n-r; i++) {
for(int j=r+1; j<=n-r; j++)
printf("%d ",ans[i][j]-1);
puts("");
}
}
return 0;
}