Commit b702ed1b3a1542226c903c8241cc39f8f7b94d7c
1 parent
2f2deade
Exists in
master
and in
67 other branches
ENH: Starting to work with masks.
* Added a threshold function * starting without masks, need to create one in the starting
Showing
2 changed files
with
86 additions
and
17 deletions
Show diff stats
invesalius/data/mask.py
@@ -85,5 +85,6 @@ class Mask(): | @@ -85,5 +85,6 @@ class Mask(): | ||
85 | Mask.general_index = index | 85 | Mask.general_index = index |
86 | 86 | ||
87 | def create_mask(self, shape): | 87 | def create_mask(self, shape): |
88 | + print "Creating a mask" | ||
88 | self.temp_file = tempfile.mktemp() | 89 | self.temp_file = tempfile.mktemp() |
89 | self.matrix = numpy.memmap(self.temp_file, mode='w+', dtype='uint8', shape=shape) | 90 | self.matrix = numpy.memmap(self.temp_file, mode='w+', dtype='uint8', shape=shape) |
invesalius/data/slice_.py
@@ -244,9 +244,23 @@ class Slice(object): | @@ -244,9 +244,23 @@ class Slice(object): | ||
244 | elif orientation == 'SAGITAL': | 244 | elif orientation == 'SAGITAL': |
245 | n_array = numpy.array(self.matrix[..., ..., slice_number]) | 245 | n_array = numpy.array(self.matrix[..., ..., slice_number]) |
246 | image = iu.to_vtk(n_array, self.spacing, slice_number, orientation) | 246 | image = iu.to_vtk(n_array, self.spacing, slice_number, orientation) |
247 | - image = self.do_ww_wl(image) | 247 | + if self.current_mask and self.current_mask.is_shown: |
248 | + mask = self.GetSlicesMask(orientation, slice_number) | ||
249 | + image = self.do_blend(self.do_ww_wl(image), mask) | ||
250 | + else: | ||
251 | + image = self.do_ww_wl(image) | ||
248 | return image | 252 | return image |
249 | 253 | ||
254 | + def GetSlicesMask(self, orientation, slice_number): | ||
255 | + if orientation == 'AXIAL': | ||
256 | + n_mask = numpy.array(self.current_mask.matrix[slice_number]) | ||
257 | + elif orientation == 'CORONAL': | ||
258 | + n_mask = numpy.array(self.current_mask.matrix[..., slice_number, ...]) | ||
259 | + elif orientation == 'SAGITAL': | ||
260 | + n_mask = numpy.array(self.current_mask.matrix[..., ..., slice_number]) | ||
261 | + mask = iu.to_vtk(n_mask, self.spacing, slice_number, orientation) | ||
262 | + return self.do_colour_mask(mask) | ||
263 | + | ||
250 | def GetNumberOfSlices(self, orientation): | 264 | def GetNumberOfSlices(self, orientation): |
251 | if orientation == 'AXIAL': | 265 | if orientation == 'AXIAL': |
252 | return self.matrix.shape[0] | 266 | return self.matrix.shape[0] |
@@ -298,22 +312,30 @@ class Slice(object): | @@ -298,22 +312,30 @@ class Slice(object): | ||
298 | thresh_min, thresh_max = threshold_range | 312 | thresh_min, thresh_max = threshold_range |
299 | 313 | ||
300 | if self.current_mask.index == index: | 314 | if self.current_mask.index == index: |
301 | - # Update pipeline (this must be here, so pipeline is not broken) | ||
302 | - self.img_thresh_mask.SetInput(self.imagedata) | ||
303 | - self.img_thresh_mask.ThresholdBetween(float(thresh_min), | ||
304 | - float(thresh_max)) | ||
305 | - self.img_thresh_mask.Update() | ||
306 | - | ||
307 | - # Create imagedata copy so the pipeline is not broken | ||
308 | - imagedata = self.img_thresh_mask.GetOutput() | ||
309 | - self.current_mask.imagedata.DeepCopy(imagedata) | ||
310 | - self.current_mask.threshold_range = threshold_range | ||
311 | - | ||
312 | - # Update pipeline (this must be here, so pipeline is not broken) | ||
313 | - self.img_colours_mask.SetInput(self.current_mask.imagedata) | 315 | + ## Update pipeline (this must be here, so pipeline is not broken) |
316 | + #self.img_thresh_mask.SetInput(self.imagedata) | ||
317 | + #self.img_thresh_mask.ThresholdBetween(float(thresh_min), | ||
318 | + #float(thresh_max)) | ||
319 | + #self.img_thresh_mask.Update() | ||
320 | + | ||
321 | + ## Create imagedata copy so the pipeline is not broken | ||
322 | + #imagedata = self.img_thresh_mask.GetOutput() | ||
323 | + #self.current_mask.imagedata.DeepCopy(imagedata) | ||
324 | + #self.current_mask.threshold_range = threshold_range | ||
325 | + | ||
326 | + ## Update pipeline (this must be here, so pipeline is not broken) | ||
327 | + #self.img_colours_mask.SetInput(self.current_mask.imagedata) | ||
328 | + | ||
329 | + # TODO: find out a better way to do threshold | ||
330 | + for n, slice_ in enumerate(self.matrix): | ||
331 | + m = numpy.ones(slice_.shape, self.current_mask.matrix.dtype) | ||
332 | + m[slice_ < thresh_min] = 0 | ||
333 | + m[slice_ > thresh_max] = 0 | ||
334 | + m[m == 1] = 255 | ||
335 | + self.current_mask.matrix[n] = m | ||
314 | 336 | ||
315 | # Update viewer | 337 | # Update viewer |
316 | - ps.Publisher().sendMessage('Update slice viewer') | 338 | + #ps.Publisher().sendMessage('Update slice viewer') |
317 | 339 | ||
318 | # Update data notebook (GUI) | 340 | # Update data notebook (GUI) |
319 | ps.Publisher().sendMessage('Set mask threshold in notebook', | 341 | ps.Publisher().sendMessage('Set mask threshold in notebook', |
@@ -541,8 +563,6 @@ class Slice(object): | @@ -541,8 +563,6 @@ class Slice(object): | ||
541 | future_mask = Mask() | 563 | future_mask = Mask() |
542 | future_mask.create_mask(self.matrix.shape) | 564 | future_mask.create_mask(self.matrix.shape) |
543 | 565 | ||
544 | - | ||
545 | - future_mask = Mask() | ||
546 | if colour: | 566 | if colour: |
547 | future_mask.colour = colour | 567 | future_mask.colour = colour |
548 | if opacity: | 568 | if opacity: |
@@ -594,6 +614,8 @@ class Slice(object): | @@ -594,6 +614,8 @@ class Slice(object): | ||
594 | 614 | ||
595 | self.current_mask = future_mask | 615 | self.current_mask = future_mask |
596 | 616 | ||
617 | + print self.current_mask.matrix | ||
618 | + | ||
597 | ps.Publisher().sendMessage('Change mask selected', future_mask.index) | 619 | ps.Publisher().sendMessage('Change mask selected', future_mask.index) |
598 | ps.Publisher().sendMessage('Update slice viewer') | 620 | ps.Publisher().sendMessage('Update slice viewer') |
599 | 621 | ||
@@ -631,6 +653,52 @@ class Slice(object): | @@ -631,6 +653,52 @@ class Slice(object): | ||
631 | 653 | ||
632 | return colorer.GetOutput() | 654 | return colorer.GetOutput() |
633 | 655 | ||
656 | + def do_colour_mask(self, imagedata): | ||
657 | + scalar_range = int(imagedata.GetScalarRange()[1]) | ||
658 | + r, g, b = self.current_mask.colour | ||
659 | + | ||
660 | + # map scalar values into colors | ||
661 | + lut_mask = vtk.vtkLookupTable() | ||
662 | + lut_mask.SetNumberOfColors(255) | ||
663 | + lut_mask.SetHueRange(const.THRESHOLD_HUE_RANGE) | ||
664 | + lut_mask.SetSaturationRange(1, 1) | ||
665 | + lut_mask.SetValueRange(0, 1) | ||
666 | + lut_mask.SetNumberOfTableValues(256) | ||
667 | + lut_mask.SetTableValue(0, 0, 0, 0, 0.0) | ||
668 | + lut_mask.SetTableValue(1, 0, 0, 0, 0.0) | ||
669 | + lut_mask.SetTableValue(2, 0, 0, 0, 0.0) | ||
670 | + lut_mask.SetTableValue(255, r, g, b, 1.0) | ||
671 | + lut_mask.SetRampToLinear() | ||
672 | + lut_mask.Build() | ||
673 | + # self.lut_mask = lut_mask | ||
674 | + | ||
675 | + # map the input image through a lookup table | ||
676 | + img_colours_mask = vtk.vtkImageMapToColors() | ||
677 | + img_colours_mask.SetLookupTable(lut_mask) | ||
678 | + img_colours_mask.SetOutputFormatToRGBA() | ||
679 | + img_colours_mask.SetInput(imagedata) | ||
680 | + img_colours_mask.Update() | ||
681 | + # self.img_colours_mask = img_colours_mask | ||
682 | + | ||
683 | + return img_colours_mask.GetOutput() | ||
684 | + | ||
685 | + def do_blend(self, imagedata, mask): | ||
686 | + # blend both imagedatas, so it can be inserted into viewer | ||
687 | + print "Blending Spacing", imagedata.GetSpacing(), mask.GetSpacing() | ||
688 | + | ||
689 | + blend_imagedata = vtk.vtkImageBlend() | ||
690 | + blend_imagedata.SetBlendModeToNormal() | ||
691 | + # blend_imagedata.SetOpacity(0, 1.0) | ||
692 | + blend_imagedata.SetOpacity(1, 0.8) | ||
693 | + blend_imagedata.SetInput(imagedata) | ||
694 | + blend_imagedata.AddInput(mask) | ||
695 | + blend_imagedata.Update() | ||
696 | + | ||
697 | + # return colorer.GetOutput() | ||
698 | + | ||
699 | + return blend_imagedata.GetOutput() | ||
700 | + | ||
701 | + | ||
634 | def __build_mask(self, imagedata, create=True): | 702 | def __build_mask(self, imagedata, create=True): |
635 | # create new mask instance and insert it into project | 703 | # create new mask instance and insert it into project |
636 | if create: | 704 | if create: |