# How to create 2D sub arrays by sampling every n by n points

5 views (last 30 days)
Yiwu Ding on 10 Dec 2019
Commented: Adam Danz on 12 Dec 2019
Hi, I want to create 2D sub arrays by sampling every n by n points. Specifically, I have an array with size of 280x280. I want to sample every 8 by 8 points and form a 3D array with size of (35,35,64).
Currently I am using loop (refer to below) which takes abut 0.25msec on my Laptop. I am wondering if there is a more elegent and faster way to create the 3D array by taking advantage of matlab internal indexing capability.
Thank you!
%%%%%
%A=rand(280,280);
A = A(1:1:280,1:1:280)/256;
B=zeros(35,35,64);
numIter=1000;
tic
for iter=1:numIter
for i=1:1:8
for j=1:1:8
indx1=(i-1)*8+j;
B(:,:,indx1)=A(i:8:end,j:8:end);
end
end
end
disp(toc/numIter);
figure(1); montage(B);
%%%%%%%%%%%%%%%%%%%%%%%%%%

Yiwu Ding on 10 Dec 2019
Referring to the following updated code, was able to improve the code speed from 0.25msec to 0.14msec by using the vector indexing.
Note iter of 1000 is used to get more accurate timing for single run.
Plots are used for data verification.
close all;
clear;
%A=rand(280,280);
A = A(1:1:280,1:1:280)/256;
B=zeros(35,35,64);
%%%%Approach#1 iteration
numIter=1000;
tic
for iter=1:numIter
for i=1:1:8
for j=1:1:8
indx1=(i-1)*8+j;
B(:,:,indx1)=A(i:8:end,j:8:end);
end
end
end
toc
disp('Approach#1 time: single iter')
disp(toc/numIter);
figure(1); montage(B);
%%%%%%%%%%%%%%%%%%%%%
%%%%Approach#2 vector indexing
tic
for iter=1:numIter
rngY=1:280;
rngY_permute=reshape(rngY,8,35);
rngY_permute=rngY_permute';
B1=A(rngY_permute,rngY_permute);
B2=reshape(B1,35,8,35,8);
B3=permute(B2,[1,3,4,2]);
B4=reshape(B3,35,35,64);
end
toc
disp('Approach#2 time: single iter')
disp(toc/numIter);
figure(2); montage(B4);
figure(3); montage(B4-B); title('\Delta');
max(max(max(abs(B4-B))))

#### 1 Comment

Adam Danz on 12 Dec 2019
You're adding the iter-loop just to add extra time to your computation for whatever reason. There are much better ways to building in time if you need to add delays.
You could use a timer function or the pause() command. Both offer much better control over timing and much less computational cost than this "Approach #2" .
This is not a good solution to your problem.

Ridwan Alam on 10 Dec 2019
B = reshape(A,35,35,[]);

Adam Danz on 10 Dec 2019
The indexing isn't consecutive, though.
B(:,:,indx1)=A(i:8:end,j:8:end);
Adam Danz on 10 Dec 2019
B = permute(A,dimorder) rearranges the dimensions of A. The loop in the OP's code is extracting every 8 rows and every 8 columns so it's not clear to me how permute() would help.

Adam Danz on 10 Dec 2019
Edited: Adam Danz on 10 Dec 2019
The iter-loop is completely unnecessary and is merely doing the same exact work 1000 times.
numIter=1000;
tic
% for iter=1:numIter Remove this line
for i=1:1:8
for j=1:1:8
indx1=(i-1)*8+j;
B(:,:,indx1)=A(i:8:end,j:8:end);
end
end
% end Remove this line
Removing that reduces the processing time to 0.000047 sec. Since you're indexing non-consecutively, the loop method (without the iter-loop) will be quite fast and I doubt an ugly vectorized approach will be faster.

R2019a

### Community Treasure Hunt

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

Start Hunting!

Translated by