[Insight-developers] Just checked in: Support for vector images
in itk::NiftiImageIO.cxx
Gordon Kindlmann
gk at bwh.harvard.edu
Wed Apr 5 18:17:30 EDT 2006
hello,
I'm happy to see increased NIfTI support in ITK.
I ran into the same issues when adding full NRRD support to ITK.
NRRD, like NIfTI, can store vector quantities, and as in NIfTI, you
can tag that axis with a "kind" that serves the same role as the
"intent" in NIfTI. I chose nrrdKindVector just like you chose
NIFTI_INTENT_VECTOR (this stuff is in Insight/Code/IO/
itkNrrdImageIO.cxx). As an aside, one drawback with NIfTI is that it
can't represent the difference between a contravariant vector and a
covariant vector; NRRD does allow you do set either nrrdKindVector or
nrrdKindCovariantVector, according to ITK pixel type
ImageIOBase::VECTOR or ImageIOBase::COVARIANTVECTOR, respectively.
The logic in Insight/Code/IO/itkNrrdImageIO.cxx represents the best I
could come with as far as a clean mapping between ITK pixel types and
Nrrd kinds, and probably like your ITK<-->NIfTI mapping, its not
fully bijective: ImageIOBase::OFFSET, ImageIOBase::VECTOR, and
ImageIOBase::FIXEDARRAY all map to nrrdKindVector; while
nrrdKindVector, nrrdKindList, nrrdKindQuaternion all map to
ImageIOBase::VECTOR.
You noted that its unfortunate that while ITK internally stores
multiple per-voxel values along the fastest axis (as close as
possible in memory, as it should be), NIfTI puts these values on the
slowest axis (as far apart as possible on disk). I believe this is
for backwards compatibility reasons, related to how existing software
uses the Analyze format (upon which NIfTI is entirely based). I had
the same issue with the axis permutation as you described, except
that it was slightly worse in NRRD: the axis for the per-voxel values
can be anywhere among the other spatial axes-- fastest, slowest, or
in between (as indicated by whichever axis has a non-spatial
"kind"=="intent").
So I snagged the nrrdAxesPermute function and put it into Insight/
Utilities/NrrdIO, which is likely doing the same thing as
itk::PermuteAxesImageFilter. nrrdAxesPermute is like the brute-force
permutation you described, but with the optimization that the
entities being permuted are not individual samples, but the scanlines
(or image slices) along the set of fastest axes which are
unpermuted. So instead of many scalar value assignments, you can do
memcpy()s of larger units. But in the end, on average, the
performance may not be radically different.
Gordon
On Apr 5, 2006, at 4:43 PM, Kent Williams wrote:
> This was development driven by local requirements @ U of Iowa, but
> should be of general interest.
>
> I've added support for vector images in itk::NiftiImageIO. I added
> a test to Insight/Testing/Code/IO as well. I would appreciate any
> feedback from those of you who regularly use vector images.
>
> If you write out a vector image, it sets the intent to
> NIFTI_INTENT_VECTOR. NIfTI, as it happens, supports a load of
> different intent codes that all boil down to vector types, but
> coming from ITK, you don't know if another intent code would be
> more appropriate. Unfortunately, given the way ImageIO works
> internally, getting a handle for the itk::NiftiImageIO object from
> your file writer, and setting the intent code won't work, since it
> will be overwritten in WriteImageInformation.
>
> NIfTI also defines a couple of matrix types, which I haven't added
> support for. That wouldn't be a huge amount of work because the
> data ordering in the file works the same as with vectors.
>
> NIfTI stores things a little strangely (to my mind) with respect
> to vectors -- for a volume of vectors, it's stored as a series of
> volumes, one per vector component. In other words I have to premute
> axes when I read and write nifti files, basically
>
> ITKVectorArray[t][z][y][x][vec] <=> NIfTIVectorArray[vec][t][z][y][x]
>
> I did the permutation in-line in itkNiftiImageIO.cxx. I couldn't
> find anything to re-use in ITK to do the permutation, short of
> creating an itk::Image from the image data and using
> itk::PermuteAxesImageFilter. So I use brute force nested loops.
> Anyone has a better idea let me know.
>
> _______________________________________________
> Insight-developers mailing list
> Insight-developers at itk.org
> http://www.itk.org/mailman/listinfo/insight-developers
More information about the Insight-developers
mailing list