How to divide 256X256 matrix into sixteen 16X16 blocks?
30 views (last 30 days)
Show older comments
I am having pixel value of an image as 256X256 matrix. I want to divide it into sixteen 16X16 matrix (ie)an image into sub blocks. It is needed to compare each 16X16 with other. Can anyone help?
1 Comment
Roger Stafford
on 10 Oct 2013
By my arithmetic, if you divide a 256x256 matrix into separate 16x16 blocks, there should be 256 of these blocks, not 16.
Accepted Answer
David Sanchez
on 10 Oct 2013
You need to use mat2cell:
X = reshape(1:20,5,4)'
C = mat2cell(X, [2 2], [3 2])
celldisp(C)
This code returns
X =
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20
C =
[2x3 double] [2x2 double]
[2x3 double] [2x2 double]
C{1,1} =
1 2 3
6 7 8
C{2,1} =
11 12 13
16 17 18
C{1,2} =
4 5
9 10
C{2,2} =
14 15
19 2
In your case:
A = rand(256); % your matrix here
N = 16*ones(1,16);
B = mat2cell(A,N,N);
0 Comments
More Answers (5)
Jacob
on 29 Mar 2023
Edited: Jacob
on 29 Mar 2023
In addition to @DGM's reshape method, here's another that passes through a 4D array instead of staying 3D. I've purposely picked numbers that aren't equal. I've found reshape methods tend to perform about 4–10× faster than mat2cell in my use cases but your results may vary. The ratio between the run times below is usually more similar for smaller values of nRep.
raw_img = imread('cameraman.tif'); % 256x256x1 uint8
raw_img = [raw_img; zeros(16, 256)]; % 272x256x1 (to make non-symmetric)
subX = 8; % number of pixels blocks have in the X/column direction
subY = 16; % number of pixels blocks have in the Y/row direction
nOutR = size(raw_img,1)/subY; % number of output block rows
nOutC = size(raw_img,2)/subX;
nRep = 100; %number of repetitions
tic
for iRep = 1:nRep
outstack_R2 = reshape(raw_img, subY, nOutR, subX, nOutC);
outstack_R2 = permute(outstack_R2, [1,3,4,2]);
outstack_R2 = reshape(outstack_R2, subY, subX, nOutR*nOutC);
end % end of loop over repetitions (for timing estimate)
toc
% Similar mat2cell option
tic
for iRep = 1:nRep
outstack_m2c = mat2cell(raw_img, subY*ones(nOutR,1), subX*ones(nOutC,1));
outstack_m2c = outstack_m2c';
outstack_m2c = outstack_m2c(:);
end % end of loop over repetitions (for timing estimate)
toc
% display the blocks
figure(1);
clf;
montage(outstack_R2,'Size',[nOutR nOutC],'bordersize',[5 5],'backgroundcolor',[1 1 1])
figure(2);
clf;
montage(outstack_m2c,'Size',[nOutR nOutC],'bordersize',[5 5],'backgroundcolor',[1 1 1])
1 Comment
DGM
on 29 Mar 2023
Edited: DGM
on 29 Mar 2023
When I started being active on the forum a couple years ago, I was a bit confused that everyone was suggesting mat2cell() for this sort of thing. In writing MIMT tools, I had always found that rudimentary methods were faster, especially in older versions.
Still, I can see the merit of posting potentially sub-optimal solutions if they can be broadly useful while staying succinct enough to be learnable. That said, I'm still not going to write it that way in MIMT, especially if creating a cell array is not beneficial to the workflow.
P.S. I appreciate that your first answer is formatted, explained, documented, and demonstrated. That's how it's done!
DGM
on 29 Mar 2023
Edited: DGM
on 29 Mar 2023
inpict = imread('cameraman.tif'); % 256x256
% detile the image into a 4D array
outstack = imdetile(inpict,[13 16]);
% display the blocks
montage(outstack,'bordersize',[5 5],'backgroundcolor',[1 1 1])
![](https://www.mathworks.com/matlabcentral/answers/uploaded_files/1339994/image.png)
Note that the image geometry is not integer-divisible by the tiling.
If you had wanted the image to be detiled columnwise, you could to that too.
% detile the image into a 4D array
outstack = imdetile(inpict,[13 16],'direction','col');
% display the blocks
montage(outstack,'bordersize',[5 5],'backgroundcolor',[1 1 1])
![](https://www.mathworks.com/matlabcentral/answers/uploaded_files/1339999/image.png)
... but don't expect montage() or MATLAB imtile() to be able to retile it.
On the other hand, MIMT imtile() is the counterpart to MIMT imdetile(), and they're made to work together.
% detile the image to a multiframe image
tiling = [13 16];
direction = 'row';
outstack = imdetile(inpict,tiling,'direction',direction);
% tile a multiframe image into a single image
outpict = addborder(outstack,1,1,'normalized'); % pad the stack for visualization
outpict = imtile(outpict,tiling,'direction',direction);
imshow(outpict)
![](https://www.mathworks.com/matlabcentral/answers/uploaded_files/1340004/image.png)
For better or worse, imdetile() does the task using boring old loops and direct subscript addressing.
Are there disadvantages to using imdetile() and imtile()? Yes. Obviously, being part of a third-party toolbox and relying on a number of components of that toolbox is a burden to recommendation. The fact that TMW decided to create imtile() instead of adding export functionality to montage() results in a name conflict with MIMT imtile(), so that's an unfortunate inconvenience. In cases where it's desired to create fixed-geometry tiles, imdetile is more cumbersome than in the case where it's desired to subdivide the image into an integer tiling.
A lot of MIMT tools are designed around being convenient to use in an ad-hoc manner; to that end, there are often bits of elegance that get sacrificed.
0 Comments
Namwon Kim
on 26 Aug 2019
x = zeros(256,256) % Input is (256,256).
a = size(x, 1);
b = size(x, 2);
numParts = 16
c = floor(a/numParts);
d = rem(a, numParts);
partition_a = ones(1, numParts)*c;
partition_a(1:d) = partition_a(1:d)+1;
e = floor(b/numParts);
f = rem(b, numParts);
partition_b = ones(1, numParts)*e;
partition_b(1:f) = partition_b(1:f)+1;
% Split matrix rows into partition, storing result in a cell array
% 256X256 matrix into sixteen 16X16 blocks
output = mat2cell(x, partition_a, partition_b);
0 Comments
AMEN BARGEES
on 18 Jul 2022
x=your input marrix
ans= reshape(x,16,16,[]);
1 Comment
DGM
on 22 Feb 2023
Edited: DGM
on 22 Feb 2023
That doesn't actually do what's required.
x = imread('cameraman.tif'); % 256x256x1 uint8
outstack = reshape(x,16,16,[]); % don't use 'ans' as a variable name!
% display the blocks
% i'm going to add some padding so that the block boundaries are clear
montage(outstack,'bordersize',[5 5],'backgroundcolor',[1 1 1])
FWIW, this is one way to do it with reshape():
x = imread('cameraman.tif'); % 256x256x1 uint8
outstack = reshape(x.',[],16,16);
outstack = permute(outstack,[2 1 3]);
outstack = reshape(outstack,16,16,[]);
% display the blocks
montage(outstack,'bordersize',[5 5],'backgroundcolor',[1 1 1])
See Also
Categories
Find more on Image Data Workflows in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!