From: srit Date: Wed, 13 Apr 2011 17:22:40 +0000 (+0000) Subject: Adapt vvSlicer to vvImage without vtkImageReslice. Now reslice according to the image... X-Git-Tag: v1.2.0~46 X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=commitdiff_plain;h=48d89d66788d01a4fcce97bd58681e0e9e1ce057;p=clitk.git Adapt vvSlicer to vvImage without vtkImageReslice. Now reslice according to the image grid in the slice direction. The transform for the vector field has been disabled for the time being. --- diff --git a/vv/vvSlicer.cxx b/vv/vvSlicer.cxx index 2255cce..abed78c 100644 --- a/vv/vvSlicer.cxx +++ b/vv/vvSlicer.cxx @@ -309,7 +309,18 @@ void vvSlicer::SetImage(vvImage::Pointer image) { if (image->GetVTKImages().size()) { mImage = image; - this->Superclass::SetInput(image->GetTransformedVTKImages()[0]); + + if (!mImageReslice) { + mImageReslice = vtkSmartPointer::New(); + mImageReslice->SetInterpolationModeToLinear(); + mImageReslice->AutoCropOutputOn(); + mImageReslice->SetBackgroundColor(-1000,-1000,-1000,1); + } + mImageReslice->SetResliceTransform(mImage->GetTransform()); + mImageReslice->SetInput(0, mImage->GetFirstVTKImageData()); + mImageReslice->UpdateInformation(); + + this->Superclass::SetInput(mImageReslice->GetOutput()); int extent[6]; this->GetInput()->GetWholeExtent(extent); @@ -322,8 +333,8 @@ void vvSlicer::SetImage(vvImage::Pointer image) // Make sure that the required part image has been computed extent[SliceOrientation*2] = Slice; extent[SliceOrientation*2+1] = Slice; - image->GetTransformedVTKImages()[0]->SetUpdateExtent(extent); - image->GetTransformedVTKImages()[0]->Update(); + mImageReslice->GetOutput()->SetUpdateExtent(extent); + mImageReslice->GetOutput()->Update(); this->UpdateDisplayExtent(); @@ -339,10 +350,19 @@ void vvSlicer::SetOverlay(vvImage::Pointer overlay) { if (overlay->GetVTKImages().size()) { mOverlay = overlay; + + if (!mOverlayReslice) { + mOverlayReslice = vtkSmartPointer::New(); + mOverlayReslice->SetInterpolationModeToLinear(); + mOverlayReslice->AutoCropOutputOn(); + mOverlayReslice->SetBackgroundColor(-1000,-1000,-1000,1); + } + mOverlayReslice->SetResliceTransform(mOverlay->GetTransform()); + mOverlayReslice->SetInput(0, mOverlay->GetFirstVTKImageData()); if (!mOverlayMapper) mOverlayMapper = vtkSmartPointer::New(); - mOverlayMapper->SetInput(overlay->GetTransformedVTKImages()[0]); + mOverlayMapper->SetInput(mOverlayReslice->GetOutput()); if (!mOverlayActor) { mOverlayActor = vtkSmartPointer::New(); @@ -350,7 +370,6 @@ void vvSlicer::SetOverlay(vvImage::Pointer overlay) mOverlayActor->SetPickable(0); mOverlayActor->SetVisibility(false); mOverlayActor->SetOpacity(0.5); - this->UpdateDisplayExtent(); } //stupid but necessary : the Overlay need to be rendered before fusion @@ -361,8 +380,9 @@ void vvSlicer::SetOverlay(vvImage::Pointer overlay) } else this->GetRenderer()->AddActor(mOverlayActor); - //Synchronize slice - SetTSlice(mCurrentTSlice); + //Synchronize orientation and slice + this->SetSliceOrientation(this->SliceOrientation); + this->SetTSlice(mCurrentTSlice); } } //------------------------------------------------------------------------------ @@ -374,9 +394,18 @@ void vvSlicer::SetFusion(vvImage::Pointer fusion) if (fusion->GetVTKImages().size()) { mFusion = fusion; + if (!mFusionReslice) { + mFusionReslice = vtkSmartPointer::New(); + mFusionReslice->SetInterpolationModeToLinear(); + mFusionReslice->AutoCropOutputOn(); + mFusionReslice->SetBackgroundColor(-1000,-1000,-1000,1); + } + mFusionReslice->SetResliceTransform(mFusion->GetTransform()); + mFusionReslice->SetInput(0, mFusion->GetFirstVTKImageData()); + if (!mFusionMapper) mFusionMapper = vtkSmartPointer::New(); - mFusionMapper->SetInput(fusion->GetTransformedVTKImages()[0]); + mFusionMapper->SetInput(mFusionReslice->GetOutput()); if (!mFusionActor) { mFusionActor = vtkSmartPointer::New(); @@ -384,12 +413,12 @@ void vvSlicer::SetFusion(vvImage::Pointer fusion) mFusionActor->SetPickable(0); mFusionActor->SetVisibility(false); mFusionActor->SetOpacity(0.7); - this->UpdateDisplayExtent(); this->GetRenderer()->AddActor(mFusionActor); } - //Synchronize slice - SetTSlice(mCurrentTSlice); + //Synchronize orientation and slice + this->SetSliceOrientation(this->SliceOrientation); + this->SetTSlice(mCurrentTSlice); } } //------------------------------------------------------------------------------ @@ -425,7 +454,7 @@ void vvSlicer::SetVF(vvImage::Pointer vf) mVOIFilter = vtkSmartPointer::New(); mVOIFilter->SetSampleRate(mSubSampling,mSubSampling,mSubSampling); } - mVOIFilter->SetInput(vf->GetTransformedVTKImages()[0]); + mVOIFilter->SetInput(vf->GetFirstVTKImageData()); mAAFilter->SetInput(mVOIFilter->GetOutput()); ///This tells VTK to use the scalar (pixel) data of the image to draw the little arrows mAAFilter->Assign(vtkDataSetAttributes::SCALARS, vtkDataSetAttributes::VECTORS, vtkAssignAttribute::POINT_DATA); @@ -620,18 +649,18 @@ void vvSlicer::SetTSlice(int t) if (mCurrentTSlice == t) return; mCurrentTSlice = t; - this->SetInput(mImage->GetTransformedVTKImages()[t]); + mImageReslice->SetInput( mImage->GetVTKImages()[mCurrentTSlice] ); if (mVF && mVFActor->GetVisibility()) { if (mVF->GetVTKImages().size() > (unsigned int)mCurrentTSlice) - mVOIFilter->SetInput(mVF->GetTransformedVTKImages()[mCurrentTSlice]); + mVOIFilter->SetInput(mVF->GetVTKImages()[mCurrentTSlice]); } if (mOverlay && mOverlayActor->GetVisibility()) { - if (mOverlay->GetTransformedVTKImages().size() > (unsigned int)mCurrentTSlice) - mOverlayMapper->SetInput(mOverlay->GetTransformedVTKImages()[mCurrentTSlice]); + if (mOverlay->GetVTKImages().size() > (unsigned int)mCurrentTSlice) + mOverlayReslice->SetInput( mOverlay->GetVTKImages()[mCurrentTSlice] ); } if (mFusion && mFusionActor->GetVisibility()) { if (mFusion->GetVTKImages().size() > (unsigned int)mCurrentTSlice) - mFusionMapper->SetInput(mFusion->GetTransformedVTKImages()[mCurrentTSlice]); + mFusionReslice->SetInput( mFusion->GetVTKImages()[mCurrentTSlice]); } if (mSurfaceCutActors.size() > 0) for (std::vector::iterator i=mSurfaceCutActors.begin(); @@ -649,7 +678,6 @@ int vvSlicer::GetTSlice() } //------------------------------------------------------------------------------ - //------------------------------------------------------------------------------ void vvSlicer::SetSliceOrientation(int orientation) { @@ -657,16 +685,22 @@ void vvSlicer::SetSliceOrientation(int orientation) int extent[6]; this->GetInput()->GetWholeExtent(extent); if (extent[5]-extent[4] <= 2) - orientation=2; + orientation = vtkImageViewer2::SLICE_ORIENTATION_XY; if (orientation < vtkImageViewer2::SLICE_ORIENTATION_YZ || orientation > vtkImageViewer2::SLICE_ORIENTATION_XY) { vtkErrorMacro("Error - invalid slice orientation " << orientation); return; } - + this->SliceOrientation = orientation; + if(mFusion) + AdjustResliceToSliceOrientation(mFusionReslice); + + if(mOverlay) + AdjustResliceToSliceOrientation(mOverlayReslice); + // Update the viewer int *range = this->GetSliceRange(); if (range) @@ -690,6 +724,41 @@ void vvSlicer::SetSliceOrientation(int orientation) } //---------------------------------------------------------------------------- +//------------------------------------------------------------------------------ +// This function ensures that we sample the slices of a vtkImageReslice filter +// in the direction of the slicer (SliceOrientation) similarly as mImageReslice. +// In other words, we change the grid of the reslice in the same way as the grid +// of the displayed image in the slicing direction. +void vvSlicer::AdjustResliceToSliceOrientation(vtkImageReslice *reslice) +{ + // Reset autocrop + double origin[3] = {VTK_DOUBLE_MAX, VTK_DOUBLE_MAX, VTK_DOUBLE_MAX}; + double spacing[3] = {VTK_DOUBLE_MAX, VTK_DOUBLE_MAX, VTK_DOUBLE_MAX}; + reslice->SetOutputOrigin(origin); + reslice->SetOutputSpacing(spacing); + reslice->GetOutput()->UpdateInformation(); + reslice->GetOutput()->GetOrigin(origin); + reslice->GetOutput()->GetSpacing(spacing); + + // Use similar spacing as the image in the direction SliceOrientation + spacing[this->SliceOrientation] = mImageReslice->GetOutput()->GetSpacing()[this->SliceOrientation]; + + // Modify origin to be on the image grid in the direction SliceOrientation in 3 steps + // Step 1: from world coordinates to image coordinates + origin[this->SliceOrientation] -= mImageReslice->GetOutput()->GetOrigin()[this->SliceOrientation]; + origin[this->SliceOrientation] /= mImageReslice->GetOutput()->GetSpacing()[this->SliceOrientation]; + // Step 2: round to superior grid positionInc + origin[this->SliceOrientation] = itk::Math::Ceil(origin[this->SliceOrientation]); + // Step 3: back to world coordinates + origin[this->SliceOrientation] *= mImageReslice->GetOutput()->GetSpacing()[this->SliceOrientation]; + origin[this->SliceOrientation] += mImageReslice->GetOutput()->GetOrigin()[this->SliceOrientation]; + + // Set new spacing and origin + reslice->SetOutputOrigin(origin); + reslice->SetOutputSpacing(spacing); + reslice->UpdateInformation(); +} +//------------------------------------------------------------------------------ //---------------------------------------------------------------------------- int * vvSlicer::GetExtent() @@ -743,8 +812,8 @@ void vvSlicer::UpdateDisplayExtent() // Overlay image actor if (mOverlay && mOverlayActor->GetVisibility()) { int overExtent[6]; - mOverlay->GetTransformedVTKImages()[0]->UpdateInformation(); - this->ConvertImageToImageDisplayExtent(input, w_ext, mOverlay->GetTransformedVTKImages()[0], overExtent); + mOverlayReslice->GetOutput()->UpdateInformation(); + this->ConvertImageToImageDisplayExtent(input, w_ext, mOverlayReslice->GetOutput(), overExtent); ClipDisplayedExtent(overExtent, mOverlayMapper->GetInput()->GetWholeExtent()); mOverlayActor->SetDisplayExtent( overExtent ); mOverlayActor->SetPosition(position); @@ -754,8 +823,8 @@ void vvSlicer::UpdateDisplayExtent() // Fusion image actor if (mFusion && mFusionActor->GetVisibility()) { int fusExtent[6]; - mFusion->GetTransformedVTKImages()[0]->UpdateInformation(); - this->ConvertImageToImageDisplayExtent(input, w_ext, mFusion->GetTransformedVTKImages()[0], fusExtent); + mFusionReslice->GetOutput()->UpdateInformation(); + this->ConvertImageToImageDisplayExtent(input, w_ext, mFusionReslice->GetOutput(), fusExtent); ClipDisplayedExtent(fusExtent, mFusionMapper->GetInput()->GetWholeExtent()); mFusionActor->SetDisplayExtent(fusExtent); mFusionActor->SetPosition(position); @@ -765,8 +834,8 @@ void vvSlicer::UpdateDisplayExtent() // Vector field actor if (mVF && mVFActor->GetVisibility()) { int vfExtent[6]; - mVF->GetTransformedVTKImages()[0]->UpdateInformation(); - this->ConvertImageToImageDisplayExtent(input, w_ext, mVF->GetTransformedVTKImages()[0], vfExtent); + mVF->GetVTKImages()[0]->UpdateInformation(); + this->ConvertImageToImageDisplayExtent(input, w_ext, mVF->GetVTKImages()[0], vfExtent); ClipDisplayedExtent(vfExtent, mVOIFilter->GetInput()->GetWholeExtent()); mVOIFilter->SetVOI(vfExtent); int orientation[3] = {1,1,1}; diff --git a/vv/vvSlicer.h b/vv/vvSlicer.h index 0ace4ac..8c79969 100644 --- a/vv/vvSlicer.h +++ b/vv/vvSlicer.h @@ -27,6 +27,7 @@ #include #include +#include class vtkActor; class vtkActor2D; @@ -93,6 +94,7 @@ public: void SetLandmarks(vvLandmarks* landmarks); void SetTSlice(int t); void SetSliceOrientation(int orientation); + void AdjustResliceToSliceOrientation(vtkImageReslice *reslice); int GetTSlice(); ///Reimplemented from vtkImageViewer2 to add polydata support void SetSlice(int s); @@ -189,8 +191,11 @@ protected: vvLandmarks* mLandmarks; + vtkSmartPointer mImageReslice; + vtkSmartPointer mOverlayReslice; vtkSmartPointer mOverlayMapper; vtkSmartPointer mOverlayActor; + vtkSmartPointer mFusionReslice; vtkSmartPointer mFusionMapper; vtkSmartPointer mFusionActor; vtkSmartPointer ca;