5

When indexing matrices in MATLAB, can I specify only the first or last n dimensions, and have all others dimensions "selected automatically"?

For example, I am writing a function which takes in an image, and displays it with imshow, which can either display a 3-D color image (e.g 1024×768×3) or a 2-D monochrome array (e.g 1024x768).
My function does not care about how many color channels the image has, imshow will take care of that. All I want to do is pass parameters to select a single region:

imshow(frame(x1:x2, y1:y2, :))

What do I put in place of the last colon to say "include all the others dimensions"?

Eitan T
  • 32,660
  • 14
  • 72
  • 109
sebf
  • 2,831
  • 5
  • 32
  • 50
  • 5
    Does that last colon not work? Usually that is Matlab syntax for 'all' – Schorsch Jun 04 '13 at 17:55
  • @Schorsch is right: [Colon operator documentation](http://www.mathworks.com/help/matlab/ref/colon.html) – Doresoom Jun 04 '13 at 18:00
  • 2
    No, because that will linearise the indices across the remaining dimensions. E.g. if frame is 5-dimensional, this will give a 1-dimensional result, as opposed to 3-dimensional as expected. I assume @sebf wants to preserve the trailing dimensions, in their existing structure? – Sanjay Manohar Jun 04 '13 at 20:42
  • related question: [Indexing of unknown dimensional matrix](http://stackoverflow.com/questions/10146082) – Eitan T Jun 05 '13 at 08:56

2 Answers2

7

You can use comma-separated-list expansion together with the ':' indexing.

Suppose your input is:

A = rand([7,4,2,3]);

To retrieve only first 2:

cln = {':', ':'};
A(cln{:})

To retrieve the last 3:

cln = {1, ':', ':', ':'};
A(cln{:})

Which can be generalized with:

sten            = 2:3;    % Which dims to retrieve
cln(1:ndims(A)) = {1};
cln(sten)       = {':'};
A(cln{:})
Oleg
  • 10,406
  • 3
  • 29
  • 57
  • 2
    Very useful trick. Worth pointing out that you can have as many colons as you want, because the length is assumed to be 1 for any trailing dimensions that "don't exist". – Sanjay Manohar Jun 04 '13 at 20:39
1

Following from Oleg's answer, here is a function that will work if you are selecting from several of the first dimensions. If other dimensions are needed, I think you can see how to modify.

function [dat] = getblock2(dat, varargin)
%[dat] = getblock(dat, varargin) select subarray and retain all others
%                                unchanged
%dat2 = getblock(dat, [1,2], [3,5]) is equivalent to
%       dat2 = dat(1:2, 3:5, :, :, :) etc.
%Peter Burns 4 June 2013

arg1(1:ndims(dat)) = {':,'};
v = cell2mat(varargin);
nv = length(v)/2;
v = reshape(v,2,nv)';
for ii=1:nv
    arg1{ii} = [num2str(v(ii,1)),':',num2str(v(ii,2)),','];
end
arg2 = cell2mat(arg1);
arg2 = ['dat(',arg2(1:end-1),')'];
dat = eval(arg2);
PDBurns
  • 19
  • 2