【问题标题】:resizing 3D matrix (image) in MATLAB在 MATLAB 中调整 3D 矩阵(图像)的大小
【发布时间】:2012-09-13 06:19:43
【问题描述】:

我有一个 3D 矩阵 (MxNxK) 并想将其调整为 (M'xN'xK')(就像 matlab 中的 imresize)。 我正在使用图像金字塔,但它的结果不是很准确,需要一个更好的。有什么解决办法吗?

【问题讨论】:

  • MM' 有什么区别?尺寸应该是标量。啊,我明白了,这些不是转置运算符
  • @Serg:没有关系,M'只是我们想要的更小的维度。
  • 您想如何调整它的大小?最近的邻居?双线性?双立方?
  • @Andrey:能做到的最好的方法。因为准确性对我来说非常重要。
  • 您可以深入研究 matlab 的 imresize 并对其进行调整以沿所有三个维度调整大小。

标签: matlab image-processing signal-processing 3d-modelling multidimensional-array


【解决方案1】:

您可以使用interp3(因为您想插入 3D 数据):

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);

【讨论】:

  • @Oli: 可以用来缩小矩阵吗?使矩阵更小
  • @Oli:但它会在边缘产生一些 NaN 值!!我怎么了?
  • 我想我有点混淆了索引。看看超黄回答的案例3,有更好的解决办法。
【解决方案2】:

这是我们在kWave 工具箱中使用的resize 函数。

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

【讨论】:

  • @Chaohung:这个工具箱我不熟悉,它可以和3D矩阵一起变小吗? matlab应该增加这个工具箱的哪个功能?
  • 感谢分享!我相信输入完整性检查中的numDim(.) 不是标准的matlab 函数。但是它可以替换为ndims(.)。之后,代码完美运行。干杯!
  • 在定义[x_mat, y_mat, z_mat]的时候,好像grid是从0创建的,不应该是从1创建的吧?
【解决方案3】:

查看图像处理工具箱中的示例Exploring Slices from a 3-Dimensional MRI Data Set。它看起来比实际上更复杂。当按照这个例子工作时,你也可以很容易地选择插值方法。要通过x 调整体积各向同性,您必须使用类似的东西(我没有测试它):

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);

如果您使用二进制图像/体积,最好将“三次”插值更改为“最近”。

【讨论】:

  • 实际上这是这里唯一在技术上正确的答案。其余的答案总是有out(1,1,1)==in(1,1,1),这不是调整大小的正确方法,因为边框像素比中间像素更重要。
猜你喜欢
  • 1970-01-01
  • 2010-10-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多