How to crop arrays using a vector? (reverse of padarray)

6 ビュー (過去 30 日間)
Kerwin
Kerwin 2012 年 7 月 11 日
*Short version: I'm looking for the reverse of padarray, where you can do padarray(a,[2 2 2]), but instead have it crop [2 2 2] instead of pad [2 2 2]. (Or alternatively, imcrop for more then two dimensions); *
Long version: I have a cell arrays of unknown size K, each cell in the array contains an numerical array with dimensions (m,n,k,... )importantly:
1. I don't know beforehand how many dimensions there will be for the
numerical arrays in the different cell arrays, but I
know that within a cell array all the numerical arrays will have
the same number of dimensions.
2. While all the arrays have the same number of dimensions, they
differ in size.
Basically I want to make a functions that crops the numerical arrays to the smallest dimensions, and then concatenates them, i.e. if
a{1} = zeros(10,10)
a{2} = zeros(16,6)
a{3} = zeros(6,6)
I want the outcome to be an array c with size (6,6,3).
I guess the problem is that I don't know how to index the arrays for a variable amount of dimensions. That is, I can get the size to which I need to crop (or the number by which I need to crop) in vector form like [6 6] or [15 4 8], but I don't know how to use this vector to index my arrays.
Thanks in advance!
Edit: Just thought of something, but it's very ugly: if we know we want to crop to an array of size (30,30,30)
minSize = [30 30 30]
c = []
for ii = length(a);
temp = a{ii}(:);
mask = zeros(minSize)
padding = (minSize - size(a{ii})./2;
mask = padarray(mask,padding,1,'both');
mask = logical(mask);
temp(mask)= [];
temp = reshape(temp,minSize);
c = cat(ndim(a{ii})+1,c,temp);
end
  2 件のコメント
Jan
Jan 2012 年 7 月 11 日
Do you know an upper limit for the number of dimensions?
Kerwin
Kerwin 2012 年 7 月 13 日
No, they can theoretically be of any nr.

サインインしてコメントする。

採用された回答

Sean de Wolski
Sean de Wolski 2012 年 7 月 11 日
編集済み: Sean de Wolski 2012 年 7 月 11 日
So something along the lines of:
x = rand(10,6,8,9);
nd = ndims(x);
c = repmat({':'},nd-1,1);
for ii = 1:nd;
x = shiftdim(x,1);
x = x(3:end-2,c{:});
end
  1 件のコメント
Kerwin
Kerwin 2012 年 7 月 12 日
編集済み: Kerwin 2012 年 7 月 13 日
Definitely better than my solution, thanks!
On second inspection, for large arrays this operation is fairly slow, because shiftdim is quite intensive. I really wish there was a way to use vectors for dimensions.

サインインしてコメントする。

その他の回答 (1 件)

nanren888
nanren888 2012 年 7 月 13 日
編集済み: nanren888 2012 年 7 月 13 日
Sorry I do not know paddarray, so maybe I am answering the wrong question.
I can give you parts of a way to do it. There may be more elegant ways. Indexing any number of dimensions is supported by Matlab's cool mechanism of using cell arrays as parameters;
Short version:
(1) Find the size you want with size & min
(2) Create a cell array of the ranges you want indC = {1:4 1:5 1:6 1:2 ...}
(3) Use < for all cells k > c{k} = c{k}(indC{:});
Longer version:
It seems finding the size you want to crop to is easy, just go through all cells with some sort of min(), eg collect all sizes & use min(?,dim), or manually take minimum values.
Maybe for the indexing, this will help
gg = randn([2 3 4 2]);
szVec = size(gg);
nDim = length(szVec);
.... cropSize = [nDim,1] array of desired dimensions as above
ind = {};
for k = 1:nDim
ind = [ind 1:cropSize(k)]; % I presume you want 1:cropSize
end
smallerGg = gg(ind{:});
Hope it helps
  2 件のコメント
nanren888
nanren888 2012 年 7 月 14 日
編集済み: nanren888 2012 年 7 月 14 日
Yeah, Mine won't suffer to the same extent from the extremely slow moves, I guess.
Maybe you could profile them for us, on a reasonable number of trials?
I guess what you asked for "vectors for dimensions" I did with cells for dimensions.
%% timeMultiDimStuff.m
x = rand(10,6,8,9,5,6,4,5,5);
y = zeros(size(x));
nDim = ndims(x);
cropSize = [8,6,7,3,4,5,3,5,4];
ind = {};
for k = 1:nDim
ind = [ind 1:cropSize(k)];
end
nTrial = 1000;
tic();
for k = 1:nTrial
y = x(ind{:}); %#ok<NASGU>
end
toc();
Run with your solution & compare?
Elapsed time is 5.751869 seconds. (You have to run both on the same machine :))
Kerwin
Kerwin 2012 年 7 月 20 日
sorry for the late reply!
Your solution works very well, I quickly tested it on some arrays, the largest being 4 arrays of each 5 dimensions, with the largest array having approx 40 million elements.
The earlier proposed solution with shiftdim took 9.87 seconds. Your solution took 2.01 seconds, a very nice speed-up! I expect that on my larger arrays this difference will become even more pronounced.
Thanks again!

サインインしてコメントする。

カテゴリ

Help Center および File ExchangeDesign Condition Indicators Interactively についてさらに検索

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by