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