沿任意方向获取体积数据集的切片

时间:2014-12-28 17:21:16

标签: matlab rotation geometry

我有一个整数值的3D数组和一个方向向量。我希望能够沿着这个向量选择X切片,方向是切片器看的方向(也就是说,切片的X和Y坐标是方向向量的两个法线,垂直于每个其他)。

我有以下解决方案,但结果显示在方向向量的Y轴上预期的90度偏移,我无法弄清楚原因。

%Get "up" and "right" direction vectors
up = get_rotated_direction(direction, 90,0,0);
right = get_rotated_direction(direction, 0,90,0);

z = 0;

for i=1:zStep:zCount
    z = z +1;
    %Slicer follows a path denoted by "points"
    point = points(i,:);

    %topLeft holds the coordinates in the data volume of the point at [X=0,Y=0] in the slice.
    topLeft = point - right * width / 2 - up * height / 2;

    for x=1:width
        for y=1:height
            offsetPoint = round(topLeft + up*y+ right*x);
            result(x,y,z) = data(offsetPoint(1),offsetPoint(2),offsetPoint(3));
        end
    end
end

结果是一个有效的图像,但方向错误,所以我认为问题在于get_rotated_direction或我对它的调用,但是在测试时使用单位向量[0,0,1],[ 0,1,0]和[1,0,0]结果似乎是正确的。

get_rotated_direction看起来像这样:

function result = get_rotated_direction (direction, x_angle,y_angle,z_angle)
    %get the rotation from origin to direction
    rot = vrrotvec([0,0,1],direction);

    %Turn this into a quaternion
    rotquat = angle2quat(rot(1)*rot(4),rot(2)*rot(4),rot(3)*rot(4),'XYZ');

    %get the angles in radians
    x_angle = deg2rad(x_angle);
    y_angle = deg2rad(y_angle);
    z_angle = deg2rad(z_angle);

    %Create the desired rotation from the origin
    desiredRot = angle2quat(x_angle,y_angle,z_angle,'XYZ');

    %Rotate the origin to our desired rotation
    %Then rotate that by the rotation from origin to our direction
    %This should produce a direction that has been locally rotated.
    direction= quatrotate(rotquat,quatrotate(desiredRot,[0,0,1]));

    %Normalize the direction and return
    result = direction/norm(direction);
end

1 个答案:

答案 0 :(得分:1)

使用转换矩阵,这是一种更通用的方法。我遇到了类似的问题并使用了this回答,我试图将其推广到下面的3D案例中:

%example data
load mri; olddata = squeeze(D);
phi = 90; theta = 90; psi = 0;
r = [phi, theta, psi]; r = r*(pi/180);
dims = size(olddata);
p0 = [round(dims(1)/2);round(dims(2)/2);round(dims(3)/2)]; %image center

%I assume that spacing between points is equal in all three dimensions
Rx=[1 0 0 0;
    0 cos(r(1)) sin(r(1)) 0;
    0 -sin(r(1)) cos(r(1)) 0;
    0 0 0 1];
Ry=[cos(r(2)) 0 -sin(r(2)) 0;
    0 1 0 0;
    sin(r(2)) 0 cos(r(2)) 0;
    0 0 0 1];
Rz=[cos(r(3)) sin(r(3)) 0 0;
    -sin(r(3)) cos(r(3)) 0 0;
    0 0 1 0;
    0 0 0 1];
R = Rz*Ry*Rx;
%make affine matrix to rotate about center of image instead of origin
T = ( eye(3)-R(1:3,1:3) ) * p0(1:3);
A = R;
A(1:3,4) = T;
Rold2new = A;
Rnew2old = inv(Rold2new);

%this is the transformation
%I assume you want a volume with the same dimensions as your old volume
[xx yy zz] = meshgrid(1:dims(1),1:dims(2),1:dims(3));
coordinates_axes_new = [xx(:)';yy(:)';zz(:)'; ones(size(zz(:)))']; % the coordinates you want to find a value for
coordinates_axes_old = Rnew2old*coordinates_axes_new; % the coordinates where you can find those values
Xcoordinates = reshape(coordinates_axes_old(1,:), dims(1), dims(2), dims(3));
Ycoordinates = reshape(coordinates_axes_old(2,:), dims(1), dims(2), dims(3));
Zcoordinates = reshape(coordinates_axes_old(3,:), dims(1), dims(2), dims(3));

%this is where you get the values for your new coordinates
method = 'nearest'; %you have integers only so you probably want the nearest neighbour?
newdata = interp3(olddata, Xcoordinates, Ycoordinates, Zcoordinates, method);
figure; subplot(1,2,1); imshow(olddata(:,:,13), []); title('original'); subplot(1,2,2); imshow(newdata(:,:,13), []); title('rotated')

导致此次轮换:

original and rotated image