I have a 3D matrix (MxNxK) and want to resize it to (M'xN'xK') (like imresize in matlab). I am using image pyramid, but its result is not very accurate and need a better one. Any solution?
Asked
Active
Viewed 1.6k times
16
-
What is the difference between `M` and `M'`? The dimensions are supposed to be scalars. Ah, I see, these are not transpose operators – Serg Sep 20 '12 at 21:16
-
@ Serg: there is no relationship, M' is just the smaller dimension which we want. – Sam Sep 20 '12 at 21:18
-
How would you like to resize it? Nearest Neighbor? Bilinear? Bi-Cubic? – Andrey Rubshtein Sep 20 '12 at 21:59
-
@ Andrey: The best method which can do it. Because the accuracy for me is very important. – Sam Sep 20 '12 at 22:39
-
you can dig into matlab's `imresize` and tweak it to do the resizing along all three dimensions. – Shai Jul 09 '14 at 10:57
-
@Sam , consider accepting any of the answers if they helped you ;) – Ander Biguri Oct 06 '15 at 17:01
3 Answers
9
You could use interp3
(since you want to interpolate 3D data):
im=rand(2,3,4); %% input image
ny=3;nx=3;nz=5; %% desired output dimensions
[y x z]=...
ndgrid(linspace(1,size(im,1),ny),...
linspace(1,size(im,2),nx),...
linspace(1,size(im,3),nz));
imOut=interp3(im,x,y,z);

Ander Biguri
- 35,140
- 11
- 74
- 120

Oli
- 15,935
- 7
- 50
- 66
-
@ Oli: it can be use for shrinking a matrix? making a matrix to be smaller – Sam Sep 20 '12 at 22:35
-
-
I guess I mixed up the indices a bit. Look at the case 3 of chaohuang's answer for a better solution. – Oli Sep 21 '12 at 17:07
8
Here is the resize
function we are using in the kWave toolbox.
function mat_rs = resize(varargin)
%RESIZE Resize a matrix.
% DESCRIPTION:
% Resize a matrix to a given size using interp2 (2D) or interp3
% (3D).
% Use interpolation to redivide the [0,1] interval into Nx, Ny, Nz
% voxels, where 0 is the center of first voxel, and 1 is the center
% of the last one.
%
% USAGE:
% mat_rs = resize(mat, new_size)
% mat_rs = resize(mat, new_size, interp_mode)
%
% INPUTS:
% mat - matrix to resize
% new_size - desired matrix size in elements given by [Nx, Ny] in
% 2D and [Nx, Ny, Nz] in 3D. Here Nx is the number of
% elements in the row direction, Ny is the number of
% elements in the column direction, and Nz is the
% number of elements in the depth direction.
%
% OPTIONAL INPUTS:
% interp_mode - interpolation mode used by interp2 and interp3
% (default = '*linear')
%
% OUTPUTS:
% mat_rs - resized matrix
% check the inputs for release B.0.2 compatability
if length(varargin{2}) == 1 && nargin >= 3 && length(varargin{3}) == 1
% display warning message
disp('WARNING: input usage deprecated, please see documentation.');
disp('In future releases this usage will no longer be functional.');
% recursively call resize with the correct inputs
if nargin == 3
mat_rs = resize(varargin{1}, [varargin{2}, varargin{3}]);
else
mat_rs = resize(varargin{1}, [varargin{2}, varargin{3}], varargin{4});
end
return
end
% update command line status
disp('Resizing matrix...');
% assign the matrix input
mat = varargin{1};
% check for interpolation mode input
if nargin == 2
interp_mode = '*linear';
elseif nargin ~= 3
error('incorrect number of inputs');
else
interp_mode = varargin{3};
end
% check inputs
if numDim(mat) ~= length(varargin{2})
error('resolution input must have the same number of elements as data dimensions');
end
switch numDim(mat)
case 2
% extract the original number of pixels from the size of the matrix
[Nx_input, Ny_input] = size(mat);
% extract the desired number of pixels
Nx_output = varargin{2}(1);
Ny_output = varargin{2}(2);
% update command line status
disp([' input grid size: ' num2str(Nx_input) ' by ' num2str(Ny_input) ' elements']);
disp([' output grid size: ' num2str(Nx_output) ' by ' num2str(Ny_output) ' elements']);
% check the size is different to the input size
if Nx_input ~= Nx_output || Ny_input ~= Ny_output
% resize the input matrix to the desired number of pixels
mat_rs = interp2(0:1/(Ny_input - 1):1, (0:1/(Nx_input - 1):1)', mat, 0:1/(Ny_output - 1):1, (0:1/(Nx_output - 1):1)', interp_mode);
else
mat_rs = mat;
end
case 3
% extract the original number of pixels from the size of the matrix
[Nx_input, Ny_input, Nz_input] = size(mat);
% extract the desired number of pixels
Nx_output = varargin{2}(1);
Ny_output = varargin{2}(2);
Nz_output = varargin{2}(3);
% update command line status
disp([' input grid size: ' num2str(Nx_input) ' by ' num2str(Ny_input) ' by ' num2str(Nz_input) ' elements']);
disp([' output grid size: ' num2str(Nx_output) ' by ' num2str(Ny_output) ' by ' num2str(Nz_output) ' elements']);
% create normalised plaid grids of current discretisation
[x_mat, y_mat, z_mat] = ndgrid((0:Nx_input-1)/(Nx_input-1), (0:Ny_input-1)/(Ny_input-1), (0:Nz_input-1)/(Nz_input-1));
% create plaid grids of desired discretisation
[x_mat_interp, y_mat_interp, z_mat_interp] = ndgrid((0:Nx_output-1)/(Nx_output-1), (0:Ny_output-1)/(Ny_output-1), (0:Nz_output-1)/(Nz_output-1));
% compute interpolation; for a matrix indexed as [M, N, P], the
% axis variables must be given in the order N, M, P
mat_rs = interp3(y_mat, x_mat, z_mat, mat, y_mat_interp, x_mat_interp, z_mat_interp, interp_mode);
otherwise
error('input matrix must be 2 or 3 dimensional');
end

chaohuang
- 3,965
- 4
- 27
- 35
-
@ Chaohung: I am not familiar with this toolbox, it can work with 3D matrix to resize it to a smaller one? which function of this toolbox should be added to matlab? – Sam Sep 20 '12 at 22:37
-
1Thanks for sharing this! I believe `numDim(.)` in the input sanity checks is not a standard matlab function. However it can be replaced with `ndims(.)`. After that the code worked perfectly. Cheers! – Chrigi Aug 16 '13 at 20:28
-
when `[x_mat, y_mat, z_mat]` is defined, it seems that the grid is created from `0`, shouldn't be created from `1` instead? – Manolete Jul 16 '14 at 13:35
8
Look at the example Exploring Slices from a 3-Dimensional MRI Data Set in the Image Processing Toolbox. It looks more complicated than it actually is. You also can choose the interpolation method easily when working according to this example. To resize a volume isotrope by x
, you'd have to use something like (I didn't test it):
T = maketform('affine',[x 0 0; 0 x 0; 0 0 x; 0 0 0;]);
R = makeresampler({'cubic','cubic','cubic'},'fill');
ImageScaled = tformarray(Image,T,R,[1 2 3],[1 2 3], round(size(Image)*x),[],0);
If you're working with binary images/volumes it might be better to change the 'cubic' interpolation to 'nearest'.

nightlyop
- 7,675
- 5
- 27
- 36
-
Actually this is the only technically correct answer in here. The rest of the answers will always have `out(1,1,1)==in(1,1,1)` and that is not the correct way of resizing, as the border pixels are given more importance than the mid pixels. – Ander Biguri Oct 09 '17 at 10:56