views:

543

answers:

3

Hi

What I need to do is to create a "special" kind of median filter for image processing in Matlab - the "holey" median filter. This is a filter that excludes the element at the center of the area.

For standard median filter I use the medfilt2 function, but I can't pass the mask (kernel) for it as a matrix (it's not a linear transform).
For example, using standard averaging filter 3x3 I create the mask (kernel) as:

h = ones(3,3)/9;

And for "holey" averaging filter:

h = ones(3,3)/8;
h(2,2) = 0;

How to do the same thing with median filter? Is there any way to modify the medfilt2 or do I need to implement a running median on my own?

A: 

My guess is that it does not exist, and that you would need to implement one yourself. You can write one as a matlab function or if speed is an issue, write one in C.

Another way to approach your problem is to use a rank filter. It is not the same as what you are asking for, but might be another way to achieve what you want.

Phillip Ngan
Yes, speed is the problem. I tried to implement median filter on my own, but filtering one image 512x512 px took about 5 min in Matlab...
Gacek
+3  A: 

What about using the underlying function ordfilt2 and defining your own domain there?

http://www.mathworks.com/access/helpdesk/help/toolbox/images/ordfilt2.html

MatlabDoug
OK, this is close to what I need, but the problem is that if I have even number of elements in holey filter domain, the median is an arithmetic average of its two elements in the middle. So the only solution is to use two ordfilt2 filters and count the average on my own?
Gacek
+2  A: 

Using @Doug's idea, the following is an example that handles all cases:

  • hole position in even/odd mask size
  • median position in even/odd number of elements

Example:

%%# mask size: N-by-N
N = 3;
assert(N>=3);

%%# read image and add noise
I = im2double( imread('eight.tif') );
I = imnoise(I, 'salt & pepper',0.05);

%%# build mask with hole in center
h = true(N,N);
if mod(N,2) == 0
    %# hole is a 2-by-2 square
    h([N/2 N/2+1],[N/2 N/2+1]) = false(2);
else
    %# hole is one point
    h((N+1)/2,(N+1)/2) = false;
end

%%# compute median filter with hole
num = sum(h(:));
if mod(num,2) == 0
    %# even case: average from using the two elements in the middle
    I1 = ordfilt2(I, num/2, h, 'symmetric');
    I2 = ordfilt2(I, num/2+1, h, 'symmetric');
    J = imdivide( imadd(I1,I2), 2 );
else
    %# odd case: note this is never reached
    J = ordfilt2(I, (num+1)/2, h, 'symmetric');
end

%%# plot and compare against normal median filter
subplot(121), imshow(J)
subplot(122), imshow( medfilt2(I,[N N],'symmetric') );
Amro
Great example (+1). But I would recommend using the 'symmetric' parameter in ordfilt2
Gacek