How to divide an image into non-overlapping blocks?

30 views (last 30 days)
For block pairing, I need to divide original block and target blocks into non-overlapping blocks.I tried with the function called blockproc(),but it is not suitable for images that i have taken.
% Divide the image up into 4 blocks.
% Let's assume we know the block size and that all blocks will be the same size.
blockSizeR = 128; % Rows in block.
blockSizeC = 128; % Columns in block.
% Figure out the size of each block.
wholeBlockRows = floor(rows / blockSizeR);
wholeBlockCols = floor(columns / blockSizeC);
% Preallocate a 3D image
image3d = zeros(wholeBlockRows, wholeBlockCols, 3);
% Now scan though, getting each block and putting it as a slice of a 3D array.
sliceNumber = 1;
for row = 1 : blockSizeR : rows
for col = 1 : blockSizeC : columns
% Let's be a little explicit here in our variables
% to make it easier to see what's going on.
% Determine starting and ending rows.
row1 = row;
row2 = row1 + blockSizeR - 1;
row2 = min(rows, row2); % Don't let it go outside the image.
% Determine starting and ending columns.
col1 = col;
col2 = col1 + blockSizeC - 1;
col2 = min(columns, col2); % Don't let it go outside the image.
% Extract out the block into a single subimage.
oneBlock = grayImage(row1:row2, col1:col2);
% Specify the location for display of the image.
subplot(2, 2, sliceNumber);
imshow(oneBlock);
% Make the caption the block number.
caption = sprintf('Block #%d of 4', sliceNumber);
title(caption, 'FontSize', fontSize);
drawnow;
% Assign this slice to the image we just extracted.
if (row2-row1+1) == blockSizeR && (col2-col1+1) == blockSizeC
% Then the block size is the tile size,
% so add a slice to our 3D image stack.
image3D(:, :, sliceNumber) = oneBlock;
else
newTileSize = [(row2-row1+1), (col2-col1+1)];
warningMessage = sprintf('Warning: this block size of %d rows and %d columns\ndoes not match
the preset block size of %d rows and %d columns.\nIt will not be added to the 3D image stack.',...
newTileSize(1), newTileSize(2), blockSizeR, blockSizeC);
uiwait(warndlg(warningMessage));
end
sliceNumber = sliceNumber + 1;
end
end
Is there any specific range for blocksizeR and blocksizeC, can I assign different sizes? if I want non overlapping blocks, how these values are connected?

Accepted Answer

Walter Roberson
Walter Roberson on 13 Feb 2017
% Divide the image up into 4 blocks.
% Let's assume we know the block size and that all blocks will be the same size.
% these two values do not need to be the same
blockSizeR = 128; % Rows in block.
blockSizeC = 128; % Columns in block.
% Figure out the size of each block.
wholeBlockRows = floor(rows / blockSizeR);
wholeBlockCols = floor(columns / blockSizeC);
trailing_rows = rows - wholeBlockRows * blockSizeR;
trailing_cols = cols - wholeBlockCols * blockSizeC;
image3d_cell = mat2cell( YourImage, [blockSizeR * ones(1, wholeblockRows), trailing_rows], [blockSizeC * ones(1, wholeBlockCols), trailing_cols], size(YourImage, 3) );
Now image3d_cell will be a cell array, wholeBlockRows or wholeBlockRows+1 (if there are trailing rows), by wholeBlockCols or wholeBlockCols+1 (if there are trailing columns).
if trailing_rows == 0 && trailing_cols == 0
image3d = cat( ndims(YourImage)+1, image3d_cell{:} );
else
image3d = [];
warning('There were trailing rows or columns, could not form 3D image automatically');
end

More Answers (3)

Image Analyst
Image Analyst on 13 Feb 2017
You can try one of the two ways shown in the FAQ: http://matlab.wikia.com/wiki/Split_image_into_blocks

muhamed ibrahim
muhamed ibrahim on 29 Mar 2024 at 21:03
Moved: DGM on 29 Mar 2024 at 22:11
%% dividing the image into 9 non-overlapping patches and store them in a cell array
im=imread('pic.jpg');
imshow(im)
s=size(im,1); % the pic is square and RGB
div=floor(s/3);
patches={}
n=0
k=0
z=0
pathes={}
for i=1:div:div*3
z=z+1;
for j=1:div:div*3
n=n+1;
k=k+1;
patches{n}=im(i:z*div,j:k*div,:);
if k==3
k=0
end
end
end
  2 Comments
DGM
DGM on 29 Mar 2024 at 22:12
This code presumes that the image is square. If a nonsquare image is wide, it will be truncated. If a nonsquare image is tall, it will fail with an error.
muhamed ibrahim
muhamed ibrahim on 29 Mar 2024 at 22:50
Edited: muhamed ibrahim on 29 Mar 2024 at 22:52
Yes you are right. div in both main and nested loops can be changed to adapt to different image dimensions (tall or wide).

Sign in to comment.


DGM
DGM on 29 Mar 2024 at 22:10
This has been asked and answered a bazillion times, so I'll just throw this out there again. If the goal is to subdivide an image, MIMT imdetile() and imtile() make it easy.
inpict = imread('peppers.png'); % any I/IA/RGB/RGBA/RGBAAA image
outstack = imdetile(inpict,[3 3]); % a 4D multiframe image
That's it. One line. Want to put it back together?
outpict = imtile(outstack,[3 3]); % a single-frame image
Bam. Done.
The tiling order and means of resolving divisibility are user-defined, but all tiles always have the same geometry. If the tile geometry is resolved by scaling or truncating, does that mean that the retiled image doesn't have the same geometry as the original? Maybe. See the synopses for MIMT imtile() and maketileable() for an example on how to conditionally correct for the changes made when detiling.
When is MIMT imdetile() not helpful? Imdetile() is meant for subdividing an arbitrary image into an integer 2D tiling. If you're trying to divide an image into blocks of a specific size, imdetile() is probably not the right tool.
Note that due to an unfortunate order of events, MIMT imtile() creates a name conflict with IPT imtile(). They are not the same or remotely interchangeable. I have yet to overturn MIMT in order to resolve it. As far as I'm concerned, IPT imtile() is an afterthought that should have been functionality already present in montage(), and MIMT tools are entirely capable of replacing the functionality anyway.
Man. I'm feelin sassy.

Community Treasure Hunt

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

Start Hunting!