Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

resizing 3D matrix (image) in MATLAB

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?

like image 203
Sam Avatar asked Sep 20 '12 20:09

Sam


People also ask

How do you resize a matrix image in Matlab?

Resize the image, using the imresize function. In this example, you specify a magnification factor. To enlarge an image, specify a magnification factor greater than 1. magnificationFactor = 1.25; J = imresize(I,magnificationFactor);

How do I resize an image in Matlab?

Shrink the image by a factor of two. J = imresize(I, 0.5); Display the original image and the resized image.

How do I resize an image in Matlab without using Imresize?

1 Answer. Show activity on this post. This code is done using nearest neighbor interpolation. %# Initializations: scale = [2 2]; %# The resolution scale factors: [rows columns] oldSize = size(inputImage); %# Get the size of your image newSize = max(floor(scale.


3 Answers

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);
like image 131
Oli Avatar answered Sep 20 '22 16:09

Oli


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
like image 35
chaohuang Avatar answered Sep 20 '22 16:09

chaohuang


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'.

like image 23
nightlyop Avatar answered Sep 20 '22 16:09

nightlyop