Reputation: 11
I have a huge 3D matrix and there is a loop. In every iteration, I would like to extract some different parts (for example: 10000) out of it, then the convolution between those part and a patch is calculated.
I know it could easily be done using a loop but it is very time consuming. Is there any alternative solution to work much faster than loop?
Upvotes: 1
Views: 236
Reputation: 3476
Let's suppose you have :
1) A row vector idx
containing the row indexes of the top left corners of your parts.
2) A row vector idy
containing the column indexes of the top left corners of your parts.
3) A row vector idz
containing the indexes along the 3rd coordinate of the left corners of your parts.
We'll first have to create, from idx
, idy
and idz
3 vector containing ALL the indexes of the elements you need to extract from your matrix. Then we'll split the extracted matrix in blocks the same size of your patch using mat2cell
, and then we'll apply the convn
function to each block using cellfun
.
Totidx=bsxfun(@plus,idx,[0:(size(patch,1)-1)]'); \\i-th column of this is the column vector idx(i):(idx(i)+size(patch,1)-1)
Totidx=reshape(Totidx,1,numel(Totidx)); \\ Creates the vector needed containing all indexes along first dimension.
Doing the same for idy
and idz
, we obtain 3 vectors Totidx
, Totidy
, Totidz
containing all indexes needed.
Now we can extract the values from your initial matrix, say A
:
ExtractedA=A(Totidx,Totidy,Totidz);
Apply mat2cell
: NPatch
denotes your number of extracted patches
B=mat2cell(ExtractedA,size(patch,1)*ones(1,NPatch),size(patch,2)*ones(1,NPatch),size(patch,3)*ones(1,NPatch));
Then you can apply your convn
function to every cell of the cell array B
: patch
denotes the patch you want to convolute your extracted parts with
fun=@(M) convn(M,patch,'valid');
out=cellfun(fun,B,'uniformoutput',false);
Every cell of the cell array out
is now one of the output you wanted
Upvotes: 1