Some abnormalities occur after the mpr slice image is flipped
My vtk version is 9.2. I'm doing mpr display. One of the functions is to mirror an image. I use vtkimageflip to complete it. However, when the image is flipped, the vtkResliceCursorLineRepresentation class also rotates the plane behind the camera when rotating the camera. When I don't flip image, rotating the vtkPlaneSource will not produce adverse effects. When the image is flipped, the rotation will produce double rotation, or reverse selection. The following is the demo of my code, thank you
#include "vtkSmartPointer.h"
#include "vtkCamera.h"
#include "vtkCellPicker.h"
#include "vtkCommand.h"
#include "vtkImageActor.h"
#include "vtkImageReslice.h"
#include "vtkInteractorStyleImage.h"
#include "vtkImageMapToColors.h"
#include "vtkImagePlaneWidget.h"
#include "vtkImageReader.h"
#include "vtkInteractorEventRecorder.h"
#include "vtkLookupTable.h"
#include "vtkOutlineFilter.h"
#include "vtkDICOMImageReader.h"
#include "vtkPolyDataMapper.h"
#include "vtkProperty.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkRenderer.h"
#include "vtkImageData.h"
#include "vtkPointData.h"
#include "vtkPlaneSource.h"
#include "vtkPlane.h"
#include "vtkResliceCursorActor.h"
#include "vtkResliceCursorPolyDataAlgorithm.h"
#include "vtkResliceCursor.h"
#include "vtkResliceCursorWidget.h"
#include "vtkResliceCursorLineRepresentation.h"
#include "vtkBiDimensionalWidget.h"
#include"vtkAutoInit.h"
#include"vtkAxesActor.h"
#include"vtkTransform.h"
#include"vtkTextActor.h"
#include"vtkProperty2D.h"
#include<vtkActor2D.h>
#include<vtkResliceImageViewer.h>
#include<vtkImageFlip.h>
#include"vtkAutoInit.h"
VTK_MODULE_INIT(vtkInteractionStyle);
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkRenderingFreeType)
class myrep :public vtkResliceCursorLineRepresentation {
public:
static myrep* New()
{
return new myrep;
}
void SetResliceParameters(
double outputSpacingX, double outputSpacingY, int extentX, int extentY)override
{
vtkImageReslice* reslice = vtkImageReslice::SafeDownCast(this->Reslice);
if (reslice)
{
// Set the default color the minimum scalar value
double range[2];
vtkImageData::SafeDownCast(reslice->GetInput())->GetScalarRange(range);
reslice->SetBackgroundLevel(range[0]);
auto flip = vtkSmartPointer< vtkImageFlip>::New();
flip->SetFilteredAxis(1);
flip->SetInputConnection(reslice->GetOutputPort());
this->ColorMap->SetInputConnection(flip->GetOutputPort());
reslice->TransformInputSamplingOff();
reslice->AutoCropOutputOn();
reslice->SetResliceAxes(this->ResliceAxes);
reslice->SetOutputSpacing(outputSpacingX, outputSpacingY, 1);
reslice->SetOutputOrigin(0.5 * outputSpacingX, 0.5 * outputSpacingY, 0);
reslice->SetOutputExtent(0, extentX - 1, 0, extentY - 1, 0, 0);
}
}
};
class vtkResliceCursorCallback : public vtkCommand
{
public:
static vtkResliceCursorCallback* New()
{
return new vtkResliceCursorCallback;
}
void Execute(vtkObject* caller, unsigned long ev,
void* callData) override
{
if (ev == vtkResliceCursorWidget::WindowLevelEvent ||
ev == vtkCommand::WindowLevelEvent ||
ev == vtkResliceCursorWidget::ResliceThicknessChangedEvent)
{
// Render everything
for (int i = 0; i < 3; i++)
{
this->RCW[i]->Render();
}
this->IPW[0]->GetInteractor()->GetRenderWindow()->Render();
//return;
}
vtkResliceCursorWidget* rcw = dynamic_cast<
vtkResliceCursorWidget*>(caller);
if (rcw)
{
vtkResliceCursorLineRepresentation* rep = dynamic_cast<
vtkResliceCursorLineRepresentation*>(rcw->GetRepresentation());
double window[2];
rep->GetWindowLevel(window);
//同步的前提下才能实现
for (size_t i = 0; i < 3; i++)
{
RCW[i]->GetResliceCursorRepresentation()->SetWindowLevel(window[0], window[1]);
}
rep->GetResliceCursorActor()->GetCursorAlgorithm()->GetResliceCursor();
for (int i = 0; i < 3; i++)
{
vtkPlaneSource* ps = static_cast<vtkPlaneSource*>(
this->IPW[i]->GetPolyDataAlgorithm());
ps->SetOrigin(this->RCW[i]->GetResliceCursorRepresentation()->
GetPlaneSource()->GetOrigin());
ps->SetPoint1(this->RCW[i]->GetResliceCursorRepresentation()->
GetPlaneSource()->GetPoint1());
ps->SetPoint2(this->RCW[i]->GetResliceCursorRepresentation()->
GetPlaneSource()->GetPoint2());
// If the reslice plane has modified, update it on the 3D widget
this->IPW[i]->UpdatePlacement();
}
}
// Render everything
for (int i = 0; i < 3; i++)
{
this->RCW[i]->Render();
}
this->IPW[0]->GetInteractor()->GetRenderWindow()->Render();
}
vtkResliceCursorCallback() {}
vtkImagePlaneWidget* IPW[3];
vtkResliceCursorWidget* RCW[3];
vtkResliceImageViewer* RIW[3];
};
int main()
{
vtkSmartPointer<vtkDICOMImageReader> reader = vtkSmartPointer<vtkDICOMImageReader>::New();
std::string dict = "C:\\Users\\12820\\Desktop\\DICOM参考数据\\CT-head\\1.25-240";
std::string dict1 = "C:\\Users\\12820\\source\\repos\\vtkProject\\vtkProject\\imaghe\\rt_ct";
reader->SetDirectoryName(dict1.c_str());
reader->Update();
int imageDims[3];
reader->GetOutput()->GetDimensions(imageDims);
vtkSmartPointer< vtkResliceImageViewer >riw[3];
vtkSmartPointer< vtkRenderWindow >renderWindow[3];
vtkSmartPointer< vtkRenderWindowInteractor >renderWindowInteractor[3];
vtkSmartPointer< vtkResliceCursor > resliceCursor = vtkSmartPointer< vtkResliceCursor >::New();
vtkSmartPointer< myrep > rep[3];
resliceCursor->SetCenter(reader->GetOutput()->GetCenter());
resliceCursor->SetImage(reader->GetOutput());
for (int i = 0; i < 3; i++)
{
riw[i] = vtkSmartPointer< vtkResliceImageViewer >::New();
rep[i] = vtkSmartPointer< myrep >::New();
renderWindowInteractor[i] = vtkSmartPointer< vtkRenderWindowInteractor >::New();
riw[i]->SetupInteractor(renderWindowInteractor[i]);
}
for (int i = 0; i < 3; i++)
{
riw[i]->GetResliceCursorWidget()->SetRepresentation(rep[i]);
riw[i]->SetResliceCursor(resliceCursor);
rep[i]->GetResliceCursorActor()->GetCursorAlgorithm()->SetReslicePlaneNormal(i);
rep[i]->GetResliceCursorActor()->GetCenterlineProperty(0)->SetRepresentationToWireframe();//代表12窗口竖线
rep[i]->GetResliceCursorActor()->GetCenterlineProperty(1)->SetRepresentationToWireframe();//0竖线,2横线
rep[i]->GetResliceCursorActor()->GetCenterlineProperty(2)->SetRepresentationToWireframe();//01横线
riw[i]->SetInputData(reader->GetOutput());
riw[i]->GetRenderWindow()->SetSize(500, 500);
riw[i]->GetRenderWindow()->SetPosition(800 + i * 500, 500);
if (i == 2)
riw[i]->GetRenderWindow()->SetPosition(800, 0);
riw[i]->SetSliceOrientation(1);
riw[i]->SetSliceOrientation(i);
}
for (int i = 0; i < 3; i++)
{
riw[i]->SetResliceMode(1);
riw[i]->GetRenderer()->ResetCamera();
riw[i]->Render();
}
vtkSmartPointer<vtkCellPicker> picker = vtkSmartPointer<vtkCellPicker>::New();
vtkSmartPointer<vtkProperty> ipwProp = vtkSmartPointer<vtkProperty>::New();
vtkSmartPointer< vtkRenderer > ren = vtkSmartPointer< vtkRenderer >::New();
auto renderWindow4 = vtkSmartPointer<vtkRenderWindow>::New();;//第四个窗口
auto iren = vtkSmartPointer<vtkRenderWindowInteractor>::New();//第四个窗口的vtkRenderWindowInteractor
renderWindow4->SetInteractor(iren);
renderWindow4->AddRenderer(ren);
vtkSmartPointer<vtkImagePlaneWidget>planeWidget[3];
for (int i = 0; i < 3; i++)
{
planeWidget[i] = vtkSmartPointer<vtkImagePlaneWidget>::New();
planeWidget[i]->SetInteractor(iren);
planeWidget[i]->SetPicker(picker);
planeWidget[i]->RestrictPlaneToVolumeOn();
double color[3] = { 0, 0, 0 };
color[i] = 1;
planeWidget[i]->GetPlaneProperty()->SetColor(color);
color[0] /= 4.0;
color[1] /= 4.0;
color[2] /= 4.0;
riw[i]->GetRenderer()->SetBackground(0, 0, 0);
planeWidget[i]->SetTexturePlaneProperty(ipwProp);
planeWidget[i]->TextureInterpolateOff();
planeWidget[i]->SetResliceInterpolateToLinear();
planeWidget[i]->SetInputConnection(reader->GetOutputPort());
planeWidget[i]->SetPlaneOrientation(i);
planeWidget[i]->SetSliceIndex(imageDims[i] / 2);
planeWidget[i]->DisplayTextOn();
planeWidget[i]->SetDefaultRenderer(ren);
planeWidget[i]->SetWindowLevel(1358, -27);
planeWidget[i]->On();
planeWidget[i]->InteractionOn();
}
auto cbk = vtkSmartPointer<vtkResliceCursorCallback>::New();
for (int i = 0; i < 3; i++)
{
cbk->RIW[i] = riw[i];
cbk->IPW[i] = planeWidget[i];
cbk->RCW[i] = riw[i]->GetResliceCursorWidget();
vtkWidgetEventTranslator* WidgetTrans = riw[i]->GetResliceCursorWidget()->GetEventTranslator();
riw[i]->GetResliceCursorWidget()->AddObserver(vtkResliceCursorWidget::ResliceAxesChangedEvent, cbk);
riw[i]->GetResliceCursorWidget()->AddObserver(vtkResliceCursorWidget::WindowLevelEvent, cbk);
riw[i]->GetResliceCursorWidget()->AddObserver(vtkResliceCursorWidget::ResliceThicknessChangedEvent, cbk);
riw[i]->GetResliceCursorWidget()->AddObserver(vtkResliceCursorWidget::ResetCursorEvent, cbk);
riw[i]->SetLookupTable(riw[0]->GetLookupTable());
planeWidget[i]->GetColorMap()->SetLookupTable(riw[0]->GetLookupTable());
// planeWidget[i]->GetColorMap()->(riw[i]->GetResliceCursorWidget()->GetResliceCursorRepresentation()->GetColorMap()->GetInput());
planeWidget[i]->SetColorMap(riw[i]->GetResliceCursorWidget()->GetResliceCursorRepresentation()->GetColorMap());
}
auto style = vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New();
iren->SetInteractorStyle(style);
renderWindow4->SetSize(500, 500);
renderWindow4->SetPosition(1300, 0);
renderWindow4->Render();
iren->Initialize();
iren->Start();
}
Edited by 马文龙