WILLIAM HERTZ
WILLIAM HERTZ

Reputation: 31

Cut out all of a square array except for a specified NxN section in the middle in matlab

How can I take the following square array (or any other square array ebtered by the user) and take the center NxN square? For example:

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

is entered along with specifications for the middle 2x2, so it becomes

6    7
10   11

Here is my code thus far:

function [FinalMatrix] = arraycenter(x, m)
% arraycenter takes a large square NxN matrix and trims away everything
% other than the center 'm'x'm' submatrix.
% x must be a square 2 dimension matrix that is at least 3x3
% m must be an integer less than or equal to N, and if N is even, m
% must be even, and vice versa

% Find dimensions of x and check to make sure it is a square, 2D matrix
columndim = size(x, 1);
rowdim = size(x, 2);
pagedim = size(x, 3);
if columndim < 2 || rowdim < 2 || pagedim ~= 1
    error('Your first matrix entered was not two dimensional. Try again.')
end
if columndim ~= rowdim
    error('Your first matrix was not a square. Try again.')
end

% Make sure m is the correct size
if m >= columndim || m >= rowdim
    error('m is too large. Try again.')
end

% Make sure N and m match (N is odd, m is odd; N is even, m is even)
if rem(rowdim, 2) == 0 && rem(m, 2) == 1
    error('N is even and m is odd. Try again.')
end
if rem(rowdim, 2) == 1 && rem(m, 2) == 0
    error('N is odd and m is even. Try again.')
end

% Perform the operation to find the center matrix
end

As you can see, I have done all the data validation. I am stuck on the actual performance of the task. Thank you in advance!

Upvotes: 2

Views: 118

Answers (1)

saastn
saastn

Reputation: 6015

The following function crops out a square matrix from center of another. It does not control the even/odd criteria implemented in your code. If equal margins cannot be created according to the dimensions of x and the value of m, the top and left margins will be smaller than the right and bottom margins by one element.

function [y, sI, eI] = arraycenter(x, m)
% returns an m by m matrix from center of square matrix x
% startIndex and endIndex are index of first and last 
%   column (or row) if x that will be copied to y,
%   so that y = x(sI:eI, sI:eI)

% check if x is a square 2d matrix
sz = size(x);
if ~ismatrix(x) || sz(1)~=sz(2)
    error('x must be a square 2D matrix');
end

% check id m is equal or less than d
d = sz(1);
if m>d
    error('m must be equal or less than size(x, 1).');
end

sI = floor((d-m)/2)+1;
eI = sI+m-1;
y = x(sI:eI, sI:eI);

end

But if you insist to inform caller that all margins will not be equal, you can add the following control as well:

if mod((d-m), 2)
    warning('y can not be exactly at the center of x.');
end

Use it like:

n = 5;
M = magic(n)
for i=1:n
    fprintf('%dx%d:\n', i, i);
    disp(arraycenter(M, i));
end

M =

  17    24     1     8    15  
  23     5     7    14    16  
   4     6    13    20    22  
  10    12    19    21     3  
  11    18    25     2     9  

1x1:

  13  

2x2:

   5     7  
   6    13  

3x3:

   5     7    14  
   6    13    20  
  12    19    21  

4x4:

  17    24     1     8  
  23     5     7    14  
   4     6    13    20  
  10    12    19    21  

5x5:

  17    24     1     8    15  
  23     5     7    14    16  
   4     6    13    20    22  
  10    12    19    21     3  
  11    18    25     2     9  

Upvotes: 1

Related Questions