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