umbe1987
umbe1987

Reputation: 3568

neighbor analysis in MATLAB

I have an m-by-n matrix named A, with values 1s and 0s. I want to convert all 0s values to 1s if at least 5 out of 8 neighbor pixels are 1s. What I tried is to use the nlfilter function, but I'm not getting how the arg fun should be used, and I would need a help. I created a function as handle for nlfilter as following:

function b = gap_fill(A)
b=A;
index= A([1 2 3 4 6 7 8 9]);
if sum(index)>=5
b(5)= 1
end
end

Then I tried to do this:

B= nlfilter(A,[3 3],@gap_fill)

But it gave this error:

??? Subscripted assignment dimension mismatch.

Error in ==> nlfilter at 75
    b(i,j) = feval(fun,x,params{:});

Any suggestion? The main problem is I'm not used to handle functions.

= UPDATING =

I finally came up with a good result. I changed my function to output a scalar and when I use it as fun arg in nlfilter it work the way I want. This is my code, thanks for helping and I hope it could be useful for anybody:

function b = gap_fill(A)
index= A([1 2 3 4 6 7 8 9]);
if sum(index)>=5
A(5)= 1;
end
b=A(5);
end

In MATLAB:

b= nlfilter (A,[3 3],'gap_fill')

Upvotes: 2

Views: 286

Answers (4)

Luis Mendo
Luis Mendo

Reputation: 112659

You can do it in one line with blockproc:

B = blockproc(A,[1 1],@(x)sum(x.data(:)),'BorderSize',[1 1],'TrimBorder',0)-A>=5;

For example,

A =

     1     0     1     1     0
     0     0     0     1     1
     1     1     1     1     1
     0     1     0     1     1

gives the result

B =

     0     0     0     0     0
     0     1     1     1     0
     0     0     1     1     1
     0     0     1     0     0

Note that border pixels of the image are handled correctly, thanks to using the 'BorderSize' option of blockproc.

To keep the original ones in A, apply a final "or" operation:

B = B|A;

Upvotes: 3

anquegi
anquegi

Reputation: 11522

The fun function must return an scalar in your case it returns a matrix. from matlab

B = nlfilter(A, [m n], fun) applies the function fun to each m-by-n sliding block of the grayscale image A. fun is a function that accepts an m-by-n matrix as input and returns a scalar result.

c = fun(x)

so your code shoud be There are better ways to code it,specially with amtrix but following your sample:

function b = gap_fill(A)
index= A([1 2 3 4 6 7 8 9]);
if A(5)sum(index)>=5
    b = 1;
else
    b = A(5);
end
end

Sorry for the error I change b = 0 to b= A(5)

Upvotes: 0

Jonas
Jonas

Reputation: 74930

For a solution that's slightly faster than blockproc, you can use a 2D convolution:

mask = ones(3);
mask(5) = 0;
B = conv2(A,mask,'same') >= 5;

To make this even faster (you'll only notice this if the arrays become larger), you can make use of the fact that an average filter is separable:

B = conv2(conv2(A,ones(1,3),'same'),ones(3,1),'same') - A >= 5;

Upvotes: 1

Dinesh
Dinesh

Reputation: 2204

I think it is because the documentation for nlfilter says that the user function must return a scalar and you are trying to return a matrix.

B = nlfilter(A, [m n], fun) applies the function fun to each m-by-n sliding block 
of the grayscale image A. fun is a function that accepts an m-by-n matrix as input
and returns a scalar (!!!) result.

Upvotes: 2

Related Questions