Пример #1
0
def recoSurface(points, bins=256,
                c='gold', alpha=1, wire=False, bc='t', legend=None):
    '''
    Surface reconstruction from sparse points.

    [**Example**](https://github.com/marcomusy/vtkplotter/blob/master/examples/advanced/recosurface.py)  

    ![reco](https://user-images.githubusercontent.com/32848391/46817107-b3263880-cd7e-11e8-985d-f5d158992f0c.png)
    '''

    if isinstance(points, vtk.vtkActor):
        points = points.coordinates()
    N = len(points)
    if N < 50:
        print('recoSurface: Use at least 50 points.')
        return None
    points = np.array(points)

    ptsSource = vtk.vtkPointSource()
    ptsSource.SetNumberOfPoints(N)
    ptsSource.Update()
    vpts = ptsSource.GetOutput().GetPoints()
    for i, p in enumerate(points):
        vpts.SetPoint(i, p)
    polyData = ptsSource.GetOutput()

    distance = vtk.vtkSignedDistance()
    f = 0.1
    x0, x1, y0, y1, z0, z1 = polyData.GetBounds()
    distance.SetBounds(x0-(x1-x0)*f, x1+(x1-x0)*f,
                       y0-(y1-y0)*f, y1+(y1-y0)*f,
                       z0-(z1-z0)*f, z1+(z1-z0)*f)
    if polyData.GetPointData().GetNormals():
        distance.SetInputData(polyData)
    else:
        normals = vtk.vtkPCANormalEstimation()
        normals.SetInputData(polyData)
        normals.SetSampleSize(int(N/50))
        normals.SetNormalOrientationToGraphTraversal()
        distance.SetInputConnection(normals.GetOutputPort())
        print('Recalculating normals for', N,
              'points, sample size=', int(N/50))
        
    b = polyData.GetBounds()
    diagsize = np.sqrt((b[1]-b[0])**2 + (b[3]-b[2])**2 + (b[5]-b[4])**2)
    radius = diagsize/bins*5
    distance.SetRadius(radius)
    distance.SetDimensions(bins, bins, bins)
    distance.Update()

    print('Calculating mesh from points with R =', radius)
    surface = vtk.vtkExtractSurface()
    surface.SetRadius(radius * .99)
    surface.HoleFillingOn()
    surface.ComputeNormalsOff()
    surface.ComputeGradientsOff()
    surface.SetInputConnection(distance.GetOutputPort())
    surface.Update()
    return Actor(surface.GetOutput(), c, alpha, wire, bc, legend)
def recoSurface(points,
                bins=256,
                c='gold',
                alpha=1,
                wire=False,
                bc='t',
                edges=False,
                legend=None):
    '''
    Surface reconstruction from sparse points.
    '''

    if isinstance(points, vtk.vtkActor): points = vu.coordinates(points)
    N = len(points)
    if N < 50:
        print('recoSurface: Use at least 50 points.')
        return None
    points = np.array(points)

    ptsSource = vtk.vtkPointSource()
    ptsSource.SetNumberOfPoints(N)
    ptsSource.Update()
    vpts = ptsSource.GetOutput().GetPoints()
    for i, p in enumerate(points):
        vpts.SetPoint(i, p)
    polyData = ptsSource.GetOutput()

    distance = vtk.vtkSignedDistance()
    f = 0.1
    x0, x1, y0, y1, z0, z1 = polyData.GetBounds()
    distance.SetBounds(x0 - (x1 - x0) * f, x1 + (x1 - x0) * f,
                       y0 - (y1 - y0) * f, y1 + (y1 - y0) * f,
                       z0 - (z1 - z0) * f, z1 + (z1 - z0) * f)
    if polyData.GetPointData().GetNormals():
        distance.SetInputData(polyData)
        vu.setInput(distance, polyData)
    else:
        normals = vtk.vtkPCANormalEstimation()
        vu.setInput(normals, polyData)
        normals.SetSampleSize(int(N / 50))
        normals.SetNormalOrientationToGraphTraversal()
        distance.SetInputConnection(normals.GetOutputPort())
        print('Recalculating normals for', N, 'points, sample size=',
              int(N / 50))
    radius = vu.diagonalSize(polyData) / bins * 5
    distance.SetRadius(radius)
    distance.SetDimensions(bins, bins, bins)
    distance.Update()

    print('Calculating mesh from points with R =', radius)
    surface = vtk.vtkExtractSurface()
    surface.SetRadius(radius * .99)
    surface.HoleFillingOn()
    surface.ComputeNormalsOff()
    surface.ComputeGradientsOff()
    surface.SetInputConnection(distance.GetOutputPort())
    surface.Update()
    return vu.makeActor(surface.GetOutput(), c, alpha, wire, bc, edges, legend)
Пример #3
0
    def __init__(self, input, toggle_normals, sample):
        self._norms = vtk.vtkPCANormalEstimation()
        self._norms.SetInputConnection(input.GetOutputPort())
        self._norms.SetSampleSize(sample)

        if toggle_normals:
            self._norms.FlipNormalsOn()
        else:
            self._norms.FlipNormalsOff()

        self._norms.SetNormalOrientationToGraphTraversal()
Пример #4
0
def create_surface_actor(points, n=None, orientationPoint=None, negate=False):
    """Generate point normals using PCA (principal component analysis).
    Basically this estimates a local tangent plane around each sample point p
    by considering a small neighborhood of points around p, and fitting a plane
    to the neighborhood (via PCA).

    :param int n: neighborhood size to calculate the normal
    :param list orientationPoint: adjust the +/- sign of the normals so that
        the normals all point towards a specified point. If None, perform a traversal
        of the point cloud and flip neighboring normals so that they are mutually consistent.

    :param bool negate: flip all normals
    """

    if n is not None:
        sampleSize = n

    else:
        sampleSize = points.GetNumberOfPoints() * .00005
        if sampleSize < 10:
            sampleSize = 10

    polydata = vtk.vtkPolyData()
    polydata.SetPoints(points)

    print('Estimating normals using PCANormalEstimation')
    normals = vtk.vtkPCANormalEstimation()
    normals.SetInputData(polydata)
    normals.SetSampleSize(sampleSize)
    if orientationPoint is not None:
        normals.SetNormalOrientationToPoint()
        normals.SetOrientationPoint(orientationPoint)
    else:
        normals.SetNormalOrientationToGraphTraversal()
    if negate:
        normals.FlipNormalsOn()
    normals.Update()

    points_array = vtk_to_numpy(points.GetData())
    normals_array = vtk_to_numpy(
        normals.GetOutput().GetPointData().GetNormals())

    faces, vertices = poisson_reconstruction(points_array,
                                             normals_array,
                                             depth=10)

    return create_mesh_actor(vertices, faces)
Пример #5
0
def normal_estimation_visual(filename, ply=None):
    '''
    filename:文件名
    顶点的法线评估
    '''
    reader = vtk.vtkSimplePointsReader()
    reader.SetFileName(filename)
    reader.Update()
    polyData = reader.GetOutput()

    sampleSize = polyData.GetNumberOfPoints() * .00005
    if sampleSize < 10:
        sampleSize = 10

    print('Estimating normals using PCANormalEstimation')
    normals = vtk.vtkPCANormalEstimation()
    normals.SetInputData(polyData)
    normals.SetSampleSize(sampleSize)
    normals.SetNormalOrientationToGraphTraversal()
    normals.FlipNormalsOff()
    normals.Update()

    render(normals.GetOutput(), None, ply)
Пример #6
0
def normal_estimation_write(infile, outfile):
    '''
    infile:string, 输入的文件路径
    outfile:string,输出的文件路径
    '''
    reader = vtk.vtkSimplePointsReader()
    reader.SetFileName(infile)
    reader.Update()
    polyData = reader.GetOutput()

    sampleSize = polyData.GetNumberOfPoints() * .00005
    if sampleSize < 10:
        sampleSize = 10

    print('Estimating normals using PCANormalEstimation')
    normals = vtk.vtkPCANormalEstimation()
    normals.SetInputData(polyData)
    normals.SetSampleSize(sampleSize)
    normals.SetNormalOrientationToGraphTraversal()
    normals.FlipNormalsOn()
    normals.Update()

    output = normals.GetOutput()
    arr_normal = output.GetPointData().GetNormals()
    num = arr_normal.GetNumberOfTuples()

    f = codecs.open(outfile, "w")

    for index in range(num):
        for i in range(3):
            f.write("%.6f " % polyData.GetPoint(index)[i])
        for i in range(2):
            f.write("%.6f " % arr_normal.GetTuple(index)[i])
        f.write("%.6f\n" % arr_normal.GetTuple(index)[2])

    f.close()
Пример #7
0
points.Update()

# Create a sphere implicit function
sphere = vtk.vtkSphere()
sphere.SetCenter(0,0,0)
sphere.SetRadius(0.75)

# Extract points along sphere surface
extract = vtk.vtkFitImplicitFunction()
extract.SetInputConnection(points.GetOutputPort())
extract.SetImplicitFunction(sphere)
extract.SetThreshold(0.005)
extract.Update()

# Now generate normals from resulting points
norms = vtk.vtkPCANormalEstimation()
norms.SetInputConnection(extract.GetOutputPort())
norms.SetSampleSize(20)
norms.FlipNormalsOn()
norms.SetNormalOrientationToPoint()
norms.SetOrientationPoint(0,0,0)

# Time execution
timer = vtk.vtkTimerLog()
timer.StartTimer()
norms.Update()
timer.StopTimer()
time = timer.GetElapsedTime()
print("Points processed: {0}".format(NPts))
print("   Time to generate normals: {0}".format(time))
#print(hBin)
points.Update()

# Create a sphere implicit function
sphere = vtk.vtkSphere()
sphere.SetCenter(0,0,0)
sphere.SetRadius(0.75)

# Extract points along sphere surface
extract = vtk.vtkFitImplicitFunction()
extract.SetInputConnection(points.GetOutputPort())
extract.SetImplicitFunction(sphere)
extract.SetThreshold(0.005)
extract.Update()

# Now generate normals from resulting points
norms = vtk.vtkPCANormalEstimation()
norms.SetInputConnection(extract.GetOutputPort())
norms.SetSampleSize(20)
norms.FlipNormalsOn()
norms.SetNormalOrientationToGraphTraversal()

# Time execution
timer = vtk.vtkTimerLog()
timer.StartTimer()
norms.Update()
timer.StopTimer()
time = timer.GetElapsedTime()
print("Points processed: {0}".format(NPts))
print("   Time to generate normals: {0}".format(time))
#print(hBin)
#print(hBin.GetOutput())
Пример #9
0
def main(argv):
    colors = vtk.vtkNamedColors()

    polyData = ReadPolyData({True: argv[1], False: ""}[len(argv) > 1])

    bounds = polyData.GetBounds()

    rng = [0, 0, 0]

    for i in range(3):
        rng[i] = bounds[2 * i + 1] - bounds[2 * i]

    sampleSize = polyData.GetNumberOfPoints() * .00005
    if (sampleSize < 10):
        sampleSize = 10

    print("Sample size is: %d" % (sampleSize))
    normals = vtk.vtkPCANormalEstimation()
    normals.SetInputData(polyData)
    normals.SetSampleSize(sampleSize)
    normals.SetNormalOrientationToGraphTraversal()
    normals.FlipNormalsOn()
    print("Range: %f, %f, %f" % (rng[0], rng[1], rng[2]))

    dimension = 256
    dimension = 128

    radius = rng[0] / float(dimension) * 5  # ~5 voxels
    print("Radius: %f" % (radius))
    distance = vtk.vtkSignedDistance()
    distance.SetInputConnection(normals.GetOutputPort())
    distance.SetRadius(radius)
    distance.SetDimensions(dimension, dimension, dimension)
    distance.SetBounds(bounds[0] - rng[0] * 0.1, bounds[1] + rng[0] * 0.1,
                       bounds[2] - rng[1] * 0.1, bounds[3] + rng[1] * 0.1,
                       bounds[4] - rng[2] * 0.1, bounds[5] + rng[2] * 0.1)

    # Create a lookup table that consists of the full hue circle
    # (from HSV).
    belowRangeColor = colors.GetColor4d("Black")
    belowRangeColor[3] = 0.2
    aboveRangeColor = colors.GetColor4d("White")
    aboveRangeColor[3] = 0.2
    hueLut = vtk.vtkLookupTable()
    hueLut.SetTableRange(-0.99 * radius, 0.99 * radius)
    hueLut.SetHueRange(0.667, 0)
    hueLut.SetSaturationRange(1, 1)
    hueLut.SetValueRange(1, 1)
    hueLut.UseBelowRangeColorOn()
    hueLut.SetBelowRangeColor(belowRangeColor)
    hueLut.UseAboveRangeColorOn()
    hueLut.SetAboveRangeColor(aboveRangeColor)
    hueLut.SetNumberOfColors(5)
    hueLut.Build()
    last = hueLut.GetTableValue(4)
    hueLut.SetAboveRangeColor(last[0], last[1], last[2], 0)

    sagittalColors = vtk.vtkImageMapToColors()
    sagittalColors.SetInputConnection(distance.GetOutputPort())
    sagittalColors.SetLookupTable(hueLut)
    sagittalColors.Update()

    sagittal = vtk.vtkImageActor()
    sagittal.GetMapper().SetInputConnection(sagittalColors.GetOutputPort())
    sagittal.SetDisplayExtent(dimension // 2, dimension // 2, 0, dimension - 1,
                              0, dimension - 1)
    sagittal.ForceOpaqueOn()

    axialColors = vtk.vtkImageMapToColors()
    axialColors.SetInputConnection(distance.GetOutputPort())
    axialColors.SetLookupTable(hueLut)
    axialColors.Update()

    axial = vtk.vtkImageActor()
    axial.GetMapper().SetInputConnection(axialColors.GetOutputPort())
    axial.SetDisplayExtent(0, dimension - 1, 0, dimension - 1, dimension // 2,
                           dimension // 2)
    axial.ForceOpaqueOn()

    coronalColors = vtk.vtkImageMapToColors()
    coronalColors.SetInputConnection(distance.GetOutputPort())
    coronalColors.SetLookupTable(hueLut)
    coronalColors.Update()

    coronal = vtk.vtkImageActor()
    coronal.GetMapper().SetInputConnection(coronalColors.GetOutputPort())
    coronal.SetDisplayExtent(0, dimension - 1, dimension // 2, dimension // 2,
                             0, dimension - 1)
    coronal.ForceOpaqueOn()

    # Create a scalar bar
    scalarBar = vtk.vtkScalarBarActor()
    scalarBar.SetLookupTable(hueLut)
    scalarBar.SetTitle("Distance")
    scalarBar.SetNumberOfLabels(5)

    # Create graphics stuff
    #
    ren1 = vtk.vtkRenderer()
    ren1.SetBackground(colors.GetColor3d("CornflowerBlue"))

    renWin = vtk.vtkRenderWindow()
    renWin.AddRenderer(ren1)
    renWin.SetSize(600, 400)
    renWin.SetWindowName("SignedDistance")

    iren = vtk.vtkRenderWindowInteractor()
    iren.SetRenderWindow(renWin)

    # Add the actors to the renderer, set the background and size
    #
    ren1.AddActor(sagittal)
    ren1.AddActor(axial)
    ren1.AddActor(coronal)
    ren1.AddActor2D(scalarBar)

    # Generate an interesting view
    #
    ren1.ResetCamera()
    ren1.GetActiveCamera().Azimuth(120)
    ren1.GetActiveCamera().Elevation(30)
    ren1.GetActiveCamera().Dolly(1.5)
    ren1.ResetCameraClippingRange()

    renWin.Render()
    iren.Initialize()
    iren.Start()
    print("%f, %f" % (distance.GetOutput().GetScalarRange()[0],
                      distance.GetOutput().GetScalarRange()[1]))
    return distance