def _update_camera_params(self): P = vtk.vtkMatrix4x4() # projection matrix with clipping planes P.Zero() P.SetElement(0, 0, self._fx) P.SetElement(1, 1, self._fy) P.SetElement(0, 2, self._cx) P.SetElement(1, 2, self._cy) P.SetElement(2, 2, -self.near_clipping - self.far_clipping) P.SetElement(2, 3, -self.near_clipping * self.far_clipping) P.SetElement(3, 2, -1.) # first, reset the user transformation matrix cameraTransform = vtk.vtkPerspectiveTransform() self._camera.SetUserTransform(cameraTransform) # current projection matrix for the VTK camera Minv = self._camera.GetProjectionTransformMatrix( self.width / self.height, self.near_clipping, self.far_clipping) Minv.Invert() # desired user transform matrix U: UM = P U = vtk.vtkMatrix4x4() vtk.vtkMatrix4x4.Multiply4x4(P, Minv, U) # and finally update the transform cameraTransform.SetMatrix(U) self._camera.SetUserTransform(cameraTransform) self.render_window.SetSize(self.width, self.height) self.update()
def update_image(self): reslice = vtk.vtkImageReslice() if self.origin_x is not None: # add padding so that origin_x is in the middle of the image pad = vtk.vtkImageConstantPad() pad.SetInputConnection(self.reader.GetOutputPort()) pad.SetConstant(BG_HU) # GetExtent() returns a tuple (minX, maxX, minY, maxY, minZ, maxZ) extent = list(self.reader.GetOutput().GetExtent()) x_size = extent[1] - extent[0] extent[0] -= max(x_size - 2 * self.origin_x, 0) extent[1] += max(2 * self.origin_x - x_size, 0) pad.SetOutputWholeExtent(*extent) reslice.SetInputConnection(pad.GetOutputPort()) else: reslice.SetInputConnection(self.reader.GetOutputPort()) transform = vtk.vtkPerspectiveTransform() # gantry tilt transform.Shear(0, *self.shear_params) if self.angle_z != 0 or self.angle_y != 0: transform.RotateWXYZ(-self.angle_z, 0, 0, 1) # top transform.RotateWXYZ(self.angle_y, 0, 1, 0) # front reslice.SetResliceTransform(transform) reslice.SetInterpolationModeToCubic() reslice.AutoCropOutputOn() reslice.SetBackgroundLevel(BG_HU) reslice.Update() spacings_lists = reslice.GetOutput().GetSpacing() if self.spacing == 'auto': min_spacing = min(spacings_lists) if not min_spacing: raise ValueError('Invalid scan. Path: {}'.format( self.scan_dir)) spacing = [min_spacing, min_spacing, min_spacing] elif self.spacing == 'none': spacing = None else: spacing = self.spacing if spacing is None: self.image = reslice else: resample = vtkImageResample() resample.SetInputConnection(reslice.GetOutputPort()) resample.SetAxisOutputSpacing(0, spacing[0]) # x axis resample.SetAxisOutputSpacing(1, spacing[1]) # y axis resample.SetAxisOutputSpacing(2, spacing[2]) # z axis resample.SetInterpolationModeToCubic() resample.Update() self.image = resample
def testGeo(): p1 = (2, 0, 0) p2 = (0, 1, 0) t = vtk.reference(1) closest = [0, 0, 0] dtl = vtk.vtkLine.DistanceToLine((0, 0, 0), p1, p2, t, closest) print(dtl, t, closest) print(vtk.vtkMath.Distance2BetweenPoints(p1, p2)) p = [1, 2, 3] project = [0, 0, 0] plane = vtk.vtkPlane() plane.SetOrigin(0, 0, 0) plane.SetNormal(0, 0, 1) plane.ProjectPoint(p, project) print('distance:', p, project) m = vtk.vtkMatrix4x4() m.SetElement(0, 0, 1) m.SetElement(0, 1, 0) m.SetElement(0, 2, 0) m.SetElement(0, 3, 0) m.SetElement(1, 0, 0) m.SetElement(1, 1, 2) m.SetElement(1, 2, 0) m.SetElement(1, 3, 0) m.SetElement(2, 0, 0) m.SetElement(2, 1, 0) m.SetElement(2, 2, 3) m.SetElement(2, 3, 0) m.SetElement(3, 0, 0) m.SetElement(3, 1, 0) m.SetElement(3, 2, 0) m.SetElement(3, 3, 4) transform = vtk.vtkTransform() transform.SetMatrix(m) normalProjection = [1.0] * 3 mNorm = transform.TransformFloatPoint(normalProjection) perspectiveTrans = vtk.vtkPerspectiveTransform() perspectiveTrans.SetMatrix(m) perspectiveProjection = [2] * 3 mPersp = perspectiveTrans.TransformFloatPoint(perspectiveProjection) # m.Identity() print('transform:', m.Determinant(), mNorm, mPersp, m.MultiplyPoint((1, 1, 1, 1)))
def main(): m = vtk.vtkMatrix4x4() m.SetElement(0, 0, 1) m.SetElement(0, 1, 2) m.SetElement(0, 2, 3) m.SetElement(0, 3, 4) m.SetElement(1, 0, 2) m.SetElement(1, 1, 2) m.SetElement(1, 2, 3) m.SetElement(1, 3, 4) m.SetElement(2, 0, 3) m.SetElement(2, 1, 2) m.SetElement(2, 2, 3) m.SetElement(2, 3, 4) m.SetElement(3, 0, 4) m.SetElement(3, 1, 2) m.SetElement(3, 2, 3) m.SetElement(3, 3, 4) perspective_transform = vtk.vtkPerspectiveTransform() perspective_transform.SetMatrix(m) transform = vtk.vtkTransform() transform.SetMatrix(m) p = [1.0, 2.0, 3.0] normal_projection = [0.0, 0.0, 0.0] transform.TransformPoint(p, normal_projection) print("Standard projection:", normal_projection[0], normal_projection[1], normal_projection[2]) perspective_projection = [0.0, 0.0, 0.0] perspective_transform.TransformPoint(p, perspective_projection) print("Perspective projection:", perspective_projection[0], perspective_projection[1], perspective_projection[2])
p6.SetPoint1(-0.5, 0.5, 0.508) p6.SetPoint2(0.5, -0.5, 0.508) p6.SetXResolution(5) p6.SetYResolution(5) p6.Update() # append together ap = vtk.vtkAppendPolyData() ap.AddInputData(p1.GetOutput()) ap.AddInputData(p2.GetOutput()) ap.AddInputData(p3.GetOutput()) ap.AddInputData(p4.GetOutput()) ap.AddInputData(p5.GetOutput()) ap.AddInputData(p6.GetOutput()) #-------------------------- tLinear = vtk.vtkTransform() tPerspective = vtk.vtkPerspectiveTransform() tGeneral = vtk.vtkGeneralTransform() # set up a linear transformation tLinear.Scale(1.2, 1.0, 0.8) tLinear.RotateX(30) tLinear.RotateY(10) tLinear.RotateZ(80) tLinear.Translate(0.2, 0.3, -0.1) tLinear.Update() # set up a perspective transform tPerspective.SetInput(tLinear) tPerspective.SetInput(tLinear.GetInverse()) tPerspective.Scale(2, 2, 2) # these should cancel tPerspective.AdjustViewport(-0.5, 0.5, -0.5, 0.5, -1, 1, -1, 1) tPerspective.AdjustViewport(-1, 1, -1, 1, -0.5, 0.5, -0.5, 0.5)
f32.SetInputConnection(ap.GetOutputPort()) f32.SetTransform(t3.GetInverse()) m32 = vtk.vtkDataSetMapper() m32.SetInputConnection(f32.GetOutputPort()) a32 = vtk.vtkActor() a32.SetMapper(m32) a32.GetProperty().SetColor(0.9,0.9,0) a32.GetProperty().SetRepresentationToWireframe() ren32 = vtk.vtkRenderer() ren32.SetViewport(0.5,0.0,0.75,0.5) ren32.ResetCamera(-0.5,0.5,-0.5,0.5,-1,1) ren32.AddActor(a32) renWin.AddRenderer(ren32) #-------------------------- # perspective transform concatenation t4 = vtk.vtkPerspectiveTransform() t4.Concatenate(t1) t4.Concatenate(t2) t4.Concatenate(t3) f41 = vtk.vtkTransformPolyDataFilter() f41.SetInputConnection(ap.GetOutputPort()) f41.SetTransform(t4) m41 = vtk.vtkDataSetMapper() m41.SetInputConnection(f41.GetOutputPort()) a41 = vtk.vtkActor() a41.SetMapper(m41) a41.GetProperty().SetColor(1,0,0) a41.GetProperty().SetRepresentationToWireframe() ren41 = vtk.vtkRenderer() ren41.SetViewport(0.75,0.5,1.0,1.0) ren41.ResetCamera(-0.5,0.5,-0.5,0.5,-1,1)
a22 = vtk.vtkActor() a22.SetMapper(m22) a22.GetProperty().SetColor(0.9,0.9,0) a22.GetProperty().SetRepresentationToWireframe() ren22 = vtk.vtkRenderer() ren22.SetViewport(0.25,0.0,0.50,0.5) ren22.ResetCamera(-0.5,0.5,-0.5,0.5,-1,1) ren22.AddActor(a22) renWin.AddRenderer(ren22) #-------------------------- # perspective transform matrix = vtk.vtkMatrix4x4() matrix.SetElement(3,0,0.1) matrix.SetElement(3,1,0.2) matrix.SetElement(3,2,0.5) t3 = vtk.vtkPerspectiveTransform() t3.SetMatrix(matrix) f31 = vtk.vtkTransformPolyDataFilter() f31.SetInputConnection(ap.GetOutputPort()) f31.SetTransform(t3) m31 = vtk.vtkDataSetMapper() m31.SetInputConnection(f31.GetOutputPort()) a31 = vtk.vtkActor() a31.SetMapper(m31) a31.GetProperty().SetColor(1,0,0) a31.GetProperty().SetRepresentationToWireframe() ren31 = vtk.vtkRenderer() ren31.SetViewport(0.50,0.5,0.75,1.0) ren31.ResetCamera(-0.5,0.5,-0.5,0.5,-1,1) ren31.AddActor(a31) renWin.AddRenderer(ren31)
def create_stl(self, image=None, gif=None, file=None): ''' gif: three posible values int: get specified region len([])==1: lower threshold of binary mask len([])>1: get region of combined labels ''' # directory dir_end = file.rfind('\\') dir = file[:dir_end] filename = file[dir_end + 1:] name_end = filename.rfind('.') name = filename[:name_end] # create mask mask_image = None if isinstance(gif, int): # create mask of single region mask_image = (image == gif) elif len(gif) == 1: # take region as lowest threshold binaryThresholdFilter = sitk.BinaryThresholdImageFilter() binaryThresholdFilter.SetLowerThreshold(gif[0]) binaryThresholdFilter.SetUpperThreshold(208) mask_image = binaryThresholdFilter.Execute(image) elif len(gif) > 1: # union of masks of each region maskS = (image == gif[0]) for i in range(1, len(gif)): maskS = maskS | (image == gif[i]) # write NII # https://simpleitk.readthedocs.io/en/master/Documentation/docs/source/IO.html writer = sitk.ImageFileWriter() writer.SetImageIO("NiftiImageIO") writer.SetFileName(os.path.join(dir, name + '.nii.gz')) writer.Execute(mask_image) # read NII reader = vtk.vtkNIFTIImageReader() reader.SetFileName(os.path.join(dir, name + '.nii.gz')) reader.Update() # transformation matrix header = reader.GetNIFTIHeader() imgV = reader.GetOutput() mat = self.compute_transformation_matrix(header=header, image=imgV) # mask to vtk dim = reader.GetOutput().GetDimensions() centre = reader.GetOutput().GetOrigin() spacing = reader.GetOutput().GetSpacing() # print('vtk.vtkNIFTIImageReader() dim={} origin={} spacing={}'.format(dim, centre, spacing)) # print('GIF dim={} origin={} spacing={}'.format(image.GetSize(), image.GetOrigin(), image.GetSpacing())) # gaussian gaussian = vtk.vtkImageGaussianSmooth() gaussian.SetInputConnection(reader.GetOutputPort()) gaussian.SetDimensionality(3) gaussian.SetRadiusFactor(0.49) gaussian.SetStandardDeviation(0.1) gaussian.ReleaseDataFlagOn() gaussian.UpdateInformation() gaussian.Update() # marching cubes dmc = vtk.vtkDiscreteMarchingCubes() dmc.SetInputConnection(gaussian.GetOutputPort()) dmc.ComputeNormalsOn() dmc.SetValue(0, 1) dmc.Update() if dmc.GetOutput().GetNumberOfPoints() == 0: print('marching cubes of GIF={} is {}'.format( gif, dmc.GetOutput().GetNumberOfPoints())) return None # smooth marching cubes smoother = vtk.vtkWindowedSincPolyDataFilter() smoothingIterations = 30 # 15 10 passBand = 0.001 # 2 featureAngle = 60.0 # 120.0 360.0 smoother.SetInputConnection(dmc.GetOutputPort()) smoother.SetNumberOfIterations(smoothingIterations) smoother.BoundarySmoothingOff() smoother.FeatureEdgeSmoothingOff() # on smoother.SetFeatureAngle(featureAngle) smoother.SetPassBand(passBand) smoother.NonManifoldSmoothingOn() smoother.BoundarySmoothingOn() smoother.NormalizeCoordinatesOn() smoother.Update() # translate transform = vtk.vtkPerspectiveTransform() transform.SetMatrix(mat) # transform.Concatenate(matA) transformFilter = vtk.vtkTransformPolyDataFilter() transformFilter.SetTransform(transform) transformFilter.SetInputConnection(smoother.GetOutputPort()) transformFilter.Update() # transform if M was saved polydata = transformFilter.GetOutput() if polydata.GetNumberOfPoints() == 0: print('Number of mesh points', polydata.GetNumberOfPoints()) return None # create normals if not available point_normals = polydata.GetPointData().GetNormals() if point_normals == None: normalGen = vtk.vtkPolyDataNormals() normalGen.SetInputData(polydata) normalGen.AutoOrientNormalsOn() normalGen.Update() point_normals = normalGen.GetOutput().GetPointData().GetNormals() polydata.GetPointData().SetNormals(point_normals) polydata.GetPointData().GetNormals().Modified() polydata.GetPointData().Modified() # save STL stlWriter = vtk.vtkSTLWriter() stlWriter.SetFileName(file) # stlWriter.SetInputConnection(smoother.GetOutputPort()) # stlWriter.SetInputConnection(transformFilter.GetOutputPort()) stlWriter.SetInputData(polydata) stlWriter.Write() return polydata