Image filtering by changing weighted elements along an edge

135 views Asked by At

So basically I would like to apply a filter to a binary image that takes a weighted average of the values of the neighboring cells. This part I have set up already.

My problem now is I have an "edge" in my image (which is not the edge of the matrix). I want to take a weighted after of the neighboring elements, but only do so for the particular elements that I'm interested in.

There are two approaches that I know of. Either 1) change the weight of the disk filter when the edge is in proximity to the disk or 2) somehow reflect/mirror the values near the edge to the other side. The problem with 2) is that my edge is not straight and kind of goes everywhere.

Here is an oversimplification of the scenario:

bin =  [0 0 0 0 0 0 0 0
         0 0 0 0 0 0 0 0
         1 1 1 1 0 0 0 0
         1 1 1 1 1 0 0 0
         1 1 1 1 1 0 0 0
         1 1 1 1 0 0 0 0
         0 0 0 0 0 0 0 0
         0 0 0 0 0 0 0 0];

mask = [0 0 0 0 0 0 0 0
         0 0 0 1 1 1 0 1
         1 1 1 1 1 1 1 1
         1 1 1 1 1 1 1 1
         1 1 1 1 1 1 1 1
         1 1 1 1 1 1 1 1
         0 0 1 1 0 0 0 0
         0 0 0 0 0 0 0 0];

I want to apply a filter to bin but I only want to take weights of the elements that have a value of 1 in mask. I can't necessarily mirror bin because of the nonlinearity of the edge, so there must be some way to change to weights of the disk filter. For example, if the normal disk filter has 20 elements in it, each one would have a weight of 0.05. But let's say we are right up against a flat edge; only half of the values of bin in the disk filter have a value of 1 in mask. Therefore there would be 10 elements, each with a weight of 0.1. Is there a non-iterative way to apply a filter like this?

1

There are 1 answers

3
Cape Code On

One option: use NaN (Not a Number) in a pre-processing step:

bin(~mask)=NaN;

Such that bin looks like:

   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN
   NaN   NaN   NaN     0     0     0   NaN     0
     1     1     1     1     0     0     0     0
     1     1     1     1     1     0     0     0
     1     1     1     1     1     0     0     0
     1     1     1     1     0     0     0     0
   NaN   NaN     0     0   NaN   NaN   NaN   NaN
   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN

And then use nanmean in your filtering routine. In this way, only non-NaN elements are included in the calculation of the mean which will handle a different number of elements to be averaged.

Example:

fun = @(x) nanmean(nanmean(x));
B = nlfilter(bin,[3 3],fun);

Result:

B =

         0         0         0         0         0         0         0         0
    0.6667    1.0000    0.8333    0.5000    0.1667         0         0         0
    0.6667    1.0000    0.8889    0.6667    0.3333    0.1111         0         0
    0.6667    1.0000    1.0000    0.8889    0.5556    0.2222         0         0
    0.6667    1.0000    1.0000    0.8889    0.5556    0.2222         0         0
    0.6667    0.8889    0.7778    0.6111    0.3889    0.1667         0         0
    0.6667    0.8333    0.6667    0.3333    0.1667         0         0         0
         0         0         0         0         0         0         0         0