📄 xform_nii.m
字号:
affine_transform = 1;
% NIFTI can have both sform and qform transform. This program
% will check sform_code prior to qform_code by default.
%
% If user specifys "preferredForm", user can then choose the
% priority. - Jeff
%
useForm=[]; % Jeff
if isequal(preferredForm,'S')
if isequal(hdr.hist.sform_code,0)
error('User requires sform, sform not set in header');
else
useForm='s';
end
end % Jeff
if isequal(preferredForm,'Q')
if isequal(hdr.hist.qform_code,0)
error('User requires sform, sform not set in header');
else
useForm='q';
end
end % Jeff
if isequal(preferredForm,'s')
if hdr.hist.sform_code > 0
useForm='s';
elseif hdr.hist.qform_code > 0
useForm='q';
end
end % Jeff
if isequal(preferredForm,'q')
if hdr.hist.qform_code > 0
useForm='q';
elseif hdr.hist.sform_code > 0
useForm='s';
end
end % Jeff
if isequal(useForm,'s')
R = [hdr.hist.srow_x(1:3)
hdr.hist.srow_y(1:3)
hdr.hist.srow_z(1:3)];
T = [hdr.hist.srow_x(4)
hdr.hist.srow_y(4)
hdr.hist.srow_z(4)];
if det(R) == 0 | ~isequal(R(find(R)), sum(R)')
hdr.hist.old_affine = [ [R;[0 0 0]] [T;1] ];
R_sort = sort(abs(R(:)));
R( find( abs(R) < tolerance*min(R_sort(end-2:end)) ) ) = 0;
hdr.hist.new_affine = [ [R;[0 0 0]] [T;1] ];
if det(R) == 0 | ~isequal(R(find(R)), sum(R)')
msg = [char(10) char(10) ' Non-orthogonal rotation or shearing '];
msg = [msg 'found inside the affine matrix' char(10)];
msg = [msg ' in this NIfTI file. You have 3 options:' char(10) char(10)];
msg = [msg ' 1. Using included ''reslice_nii.m'' program to reslice the NIfTI' char(10)];
msg = [msg ' file. I strongly recommand this, because it will not cause' char(10)];
msg = [msg ' negative effect, as long as you remember not to do slice' char(10)];
msg = [msg ' time correction after using ''reslice_nii.m''.' char(10) char(10)];
msg = [msg ' 2. Using included ''load_untouch_nii.m'' program to load image' char(10)];
msg = [msg ' without applying any affine geometric transformation or' char(10)];
msg = [msg ' voxel intensity scaling. This is only for people who want' char(10)];
msg = [msg ' to do some image processing regardless of image orientation' char(10)];
msg = [msg ' and to save data back with the same NIfTI header.' char(10) char(10)];
msg = [msg ' 3. Increasing the tolerance to allow more distortion in loaded' char(10)];
msg = [msg ' image, but I don''t suggest this.' char(10) char(10)];
msg = [msg ' To get help, please type:' char(10) char(10) ' help reslice_nii.m' char(10)];
msg = [msg ' help load_untouch_nii.m' char(10) ' help load_nii.m'];
error(msg);
end
end
elseif isequal(useForm,'q')
b = hdr.hist.quatern_b;
c = hdr.hist.quatern_c;
d = hdr.hist.quatern_d;
if 1.0-(b*b+c*c+d*d) < 0
if abs(1.0-(b*b+c*c+d*d)) < 1e-5
a = 0;
else
error('Incorrect quaternion values in this NIFTI data.');
end
else
a = sqrt(1.0-(b*b+c*c+d*d));
end
qfac = hdr.dime.pixdim(1);
i = hdr.dime.pixdim(2);
j = hdr.dime.pixdim(3);
k = qfac * hdr.dime.pixdim(4);
R = [a*a+b*b-c*c-d*d 2*b*c-2*a*d 2*b*d+2*a*c
2*b*c+2*a*d a*a+c*c-b*b-d*d 2*c*d-2*a*b
2*b*d-2*a*c 2*c*d+2*a*b a*a+d*d-c*c-b*b];
T = [hdr.hist.qoffset_x
hdr.hist.qoffset_y
hdr.hist.qoffset_z];
% qforms are expected to generate rotation matrices R which are
% det(R) = 1; we'll make sure that happens.
%
% now we make the same checks as were done above for sform data
% BUT we do it on a transform that is in terms of voxels not mm;
% after we figure out the angles and squash them to closest
% rectilinear direction. After that, the voxel sizes are then
% added.
%
% This part is modified by Jeff Gunter.
%
if det(R) == 0 | ~isequal(R(find(R)), sum(R)')
% det(R) == 0 is not a common trigger for this ---
% R(find(R)) is a list of non-zero elements in R; if that
% is straight (not oblique) then it should be the same as
% columnwise summation. Could just as well have checked the
% lengths of R(find(R)) and sum(R)' (which should be 3)
%
hdr.hist.old_affine = [ [R * diag([i j k]);[0 0 0]] [T;1] ];
R_sort = sort(abs(R(:)));
R( find( abs(R) < tolerance*min(R_sort(end-2:end)) ) ) = 0;
R = R * diag([i j k]);
hdr.hist.new_affine = [ [R;[0 0 0]] [T;1] ];
if det(R) == 0 | ~isequal(R(find(R)), sum(R)')
msg = [char(10) char(10) ' Non-orthogonal rotation or shearing '];
msg = [msg 'found inside the affine matrix' char(10)];
msg = [msg ' in this NIfTI file. You have 3 options:' char(10) char(10)];
msg = [msg ' 1. Using included ''reslice_nii.m'' program to reslice the NIfTI' char(10)];
msg = [msg ' file. I strongly recommand this, because it will not cause' char(10)];
msg = [msg ' negative effect, as long as you remember not to do slice' char(10)];
msg = [msg ' time correction after using ''reslice_nii.m''.' char(10) char(10)];
msg = [msg ' 2. Using included ''load_untouch_nii.m'' program to load image' char(10)];
msg = [msg ' without applying any affine geometric transformation or' char(10)];
msg = [msg ' voxel intensity scaling. This is only for people who want' char(10)];
msg = [msg ' to do some image processing regardless of image orientation' char(10)];
msg = [msg ' and to save data back with the same NIfTI header.' char(10) char(10)];
msg = [msg ' 3. Increasing the tolerance to allow more distortion in loaded' char(10)];
msg = [msg ' image, but I don''t suggest this.' char(10) char(10)];
msg = [msg ' To get help, please type:' char(10) char(10) ' help reslice_nii.m' char(10)];
msg = [msg ' help load_untouch_nii.m' char(10) ' help load_nii.m'];
error(msg);
end
else
R = R * diag([i j k]);
end % 1st det(R)
else
affine_transform = 0; % no sform or qform transform
end
if affine_transform == 1
voxel_size = abs(sum(R,1));
inv_R = inv(R);
originator = inv_R*(-T)+1;
orient = get_orient(inv_R);
% modify pixdim and originator
%
hdr.dime.pixdim(2:4) = voxel_size;
hdr.hist.originator(1:3) = originator;
% set sform or qform to non-use, because they have been
% applied in xform_nii
%
hdr.hist.qform_code = 0;
hdr.hist.sform_code = 0;
end
% apply space_unit to pixdim if not 1 (mm)
%
space_unit = get_units(hdr);
if space_unit ~= 1
hdr.dime.pixdim(2:4) = hdr.dime.pixdim(2:4) * space_unit;
% set space_unit of xyzt_units to millimeter, because
% voxel_size has been re-scaled
%
hdr.dime.xyzt_units = char(bitset(hdr.dime.xyzt_units,1,0));
hdr.dime.xyzt_units = char(bitset(hdr.dime.xyzt_units,2,1));
hdr.dime.xyzt_units = char(bitset(hdr.dime.xyzt_units,3,0));
end
return; % change_hdr
%-----------------------------------------------------------------------
function orient = get_orient(R)
orient = [];
for i = 1:3
switch find(R(i,:)) * sign(sum(R(i,:)))
case 1
orient = [orient 1]; % Left to Right
case 2
orient = [orient 2]; % Posterior to Anterior
case 3
orient = [orient 3]; % Inferior to Superior
case -1
orient = [orient 4]; % Right to Left
case -2
orient = [orient 5]; % Anterior to Posterior
case -3
orient = [orient 6]; % Superior to Inferior
end
end
return; % get_orient
%-----------------------------------------------------------------------
function [space_unit, time_unit] = get_units(hdr)
switch bitand(hdr.dime.xyzt_units, 7) % mask with 0x07
case 1
space_unit = 1e+3; % meter, m
case 3
space_unit = 1e-3; % micrometer, um
otherwise
space_unit = 1; % millimeter, mm
end
switch bitand(hdr.dime.xyzt_units, 56) % mask with 0x38
case 16
time_unit = 1e-3; % millisecond, ms
case 24
time_unit = 1e-6; % microsecond, us
otherwise
time_unit = 1; % second, s
end
return; % get_units
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -