Hi there, I’m trying to synthesize one full volume from multiple partial volumes(smaller FOV) of the same objects. I wonder if anyone else has explored this topic, and happy to hear any thoughts on what would be the best approach to this.
I appreciate any ideas and advice on things to do or not to do.
Yes, you need to align the volumes in advance, but the module takes care of resampling and blending. If you find that some information is missing then please add the missing details (click the edit button in the github repository, make your changes, and when Github asks you then choose to create a pull request).
@lassoan is correct, the image volumes you want to stitch together must already be positioned where you want them in space. Then, you need an ROI which defines the region that the stitched volume should fill. I typically create this in two steps,
go to “CropVolumes” module, select first volume to stitch as input volume, select ‘Create new ROI’ as ROI, and then click “Fit to Volume”. This creates an ROI which is oriented the same way and with the same dimensions as the input volume. (I don’t crop the volume, just use CropVolumes because of the handy “Fit to Volume” button)
next, extend the ROI as needed to encompass the desired regions of all image volumes to stitch using the interaction handles in the slice views or in 3D
This is how I usually do it because I typically am connecting a series of image volumes along one axis (e.g. a series of bed positions) and it works well to mostly extend an ROI in one direction (and often also bring in the sides to reduce the number of air voxels), but you can create a rectilinear ROI any way that works well for your purposes.
Once you have your ROI created, go to the “Stitch Volumes” module, select your image volumes you want to stitch together, select your ROI, select or create the output to put the stitched volume in, and click the “Create Stitched Volume” button. The selected output will be a new image volume with the same orientation and extent as the ROI, with the same voxel size as the first image volume listed to stitch.
I just give stitch volumes a try. Unfortunately, I couldn’t find it when I did a module finder search after I installed the sandbox module.However, I can find the remove CT table module within sandbox.
@lassoan thanks. I just updated from 5.0.2 to 5.0.3. And it works. But all the previously installed extensions were gone. I wonder if Slicer3D supports update in a way that could still retain installed extensions
Apologies for keeping this issue open. I noticed some interesting behaviour of the stitch volume module, which could arise from my incorrect usage. I have some partial volumes of the same anatomy, the human ear, which I want to stitch together to construct a volume with a holistic view.
From left to right, overlaid segmentations merged models and stitched volumes where I was hoping the stitched volumes would look more like the merged models.
I wonder what would cause the inconsistency between the merged model and the stitched volume where you can notice a significant gap in the stitched volume.
Do the image volumes have transforms applied to them? If so, these transforms need to be hardened before stitching. If you don’t want the transforms to be hardened on the original image volumes, then you can clone them, apply the transforms, and harden the transforms on the clones. Many of the basic modules of Slicer ignore soft-applied transforms during processing, so I followed that convention for this module. When writing modules for my own processing, I usually build in the clone-and-harden step on any inputs which might be transformed because I always want to treat soft-applied transforms as applied, but perhaps other users have other use cases where it makes sense to treat them as not-applied.
All Slicer core modules and most well-established modules in extensions take into account the parent transform. The only exception are CLI modules, which consistently “ignore” the parent transform (parent transforms are not sent to the modules); I’m not sure what is the rationale behind that, but this is how it has always been.
Therefore, ignoring the parent transform is not a convention to follow but a limitation. A module can still be very useful even if it has some known limitations, just we need to make sure the limitation is documented - or even better, a meaningful message is displayed to the user when the module cannot do something that a user might assume it can do.
@mikebind If you don’t want to spend time now with adding support for transformed input images (e.g., by cloning volumes and hardening transform on them) then it could make sense to show an error message to the user if a parent transform is specified for any of the input volumes (or at least describe this limitation in the module documentation).
@lassoan, great, I’ll update the Stitch Volumes module to check for parent transforms and clone, harden, stitch, and clean up. I should be able to get that done by the end of this week. Is the right way to do that to fork the current Sandbox, update with my new code, and then create a pull request?
Is there a way to automatically add a warning of some kind to CLI modules if a user tries to select a transformed node as an input? It is not always obvious to end users that a module they select is a CLI module behind the scenes, and even if they did know, it is not obvious that soft transforms are ignored for these modules. I’ve unexpectedly run into that multiple times over the years before I learned to check for it (so much so that, as you can see above, I assumed that it might be a Slicer convention for basic modules!). I understand that adding machinery to automatically force CLI to respect soft transforms (by clone/hardening before passing inputs to CLI) would be a backwards-incompatible change (though I personally don’t see where it would be a problem), simply adding a warning to let users know that soft transforms will be ignored shouldn’t break anyone’s workflow and would be very helpful to most users.
The module currently stitches the volumes by splitting them along one of the 3 image axes. In the example above, the images seem to overlap in a very complex pattern. To accommodate such cases, the module could be updated to compute a weighted average of all the input images. The distance map computed from non-empty voxel locations could be used as weighting coefficients.