Matlab: Find the distance from an element to the matrix border
Asked Answered
M

3

5

Say in Matlab I have a matrix like this:

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

I now need to find submatrixes 3x3 around every element (so each element in turn is the center of a 3x3 submatrix). When in the middle, it is no problem to find fx

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

which is the submatrix:

2 3 4
2 3 4
2 3 4

But when in the border of the matrix, that is elements in the first og last row or column, it of course isn't possible to find a 3x3 submatrix. Instead I need the submatrix that fits. In the corner fx I would get

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

where the submatrix is:

1 2
1 2

and in the middle of the border, I get fx:

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

which gives:

4 5 6
4 5 6

or as another example:

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

which gives:

6 7 8
6 7 8

I hope you understand my point. I am missing some feature that lets me find the distance from an element to the border.

I can treat every element as a center of a submatrix, and if I can just test, if the distance from the element to the border is below the submatrix's border (the submatrix dimension will namely change, to fx a 5x5 submatrix), then I can truncate a part of the submatrix while it is being made.

How do I find the distance from an element to the border of the matrix in the most efficient way?

Mccutcheon answered 19/6, 2012 at 8:30 Comment(0)
P
2

Let's specify the question a bit further: You have a matrix of the size nxm and you pick an element i,j. You want to know the distance of element i,j from the border? That would be: min(i,j,n-i,m-j)

Parallel answered 19/6, 2012 at 8:39 Comment(6)
I agree with your answer but presumably he is asking for the minimum in EACH direction as he is truncating in rows AND columnsInspirit
That is correct. I need the minimum distance to the border in any direction.Mccutcheon
So you want to know the distance of the sub matrix and not that of the center element?Parallel
I need the distance from the center element in the submatrix to the nearest border.Mccutcheon
But you should see it the other way around: I'm am running through all elements in the matrix. And for every element, I take out the submatrix in which it is center. So when having an element in the for loops, I need to be able to measure, if that element is too close to a border for the surrounding submatrix to be a complete square matrix. If that's the case I will truncate, but I need to know when it is the case.Mccutcheon
Then the min(i, j, n-i, m-j) should do for you. n and m are the static dimensions and you cycle through i and j. If min() is zero, you are 'too close' and have to truncate. If min()>0 then you can have a full 3x3 submatrix.Parallel
D
4

Though it doesn't answer your question directly, I guess that your problem in a higher context is to do some kind of filter or processing on the 3x3 elements. Usually the solution is to pad the array with extra values, say NaN. Then you can safely extract 3x3 sub-matrix, which might have some NaNs.

You can do the padding using padarray command.

Edit(1): I've read your comments to another answer. It looks like you are more interested in detecting the border cases, rather then computing the distance. If you want to know when you are close to a border, how about creating a mask?

mask = false(size(A));
mask(1:2,:) = true;
mask(end-1:end,:) = true;
mask(:,1:2) = true;
mask(:,end-1:end) = true;
Disparage answered 19/6, 2012 at 8:39 Comment(0)
P
2

Let's specify the question a bit further: You have a matrix of the size nxm and you pick an element i,j. You want to know the distance of element i,j from the border? That would be: min(i,j,n-i,m-j)

Parallel answered 19/6, 2012 at 8:39 Comment(6)
I agree with your answer but presumably he is asking for the minimum in EACH direction as he is truncating in rows AND columnsInspirit
That is correct. I need the minimum distance to the border in any direction.Mccutcheon
So you want to know the distance of the sub matrix and not that of the center element?Parallel
I need the distance from the center element in the submatrix to the nearest border.Mccutcheon
But you should see it the other way around: I'm am running through all elements in the matrix. And for every element, I take out the submatrix in which it is center. So when having an element in the for loops, I need to be able to measure, if that element is too close to a border for the surrounding submatrix to be a complete square matrix. If that's the case I will truncate, but I need to know when it is the case.Mccutcheon
Then the min(i, j, n-i, m-j) should do for you. n and m are the static dimensions and you cycle through i and j. If min() is zero, you are 'too close' and have to truncate. If min()>0 then you can have a full 3x3 submatrix.Parallel
G
2
% Define the example data:

Matrix = repmat(1:9, 9, 1)

Edit: a general solution with freely sized submatrices: (size must be an odd number)

% Define the size of submatrix (square matrix assumed here).

SubmatrixSize = 5;

% Check that the size of submatrix is an odd number.

if (mod(SubmatrixSize, 2) == 0)
    error('SubmatrixSize must be odd number.');
end

Distance = floor(SubmatrixSize/2);

VertSize = size(Matrix, 1);
HorzSize = size(Matrix, 2);

for rowIndex = 1:VertSize
    yIndices = (rowIndex-Distance:rowIndex+Distance);
    yIndices = yIndices(find(yIndices >= 1 & yIndices <= VertSize));
    for colIndex = 1:HorzSize
        xIndices = (colIndex-Distance:colIndex+Distance);
        xIndices = xIndices(find(xIndices >= 1 & xIndices <= HorzSize));
        SubmatricesCellArray{rowIndex, colIndex} = Matrix(yIndices, xIndices);
    end
end

This is a possible solution only for 3x3 submatrices:

% This code only works for 3x3 submatrices.

VertSize = size(Matrix, 1);
HorzSize = size(Matrix, 2);

for rowIndex = 1:VertSize
    yIndices = nonzeros(rowIndex-1:rowIndex+1);
    if yIndices(end) > VertSize
        yIndices(end) = [];
    end
    for colIndex = 1:HorzSize
        xIndices = nonzeros(colIndex-1:colIndex+1);
        if xIndices(end) > HorzSize
            xIndices(end) = [];
        end
        SubmatricesCellArray{rowIndex, colIndex} = Matrix(yIndices, xIndices);
    end
end

Then you'll have each submatrix in SubmatricesCellArray{y, x}.

Gregg answered 19/6, 2012 at 8:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.