Commit b702ed1b3a1542226c903c8241cc39f8f7b94d7c

Authored by tfmoraes
1 parent 2f2deade

ENH: Starting to work with masks.

* Added a threshold function
* starting without masks, need to create one in the starting
invesalius/data/mask.py
... ... @@ -85,5 +85,6 @@ class Mask():
85 85 Mask.general_index = index
86 86  
87 87 def create_mask(self, shape):
  88 + print "Creating a mask"
88 89 self.temp_file = tempfile.mktemp()
89 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 244 elif orientation == 'SAGITAL':
245 245 n_array = numpy.array(self.matrix[..., ..., slice_number])
246 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 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 264 def GetNumberOfSlices(self, orientation):
251 265 if orientation == 'AXIAL':
252 266 return self.matrix.shape[0]
... ... @@ -298,22 +312,30 @@ class Slice(object):
298 312 thresh_min, thresh_max = threshold_range
299 313  
300 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 337 # Update viewer
316   - ps.Publisher().sendMessage('Update slice viewer')
  338 + #ps.Publisher().sendMessage('Update slice viewer')
317 339  
318 340 # Update data notebook (GUI)
319 341 ps.Publisher().sendMessage('Set mask threshold in notebook',
... ... @@ -541,8 +563,6 @@ class Slice(object):
541 563 future_mask = Mask()
542 564 future_mask.create_mask(self.matrix.shape)
543 565  
544   -
545   - future_mask = Mask()
546 566 if colour:
547 567 future_mask.colour = colour
548 568 if opacity:
... ... @@ -594,6 +614,8 @@ class Slice(object):
594 614  
595 615 self.current_mask = future_mask
596 616  
  617 + print self.current_mask.matrix
  618 +
597 619 ps.Publisher().sendMessage('Change mask selected', future_mask.index)
598 620 ps.Publisher().sendMessage('Update slice viewer')
599 621  
... ... @@ -631,6 +653,52 @@ class Slice(object):
631 653  
632 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 702 def __build_mask(self, imagedata, create=True):
635 703 # create new mask instance and insert it into project
636 704 if create:
... ...