giorgio.gottardi
giorgio.gottardi

Reputation: 23

Apply custom filter with a custom window matlab

I'm trying to solve the following problem: I'v a kernel made of 0's and 1's , e.g a crosslike kernel

kernel =

 0     1     0
 1     1     1
 0     1     0

and I need to apply it to a given matrix like

D =

16     2     3    13
 5    11    10     8
 9     7     6    12
 4    14    15     1

for semplicity let's assume to start from element D(2,2), wich is 11, to avoid padding (that I can do with padarray). I should superimpose the kernel and extract only elements where kernel==1, i.e [2,5,11,10,7] then apply on them a custom filter like median or average and replacing central element with the result. Then I would like to pass through all other elements (neglect edge elements for semplicity) and do the same. Now I'm using tempS= ordfilt2(Z,order,kernel,'symmetric'); that performs exactly that operation with median filter. But I would like to use a different criterion (i.e. the average or some weird operation )

Upvotes: 1

Views: 353

Answers (2)

Luis Mendo
Luis Mendo

Reputation: 112689

Use blockproc. This also handles border effects automatically (see the documentation). For example, to compute the median of the values masked by the kernel:

mask = logical(kernel);
R = blockproc(D, [1 1], @(d) median(d.data(mask)), ...
    'bordersize', [1 1], 'trimborder', 0);

The first [1 1] indicated the step. The second [1 1] indicates how many elements to take around the central one.

With your example D, the result is

R =
     2     3     3     3
     9     7     8    10
     5     9    10     6
     4     7     6     1

Upvotes: 1

Steffen
Steffen

Reputation: 2431

This should do what you want:

D = rand(10,20);
kernel = [0,1,0;1,1,1;0,1,0];
[dy,dx] = find(kernel==1);
% should be calculated from kernel
dy = dy-2;
dx = dx-2;
% start and stop should calculated by using kernel size
result = zeros(size(D));
for y = 2:(size(D,1)-1)
    for x = 2:(size(D,2)-1)
        elements = D(sub2ind(size(D),y+dy,x+dx));
        result(y,x) = weirdOperation(elements);
    end
end

Nevertheless this will perform very poorly in terms of speed. You should consider use builtin functions. conv2 or filter2 for linear filter operations. ordfilt2 for order-statistic funtionality.

Upvotes: 1

Related Questions