Commit cc5b70237c7104422a5c9ee70f37a7893367a2ad
1 parent
876d77a4
Exists in
master
and in
67 other branches
Fixed some memory leaks when generating a surface
Showing
2 changed files
with
116 additions
and
22 deletions
Show diff stats
invesalius/data/surface.py
| ... | ... | @@ -21,6 +21,7 @@ import multiprocessing |
| 21 | 21 | import os |
| 22 | 22 | import plistlib |
| 23 | 23 | import random |
| 24 | +import weakref | |
| 24 | 25 | |
| 25 | 26 | import vtk |
| 26 | 27 | import wx |
| ... | ... | @@ -474,132 +475,207 @@ class SurfaceManager(): |
| 474 | 475 | break |
| 475 | 476 | |
| 476 | 477 | polydata_append = vtk.vtkAppendPolyData() |
| 478 | + polydata_append.ReleaseDataFlagOn() | |
| 477 | 479 | t = n_pieces |
| 478 | 480 | while t: |
| 479 | 481 | filename_polydata = q_out.get() |
| 480 | 482 | |
| 481 | 483 | reader = vtk.vtkXMLPolyDataReader() |
| 482 | 484 | reader.SetFileName(filename_polydata) |
| 485 | + reader.ReleaseDataFlagOn() | |
| 483 | 486 | reader.Update() |
| 484 | - polydata_append.AddInput(reader.GetOutput()) | |
| 487 | + reader.GetOutput().ReleaseDataFlagOn() | |
| 488 | + | |
| 489 | + polydata = reader.GetOutput() | |
| 490 | + polydata.SetSource(None) | |
| 491 | + | |
| 492 | + polydata_append.AddInput(polydata) | |
| 493 | + del reader | |
| 494 | + del polydata | |
| 485 | 495 | t -= 1 |
| 486 | 496 | |
| 487 | 497 | polydata_append.Update() |
| 498 | + polydata_append.GetOutput().ReleaseDataFlagOn() | |
| 488 | 499 | polydata = polydata_append.GetOutput() |
| 500 | + #polydata.Register(None) | |
| 501 | + polydata.SetSource(None) | |
| 502 | + del polydata_append | |
| 489 | 503 | |
| 490 | 504 | if algorithm == u'Context aware smoothing': |
| 491 | 505 | normals = vtk.vtkPolyDataNormals() |
| 492 | - normals.AddObserver("ProgressEvent", lambda obj,evt: | |
| 493 | - UpdateProgress(obj, _("Generating 3D surface..."))) | |
| 506 | + normals_ref = weakref.ref(normals) | |
| 507 | + normals_ref().AddObserver("ProgressEvent", lambda obj,evt: | |
| 508 | + UpdateProgress(normals_ref(), _("Generating 3D surface..."))) | |
| 494 | 509 | normals.SetInput(polydata) |
| 510 | + normals.ReleaseDataFlagOn() | |
| 495 | 511 | #normals.SetFeatureAngle(80) |
| 496 | 512 | #normals.AutoOrientNormalsOn() |
| 497 | 513 | normals.ComputeCellNormalsOn() |
| 514 | + normals.GetOutput().ReleaseDataFlagOn() | |
| 498 | 515 | normals.Update() |
| 516 | + del polydata | |
| 499 | 517 | polydata = normals.GetOutput() |
| 518 | + polydata.SetSource(None) | |
| 519 | + del normals | |
| 500 | 520 | |
| 501 | 521 | clean = vtk.vtkCleanPolyData() |
| 502 | - clean.AddObserver("ProgressEvent", lambda obj,evt: | |
| 503 | - UpdateProgress(obj, _("Generating 3D surface..."))) | |
| 522 | + clean.ReleaseDataFlagOn() | |
| 523 | + clean.GetOutput().ReleaseDataFlagOn() | |
| 524 | + clean_ref = weakref.ref(clean) | |
| 525 | + clean_ref().AddObserver("ProgressEvent", lambda obj,evt: | |
| 526 | + UpdateProgress(clean_ref(), _("Generating 3D surface..."))) | |
| 504 | 527 | clean.SetInput(polydata) |
| 505 | 528 | clean.PointMergingOn() |
| 506 | 529 | clean.Update() |
| 530 | + | |
| 531 | + del polydata | |
| 507 | 532 | polydata = clean.GetOutput() |
| 533 | + polydata.SetSource(None) | |
| 534 | + del clean | |
| 508 | 535 | |
| 509 | 536 | polydata.BuildLinks() |
| 510 | 537 | polydata = ca_smoothing.ca_smoothing(polydata, options['angle'], |
| 511 | 538 | options['max distance'], |
| 512 | 539 | options['min weight'], |
| 513 | 540 | options['steps']) |
| 541 | + polydata.SetSource(None) | |
| 542 | + polydata.DebugOn() | |
| 514 | 543 | |
| 515 | 544 | else: |
| 516 | 545 | smoother = vtk.vtkWindowedSincPolyDataFilter() |
| 517 | - smoother.AddObserver("ProgressEvent", lambda obj,evt: | |
| 518 | - UpdateProgress(obj, _("Generating 3D surface..."))) | |
| 546 | + smoother_ref = weakref.ref(smoother) | |
| 547 | + smoother_ref().AddObserver("ProgressEvent", lambda obj,evt: | |
| 548 | + UpdateProgress(smoother_ref(), _("Generating 3D surface..."))) | |
| 519 | 549 | smoother.SetInput(polydata) |
| 520 | 550 | smoother.SetNumberOfIterations(smooth_iterations) |
| 521 | 551 | smoother.SetFeatureAngle(120) |
| 522 | 552 | smoother.SetEdgeAngle(90.0) |
| 523 | 553 | smoother.BoundarySmoothingOn() |
| 524 | 554 | smoother.SetPassBand(0.1) |
| 555 | + smoother.ReleaseDataFlagOn() | |
| 556 | + smoother.GetOutput().ReleaseDataFlagOn() | |
| 525 | 557 | #smoother.FeatureEdgeSmoothingOn() |
| 526 | 558 | #smoother.NonManifoldSmoothingOn() |
| 527 | 559 | #smoother.NormalizeCoordinatesOn() |
| 528 | 560 | smoother.Update() |
| 561 | + del polydata | |
| 529 | 562 | polydata = smoother.GetOutput() |
| 563 | + #polydata.Register(None) | |
| 564 | + polydata.SetSource(None) | |
| 565 | + del smoother | |
| 530 | 566 | |
| 531 | 567 | |
| 532 | 568 | if decimate_reduction: |
| 533 | 569 | print "Decimating", decimate_reduction |
| 534 | 570 | decimation = vtk.vtkQuadricDecimation() |
| 571 | + decimation.ReleaseDataFlagOn() | |
| 535 | 572 | decimation.SetInput(polydata) |
| 536 | 573 | decimation.SetTargetReduction(decimate_reduction) |
| 537 | - decimation.AddObserver("ProgressEvent", lambda obj,evt: | |
| 538 | - UpdateProgress(obj, _("Generating 3D surface..."))) | |
| 574 | + decimation_ref = weakref.ref(decimation) | |
| 575 | + decimation_ref().AddObserver("ProgressEvent", lambda obj,evt: | |
| 576 | + UpdateProgress(decimation_ref(), _("Generating 3D surface..."))) | |
| 539 | 577 | #decimation.PreserveTopologyOn() |
| 540 | 578 | #decimation.SplittingOff() |
| 541 | 579 | #decimation.BoundaryVertexDeletionOff() |
| 580 | + decimation.GetOutput().ReleaseDataFlagOn() | |
| 542 | 581 | decimation.Update() |
| 582 | + del polydata | |
| 543 | 583 | polydata = decimation.GetOutput() |
| 584 | + #polydata.Register(None) | |
| 585 | + polydata.SetSource(None) | |
| 586 | + del decimation | |
| 544 | 587 | |
| 545 | 588 | to_measure = polydata |
| 589 | + #to_measure.Register(None) | |
| 590 | + to_measure.SetSource(None) | |
| 546 | 591 | |
| 547 | 592 | if keep_largest: |
| 548 | 593 | conn = vtk.vtkPolyDataConnectivityFilter() |
| 549 | 594 | conn.SetInput(polydata) |
| 550 | 595 | conn.SetExtractionModeToLargestRegion() |
| 551 | - conn.AddObserver("ProgressEvent", lambda obj,evt: | |
| 552 | - UpdateProgress(obj, _("Generating 3D surface..."))) | |
| 596 | + conn_ref = weakref.ref(conn) | |
| 597 | + conn_ref().AddObserver("ProgressEvent", lambda obj,evt: | |
| 598 | + UpdateProgress(conn_ref(), _("Generating 3D surface..."))) | |
| 553 | 599 | conn.Update() |
| 600 | + conn.GetOutput().ReleaseDataFlagOn() | |
| 601 | + del polydata | |
| 554 | 602 | polydata = conn.GetOutput() |
| 603 | + #polydata.Register(None) | |
| 604 | + polydata.SetSource(None) | |
| 605 | + del conn | |
| 555 | 606 | |
| 556 | 607 | #Filter used to detect and fill holes. Only fill boundary edges holes. |
| 557 | 608 | #TODO: Hey! This piece of code is the same from |
| 558 | 609 | #polydata_utils.FillSurfaceHole, we need to review this. |
| 559 | 610 | if fill_holes: |
| 560 | 611 | filled_polydata = vtk.vtkFillHolesFilter() |
| 612 | + filled_polydata.ReleaseDataFlagOn() | |
| 561 | 613 | filled_polydata.SetInput(polydata) |
| 562 | 614 | filled_polydata.SetHoleSize(300) |
| 563 | - filled_polydata.AddObserver("ProgressEvent", lambda obj,evt: | |
| 564 | - UpdateProgress(obj, _("Generating 3D surface..."))) | |
| 615 | + filled_polydata_ref = weakref.ref(filled_polydata) | |
| 616 | + filled_polydata_ref().AddObserver("ProgressEvent", lambda obj,evt: | |
| 617 | + UpdateProgress(filled_polydata_ref(), _("Generating 3D surface..."))) | |
| 565 | 618 | filled_polydata.Update() |
| 619 | + filled_polydata.GetOutput().ReleaseDataFlagOn() | |
| 620 | + del polydata | |
| 566 | 621 | polydata = filled_polydata.GetOutput() |
| 622 | + #polydata.Register(None) | |
| 623 | + polydata.SetSource(None) | |
| 624 | + polydata.DebugOn() | |
| 625 | + del filled_polydata | |
| 567 | 626 | |
| 568 | 627 | normals = vtk.vtkPolyDataNormals() |
| 569 | - normals.AddObserver("ProgressEvent", lambda obj,evt: | |
| 570 | - UpdateProgress(obj, _("Generating 3D surface..."))) | |
| 628 | + normals.ReleaseDataFlagOn() | |
| 629 | + normals_ref = weakref.ref(normals) | |
| 630 | + normals_ref().AddObserver("ProgressEvent", lambda obj,evt: | |
| 631 | + UpdateProgress(normals_ref(), _("Generating 3D surface..."))) | |
| 571 | 632 | normals.SetInput(polydata) |
| 572 | 633 | normals.SetFeatureAngle(80) |
| 573 | 634 | normals.AutoOrientNormalsOn() |
| 635 | + normals.GetOutput().ReleaseDataFlagOn() | |
| 574 | 636 | normals.Update() |
| 637 | + del polydata | |
| 575 | 638 | polydata = normals.GetOutput() |
| 639 | + #polydata.Register(None) | |
| 640 | + polydata.SetSource(None) | |
| 641 | + del normals | |
| 576 | 642 | |
| 577 | 643 | # Improve performance |
| 578 | 644 | stripper = vtk.vtkStripper() |
| 579 | - stripper.AddObserver("ProgressEvent", lambda obj,evt: | |
| 580 | - UpdateProgress(obj, _("Generating 3D surface..."))) | |
| 645 | + stripper.ReleaseDataFlagOn() | |
| 646 | + stripper_ref = weakref.ref(stripper) | |
| 647 | + stripper_ref().AddObserver("ProgressEvent", lambda obj,evt: | |
| 648 | + UpdateProgress(stripper_ref(), _("Generating 3D surface..."))) | |
| 581 | 649 | stripper.SetInput(polydata) |
| 582 | 650 | stripper.PassThroughCellIdsOn() |
| 583 | 651 | stripper.PassThroughPointIdsOn() |
| 652 | + stripper.GetOutput().ReleaseDataFlagOn() | |
| 584 | 653 | stripper.Update() |
| 654 | + del polydata | |
| 585 | 655 | polydata = stripper.GetOutput() |
| 656 | + #polydata.Register(None) | |
| 657 | + polydata.SetSource(None) | |
| 658 | + del stripper | |
| 586 | 659 | |
| 587 | 660 | # Map polygonal data (vtkPolyData) to graphics primitives. |
| 588 | 661 | mapper = vtk.vtkPolyDataMapper() |
| 589 | 662 | mapper.SetInput(polydata) |
| 590 | 663 | mapper.ScalarVisibilityOff() |
| 664 | + mapper.ReleaseDataFlagOn() | |
| 591 | 665 | mapper.ImmediateModeRenderingOn() # improve performance |
| 592 | 666 | |
| 593 | 667 | # Represent an object (geometry & properties) in the rendered scene |
| 594 | 668 | actor = vtk.vtkActor() |
| 595 | 669 | actor.SetMapper(mapper) |
| 596 | - # Create Surface instance | |
| 670 | + del mapper | |
| 671 | + #Create Surface instance | |
| 597 | 672 | if overwrite: |
| 598 | 673 | surface = Surface(index = self.last_surface_index) |
| 599 | 674 | else: |
| 600 | 675 | surface = Surface(name=surface_name) |
| 601 | 676 | surface.colour = colour |
| 602 | 677 | surface.polydata = polydata |
| 678 | + del polydata | |
| 603 | 679 | |
| 604 | 680 | # Set actor colour and transparency |
| 605 | 681 | actor.GetProperty().SetColor(colour) |
| ... | ... | @@ -624,10 +700,13 @@ class SurfaceManager(): |
| 624 | 700 | |
| 625 | 701 | # The following lines have to be here, otherwise all volumes disappear |
| 626 | 702 | measured_polydata = vtk.vtkMassProperties() |
| 703 | + measured_polydata.ReleaseDataFlagOn() | |
| 627 | 704 | measured_polydata.SetInput(to_measure) |
| 628 | - volume = measured_polydata.GetVolume() | |
| 705 | + volume = float(measured_polydata.GetVolume()) | |
| 629 | 706 | surface.volume = volume |
| 630 | 707 | self.last_surface_index = surface.index |
| 708 | + del measured_polydata | |
| 709 | + del to_measure | |
| 631 | 710 | |
| 632 | 711 | Publisher.sendMessage('Load surface actor into viewer', actor) |
| 633 | 712 | |
| ... | ... | @@ -647,10 +726,10 @@ class SurfaceManager(): |
| 647 | 726 | #When you finalize the progress. The bar is cleaned. |
| 648 | 727 | UpdateProgress = vu.ShowProgress(1) |
| 649 | 728 | UpdateProgress(0, _("Ready")) |
| 650 | - Publisher.sendMessage('Update status text in GUI', | |
| 651 | - _("Ready")) | |
| 729 | + Publisher.sendMessage('Update status text in GUI', _("Ready")) | |
| 652 | 730 | |
| 653 | 731 | Publisher.sendMessage('End busy cursor') |
| 732 | + del actor | |
| 654 | 733 | |
| 655 | 734 | def UpdateSurfaceInterpolation(self, pub_evt): |
| 656 | 735 | interpolation = int(ses.Session().surface_interpolation) | ... | ... |
invesalius/data/surface_process.py
| ... | ... | @@ -52,7 +52,6 @@ class SurfaceProcess(multiprocessing.Process): |
| 52 | 52 | dtype=self.mask_dtype, |
| 53 | 53 | shape=self.mask_shape) |
| 54 | 54 | |
| 55 | - | |
| 56 | 55 | while 1: |
| 57 | 56 | roi = self.q_in.get() |
| 58 | 57 | if roi is None: |
| ... | ... | @@ -69,6 +68,7 @@ class SurfaceProcess(multiprocessing.Process): |
| 69 | 68 | 1:, 1:]) |
| 70 | 69 | image = converters.to_vtk(a_mask, self.spacing, roi.start, |
| 71 | 70 | "AXIAL") |
| 71 | + del a_mask | |
| 72 | 72 | else: |
| 73 | 73 | a_image = numpy.array(self.image[roi]) |
| 74 | 74 | |
| ... | ... | @@ -84,20 +84,28 @@ class SurfaceProcess(multiprocessing.Process): |
| 84 | 84 | gauss = vtk.vtkImageGaussianSmooth() |
| 85 | 85 | gauss.SetInput(image) |
| 86 | 86 | gauss.SetRadiusFactor(0.3) |
| 87 | + gauss.ReleaseDataFlagOn() | |
| 87 | 88 | gauss.Update() |
| 88 | 89 | |
| 90 | + del image | |
| 89 | 91 | image = gauss.GetOutput() |
| 92 | + del gauss | |
| 93 | + del a_mask | |
| 90 | 94 | else: |
| 91 | 95 | image = converters.to_vtk(a_image, self.spacing, roi.start, |
| 92 | 96 | "AXIAL") |
| 97 | + del a_image | |
| 93 | 98 | |
| 94 | 99 | flip = vtk.vtkImageFlip() |
| 95 | 100 | flip.SetInput(image) |
| 96 | 101 | flip.SetFilteredAxis(1) |
| 97 | 102 | flip.FlipAboutOriginOn() |
| 103 | + flip.ReleaseDataFlagOn() | |
| 98 | 104 | flip.Update() |
| 99 | 105 | |
| 106 | + del image | |
| 100 | 107 | image = flip.GetOutput() |
| 108 | + del flip | |
| 101 | 109 | |
| 102 | 110 | #filename = tempfile.mktemp(suffix='_%s.vti' % (self.pid)) |
| 103 | 111 | #writer = vtk.vtkXMLImageDataWriter() |
| ... | ... | @@ -122,9 +130,14 @@ class SurfaceProcess(multiprocessing.Process): |
| 122 | 130 | contour.ComputeScalarsOn() |
| 123 | 131 | contour.ComputeGradientsOn() |
| 124 | 132 | contour.ComputeNormalsOn() |
| 133 | + contour.ReleaseDataFlagOn() | |
| 134 | + contour.Update() | |
| 125 | 135 | #contour.AddObserver("ProgressEvent", lambda obj,evt: |
| 126 | 136 | # self.SendProgress(obj, _("Generating 3D surface..."))) |
| 127 | 137 | polydata = contour.GetOutput() |
| 138 | + del image | |
| 139 | + del contour | |
| 140 | + | |
| 128 | 141 | #else: #mode == "GRAYSCALE": |
| 129 | 142 | #mcubes = vtk.vtkMarchingCubes() |
| 130 | 143 | #mcubes.SetInput(flip.GetOutput()) |
| ... | ... | @@ -166,5 +179,7 @@ class SurfaceProcess(multiprocessing.Process): |
| 166 | 179 | writer.Write() |
| 167 | 180 | |
| 168 | 181 | print "Writing piece", roi, "to", filename |
| 182 | + del polydata | |
| 183 | + del writer | |
| 169 | 184 | |
| 170 | 185 | self.q_out.put(filename) | ... | ... |