Home > bioelectromagnetism > avw_homogeneity_correction.m

avw_homogeneity_correction

PURPOSE ^

avw_homogeneity_correction - 2D correction of MRI RF nonuniformity

SYNOPSIS ^

function avw = avw_homogeneity_correction(avw,threshold)

DESCRIPTION ^

 avw_homogeneity_correction - 2D correction of MRI RF nonuniformity
 
 avw = avw_homogeneity_correction(avw,[threshold])

 threshold - optional integer, lower intensity of volume
             for high-pass cutoff (default = 5),
             assumes T1 weighted volume
 
    a) fills in holes with the average intensity
   b) generates a low frequency background image 
   c) calculates a correction factor

 The algorithm was designed for correction of 2D slices.  
 It was adapted to iterate over slices in a 3D volume.  
 This is not an ideal solution. Most 3D cerebral MRI 
 volumes have RF inhomogeneity in the sagittal 
 direction (patient inferior to superior).  This function
 has been adapted here to work in this plane, given an
 input avw data struct from the mri_toolbox.  However,
 a better solution should work in 3D.
 This function is also severely limited by only handling
 volumes with even numbered slices.  If possible, it will
 be replaced with a better 3D function at some stage.  I
 advise, from limited experience, to use some other tools
 for this purpose (see the FSL tools, ie, FAST).

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SOURCE CODE ^

0001 function avw = avw_homogeneity_correction(avw,threshold)
0002 
0003 % avw_homogeneity_correction - 2D correction of MRI RF nonuniformity
0004 %
0005 % avw = avw_homogeneity_correction(avw,[threshold])
0006 %
0007 % threshold - optional integer, lower intensity of volume
0008 %             for high-pass cutoff (default = 5),
0009 %             assumes T1 weighted volume
0010 %
0011 %    a) fills in holes with the average intensity
0012 %   b) generates a low frequency background image
0013 %   c) calculates a correction factor
0014 %
0015 % The algorithm was designed for correction of 2D slices.
0016 % It was adapted to iterate over slices in a 3D volume.
0017 % This is not an ideal solution. Most 3D cerebral MRI
0018 % volumes have RF inhomogeneity in the sagittal
0019 % direction (patient inferior to superior).  This function
0020 % has been adapted here to work in this plane, given an
0021 % input avw data struct from the mri_toolbox.  However,
0022 % a better solution should work in 3D.
0023 % This function is also severely limited by only handling
0024 % volumes with even numbered slices.  If possible, it will
0025 % be replaced with a better 3D function at some stage.  I
0026 % advise, from limited experience, to use some other tools
0027 % for this purpose (see the FSL tools, ie, FAST).
0028 %
0029 
0030 % $Revision: 1.1 $ $Date: 2004/11/12 01:30:25 $
0031 
0032 % Licence:  GNU GPL, no express or implied warranties
0033 % History:  homocor.m  rev 0    4/8/00              Gary Glover
0034 %           @(#)vol_homocor.m    1.10  Kalina Christoff    2000-05-29
0035 %                    - see Kalina's comments at the end of this function
0036 %           07/2003, Darren.Weber_at_radiology.ucsf.edu
0037 %                    - adapting to mri_toolbox
0038 %
0039 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
0040 
0041 
0042 version = '[$Revision: 1.1 $]';
0043 fprintf('\nAVW_HOMOGENEITY_CORRECTION [v%s]\n',version(12:16));  tic;
0044 
0045 
0046 
0047 % This algorithm generates a low freq guassian matrix
0048 % in such a way that it requires a square matrix (see below),
0049 % so this function assumes there is a square in-plane slice
0050 % matrix in the input avw.img file (most MRI is square in
0051 % the in-plane acquisition slices).  Hence, it first
0052 % tries to identify the in-plane acquisition orientation.
0053 % There may be better ways to generate a low freq guassian
0054 % matrix (?).  [DLWeber]
0055 
0056 
0057 xdim = double(avw.hdr.dime.dim(2));
0058 ydim = double(avw.hdr.dime.dim(3));
0059 zdim = double(avw.hdr.dime.dim(4));
0060 
0061 % guess the slice acquisition orientation
0062 % eg. avw.hdr.dime.dim=[4 256 256 124 1 0 0 0]
0063 % the inplane dims are the same in the axial plane
0064 % --------------------------------------------------
0065 
0066 if     xdim == ydim,
0067     orientation='axial';
0068     inplane_index=[1 2]; slice_index=3;
0069     
0070 elseif ydim == zdim,
0071     orientation='sagittal';
0072     inplane_index=[2 3]; slice_index=1;
0073     
0074 elseif xdim == zdim,
0075     orientation='coronal'; 
0076     inplane_index=[1 3]; slice_index=2;
0077 end
0078 
0079 fprintf('...assuming the slices were acquired in %s orientation\n', orientation);
0080 
0081 
0082 
0083 if ~exist('threshold','var'),
0084     threshold = 5;
0085 elseif isempty(threshold),
0086     threshold = 5;
0087 end;
0088 threshold = threshold * .01;
0089 
0090 
0091 npix = size(avw.img,inplane_index(1));
0092 npixHalf = npix/2;
0093 
0094 if mod(npix,2) == 0,
0095     %OK
0096 else,
0097     slices = npix
0098     error('sorry, this simple function can only handle even numbered slices.')
0099 end
0100 
0101 fprintf('...please wait - processing slice    ');
0102 
0103 % begin looping through slices
0104 % ----------------------------
0105 for slice = 1:size(avw.img,slice_index);
0106     
0107     if     slice<10,   fprintf('\b%d',slice); 
0108     elseif slice<100,  fprintf('\b\b%d',slice); 
0109     elseif slice<1000, fprintf('\b\b\b%d',slice);
0110     end
0111     
0112     % squeeze out the singleton dimensions for coronal and sagittal
0113     if slice_index==1; img=squeeze(avw.img(slice,:,:)); end;  
0114     if slice_index==2; img=squeeze(avw.img(:,slice,:)); end;
0115     if slice_index==3; img=squeeze(avw.img(:,:,slice)); end;
0116     
0117     intensityMax = max(max(img));
0118     intensityThreshold = intensityMax*threshold;
0119     
0120     % fill in holes with image average intensity
0121     
0122     imgThresholdMask = (img > intensityThreshold);
0123     imgThresholdMaskSum = sum(sum(imgThresholdMask));
0124     
0125     imgMasked = img .* imgThresholdMask;
0126     imgAverage = sum(sum(imgMasked))/imgThresholdMaskSum;
0127     imgFilled = imgMasked + (1 - imgThresholdMask) .* imgAverage;
0128     
0129     %  make low freq image
0130     
0131     z = fftshift(fft2(imgFilled));
0132     
0133     
0134     a2 = 1/(npixHalf/8);
0135     y2 = (1:npixHalf).^2;  % use 15 as default win for guassian
0136     
0137     for x = 1:npixHalf,
0138         r2 = y2 + x*x;
0139         win1(x,:) = exp(-a2*r2);
0140     end
0141     
0142     % allocate win1 to 4 quadrants of win
0143     win(npixHalf+1:npix,npixHalf+1:npix) = win1;
0144     win(npixHalf+1:npix,npixHalf:-1:1) = win1;
0145     win(1:npixHalf,:) = win(npix:-1:npixHalf+1,:);
0146     
0147     zl = win.*z;
0148     
0149     imgLowFreq = abs(ifft2(fftshift(zl)));
0150     
0151     % image correction
0152     
0153     imgLowFreqAverage = sum(sum(imgLowFreq.*imgThresholdMask))/imgThresholdMaskSum;
0154     imgCorrectionFactor = (imgLowFreqAverage./imgLowFreq).*imgThresholdMask;
0155     imgCorrected = img .* imgCorrectionFactor;
0156     
0157     % update the volume with the corrected values
0158     % -------------------------------------------
0159     if slice_index==1; avw.img(slice,:,:) = imgCorrected; end
0160     if slice_index==2; avw.img(:,slice,:) = imgCorrected; end
0161     if slice_index==3; avw.img(:,:,slice) = imgCorrected; end
0162     
0163     % end slice loop
0164 end
0165 
0166 t=toc; fprintf('...done (%5.2f sec).\n',t);
0167 
0168 return
0169 
0170 
0171 % *Corecting for inhomogeneities in anatomical images*
0172 %
0173 % *
0174 % ------------------------------------------------------------------------
0175 % *
0176 %
0177 % Here is a small but rather useful program developed by Gary Glover for
0178 % correcting inhomogeneities in anatomical images.
0179 %
0180 % Inhomogeneities in signal intensity can be somewhat problematic at high
0181 % magentic fields (e.g. 3 Tesla) and may lead to reduced quality of the
0182 % image due to slow spatial modulation in overall intensity.
0183 %
0184 % Gary's program identifies and removes such low-frequency intensity
0185 % modulations. The transformations are computed for each slice separately.
0186 %
0187 % I have modified the program so that it can handle SPM analyze format
0188 % images. From within our lab it can be used directly by typing
0189 % "vol_homocor" at the matlab5 prompt, or otherwise it can be downloaded
0190 % from here
0191 %
0192 % vol_homocor.m
0193 %
0194 % and saved as a file named "vol_homocor.m" in your matlab directory.
0195 %
0196 % Below is an example of an anatomical image that benefitted a lot from
0197 % correction. Of course, as it goes, some anatomical images are less
0198 % problematic than others, so the usefullness of correction may vary from
0199 % subject to subject.
0200 %
0201 % ------------------------------------------------------------------------
0202 %
0203 % Kalina Christoff / 2000-05-27
0204 % kalina@psych.stanford.edu

Generated on Mon 15-Aug-2005 15:36:19 by m2html © 2003