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) | ... | ... |