# flip mpr image become abnormal

**URL:** https://discourse.vtk.org/t/flip-mpr-image-become-abnormal/9931
**Category:** Support
**Tags:** code
**Created:** [November 23, 2022, 2:56am UTC](https://discourse.vtk.org/t/flip-mpr-image-become-abnormal/9931 "2022-11-23T02:56:06Z")
**Posts on this page:** 13
**Page:** 1

<div class="post-metadata">

### Author: ![marlon.ma](https://discourse.vtk.org/user_avatar/discourse.vtk.org/marlon.ma/32/6091_2.png) [@marlon.ma](https://discourse.vtk.org/u/marlon.ma)
#### Post date: [November 23, 2022, 2:56am UTC](https://discourse.vtk.org/t/flip-mpr-image-become-abnormal/9931/1 "2022-11-23T02:56:06Z")

</div>

My vtk version is 9.2 .When I perform the flipping function of mpr reconstruction, everything is normal before flipping, and after flipping, the image rotated by the camera becomes abnormal,I found that before flipping, rotating vtkPlaneSource will not affect the rotation of the image. However, after flipping, the rotation of vtkPlaneSource will double or reverse the rotation of my image. Here is my code. thank you.

```auto
#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();

}

```

sorry i am new user ,don not allow me upload video, you can run my code and press “ctrl” rotate image,then you can found the question.

---

<div class="post-metadata">

### Author: ![marlon.ma](https://discourse.vtk.org/user_avatar/discourse.vtk.org/marlon.ma/32/6091_2.png) [@marlon.ma](https://discourse.vtk.org/u/marlon.ma)
#### Post date: [November 24, 2022, 7:15am UTC](https://discourse.vtk.org/t/flip-mpr-image-become-abnormal/9931/2 "2022-11-24T07:15:02Z")

</div>

someone help me

---

<div class="post-metadata">

### Author: ![mwestphal](https://discourse.vtk.org/user_avatar/discourse.vtk.org/mwestphal/32/19_2.png) [@mwestphal](https://discourse.vtk.org/u/mwestphal)
#### Post date: [November 24, 2022, 7:19am UTC](https://discourse.vtk.org/t/flip-mpr-image-become-abnormal/9931/3 "2022-11-24T07:19:40Z")

</div>

Here is the video from @marlon.ma , if that helps:

[/uploads/default/original/2X/5/5d424707fbdc5a4dce950f680fb0658aad76dc4a.webm](https://discourse.vtk.org/uploads/default/original/2X/5/5d424707fbdc5a4dce950f680fb0658aad76dc4a.webm)

---

<div class="post-metadata">

### Author: ![dgobbi](https://discourse.vtk.org/user_avatar/discourse.vtk.org/dgobbi/32/18_2.png) [@dgobbi](https://discourse.vtk.org/u/dgobbi)
#### Post date: [November 24, 2022, 5:03pm UTC](https://discourse.vtk.org/t/flip-mpr-image-become-abnormal/9931/4 "2022-11-24T17:03:14Z")

</div>

The problem occurs because you put vtkImageFlip _after_ vtkImageReslice. So if there is a rotation, the flip occurs in the _rotated_ coordinate system.

The flip must be _before_ vtkImageReslice.

---

<div class="post-metadata">

### Author: ![marlon.ma](https://discourse.vtk.org/user_avatar/discourse.vtk.org/marlon.ma/32/6091_2.png) [@marlon.ma](https://discourse.vtk.org/u/marlon.ma)
#### Post date: [November 25, 2022, 12:57am UTC](https://discourse.vtk.org/t/flip-mpr-image-become-abnormal/9931/5 "2022-11-25T00:57:00Z")

</div>

In my code, flip is before reslice isn’t it？

---

<div class="post-metadata">

### Author: ![dgobbi](https://discourse.vtk.org/user_avatar/discourse.vtk.org/dgobbi/32/18_2.png) [@dgobbi](https://discourse.vtk.org/u/dgobbi)
#### Post date: [November 25, 2022, 1:07am UTC](https://discourse.vtk.org/t/flip-mpr-image-become-abnormal/9931/6 "2022-11-25T01:07:35Z")

</div>

This is your code:

> [@](#):
>
> ```auto
> auto flip = vtkSmartPointer< vtkImageFlip>::New();
> flip->SetFilteredAxis(1);
> flip->SetInputConnection(reslice->GetOutputPort());
> 
> this->ColorMap->SetInputConnection(flip->GetOutputPort());
> 
> ```

In your pipeline, flip happens after reslice.

---

<div class="post-metadata">

### Author: ![marlon.ma](https://discourse.vtk.org/user_avatar/discourse.vtk.org/marlon.ma/32/6091_2.png) [@marlon.ma](https://discourse.vtk.org/u/marlon.ma)
#### Post date: [November 25, 2022, 1:19am UTC](https://discourse.vtk.org/t/flip-mpr-image-become-abnormal/9931/8 "2022-11-25T01:19:05Z")

</div>

thank you very much,i have a try

---

<div class="post-metadata">

### Author: ![marlon.ma](https://discourse.vtk.org/user_avatar/discourse.vtk.org/marlon.ma/32/6091_2.png) [@marlon.ma](https://discourse.vtk.org/u/marlon.ma)
#### Post date: [November 25, 2022, 1:24am UTC](https://discourse.vtk.org/t/flip-mpr-image-become-abnormal/9931/9 "2022-11-25T01:24:28Z")

</div>

If I put the flip before reslice, then I flip the volume data. This is not in line with my idea. Can I flip only the single slice image? My current solution is to prohibit the rotation of the vtkplanesouse. It can work. The side effect is that the size of the vtkplanesouse will not change with the rotation

---

<div class="post-metadata">

### Author: ![dgobbi](https://discourse.vtk.org/user_avatar/discourse.vtk.org/dgobbi/32/18_2.png) [@dgobbi](https://discourse.vtk.org/u/dgobbi)
#### Post date: [November 25, 2022, 2:31am UTC](https://discourse.vtk.org/t/flip-mpr-image-become-abnormal/9931/10 "2022-11-25T02:31:41Z")

</div>

Doing it for just one slice might be difficult. In SetResliceParameters(), how will you know the slice direction, so that you know whether to flip or not to flip? Maybe you can check the ResliceAxes.

What you are trying to do is contrary to what vtkResliceCursor is designed to do, so it will probably be hard to achieve good results.

---

<div class="post-metadata">

### Author: ![dgobbi](https://discourse.vtk.org/user_avatar/discourse.vtk.org/dgobbi/32/18_2.png) [@dgobbi](https://discourse.vtk.org/u/dgobbi)
#### Post date: [November 25, 2022, 2:58am UTC](https://discourse.vtk.org/t/flip-mpr-image-become-abnormal/9931/11 "2022-11-25T02:58:00Z")

</div>

Also, maybe use can use vtkImageReslice to do the flip. This way, you don’t need to add vtkImageFlip to the pipeline.

Where the code says `reslice->SetResliceAxes(this->ResliceAxes)`, you can add a transform that flips the image:

```cpp
auto transform = vtkSmartPointer<vtkTransform>::New();
transform->PostMultiply();
transform->Translate(-centerX, -centerY, -centerZ);
transform->RotateWXYZ(180, 0, 0, 1); // you can also try Scale(+1, -1, +1)
transform->Translate(+centerX, +centerY, +centerZ);

reslice->SetResliceTransform(transform);
reslice->SetResliceAxes(this->ResliceAxes);

```

This is just an idea, so I’m not sure if it will work. The vtkResliceCursor code is complicated, so adding the transform might cause problems in other parts of the code.

---

<div class="post-metadata">

### Author: ![marlon.ma](https://discourse.vtk.org/user_avatar/discourse.vtk.org/marlon.ma/32/6091_2.png) [@marlon.ma](https://discourse.vtk.org/u/marlon.ma)
#### Post date: [November 25, 2022, 3:09am UTC](https://discourse.vtk.org/t/flip-mpr-image-become-abnormal/9931/12 "2022-11-25T03:09:02Z")

</div>

> [@dgobbi](#):
>
> ```auto
> auto transform = vtkSmartPointer<vtkTransform>::New();
> transform->PostMultiply();
> transform->Translate(-centerX, -centerY, -centerZ);
> transform->RotateWXYZ(180, 0, 0, 1); // you can also try Scale(+1, -1, +1)
> transform->Translate(+centerX, +centerY, +centerZ);
> 
> reslice->SetResliceTransform(transform);
> reslice->SetResliceAxes(this->ResliceAxes);
> 
> ```

I have tried this method. There are always other problems. After setting the transform, rotating the slice line will move the center of the slice image, which looks terrible

---

<div class="post-metadata">

### Author: ![marlon.ma](https://discourse.vtk.org/user_avatar/discourse.vtk.org/marlon.ma/32/6091_2.png) [@marlon.ma](https://discourse.vtk.org/u/marlon.ma)
#### Post date: [November 25, 2022, 3:11am UTC](https://discourse.vtk.org/t/flip-mpr-image-become-abnormal/9931/13 "2022-11-25T03:11:58Z")

</div>

But the problem is, when I forbid vtkplansoe rotation, only everything becomes normal. Before flipping, rotate vtkplansoe, and the image will not rotate. But after flipping, the image will rotate with vtkplansoe, which is incomprehensible to me.

---

<div class="post-metadata">

### Author: ![marlon.ma](https://discourse.vtk.org/user_avatar/discourse.vtk.org/marlon.ma/32/6091_2.png) [@marlon.ma](https://discourse.vtk.org/u/marlon.ma)
#### Post date: [November 25, 2022, 3:13am UTC](https://discourse.vtk.org/t/flip-mpr-image-become-abnormal/9931/14 "2022-11-25T03:13:21Z")

</div>

```auto
void myrep::TransformPlane(vtkPlaneSource* planeToTransform,
	double targetCenter[3], double targetNormal[3], double targetViewUp[3])
{

	
	planeToTransform->SetNormal(targetNormal);
	double currentViewUp[3];
	vtkMath::Subtract(planeToTransform->GetPoint2(), planeToTransform->GetOrigin(), currentViewUp);

	double angle = vtkMath::SignedAngleBetweenVectors(currentViewUp, targetViewUp, targetNormal);
	angle = vtkMath::DegreesFromRadians(angle);

	angle = 0;
	planeToTransform->Rotate(-angle, targetNormal);
	planeToTransform->SetCenter(targetCenter);
}

```

In this way, I forbid vtkplanesouse rotation
