Commit 379a62714282b82147d84134864df41cc1975b1e

Authored by Thiago Franco de Moraes
1 parent 6d9e7e2a
Exists in master

Using the resample method to calculate the final image size when rescaling (closes #126)

Showing 1 changed file with 54 additions and 60 deletions   Show diff stats
invesalius/data/imagedata_utils.py
@@ -27,7 +27,7 @@ import vtk @@ -27,7 +27,7 @@ import vtk
27 import vtkgdcm 27 import vtkgdcm
28 from wx.lib.pubsub import pub as Publisher 28 from wx.lib.pubsub import pub as Publisher
29 29
30 -from scipy.ndimage import shift 30 +from scipy.ndimage import shift, zoom
31 from vtk.util import numpy_support 31 from vtk.util import numpy_support
32 32
33 import invesalius.constants as const 33 import invesalius.constants as const
@@ -69,20 +69,20 @@ def ResampleImage2D(imagedata, px=None, py=None, resolution_percentage = None, @@ -69,20 +69,20 @@ def ResampleImage2D(imagedata, px=None, py=None, resolution_percentage = None,
69 dimensions = imagedata.GetDimensions() 69 dimensions = imagedata.GetDimensions()
70 70
71 if resolution_percentage: 71 if resolution_percentage:
72 - px = math.ceil(dimensions[0] * resolution_percentage)  
73 - py = math.ceil(dimensions[1] * resolution_percentage)  
74 -  
75 - if abs(extent[1]-extent[3]) < abs(extent[3]-extent[5]):  
76 - f = extent[1]  
77 - elif abs(extent[1]-extent[5]) < abs(extent[1] - extent[3]):  
78 - f = extent[1]  
79 - elif abs(extent[3]-extent[5]) < abs(extent[1] - extent[3]):  
80 - f = extent[3] 72 + factor_x = resolution_percentage
  73 + factor_y = resolution_percentage
81 else: 74 else:
82 - f = extent[1] 75 + if abs(extent[1]-extent[3]) < abs(extent[3]-extent[5]):
  76 + f = extent[1]
  77 + elif abs(extent[1]-extent[5]) < abs(extent[1] - extent[3]):
  78 + f = extent[1]
  79 + elif abs(extent[3]-extent[5]) < abs(extent[1] - extent[3]):
  80 + f = extent[3]
  81 + else:
  82 + f = extent[1]
83 83
84 - factor_x = px/float(f+1)  
85 - factor_y = py/float(f+1) 84 + factor_x = px/float(f+1)
  85 + factor_y = py/float(f+1)
86 86
87 resample = vtk.vtkImageResample() 87 resample = vtk.vtkImageResample()
88 resample.SetInputData(imagedata) 88 resample.SetInputData(imagedata)
@@ -98,6 +98,35 @@ def ResampleImage2D(imagedata, px=None, py=None, resolution_percentage = None, @@ -98,6 +98,35 @@ def ResampleImage2D(imagedata, px=None, py=None, resolution_percentage = None,
98 98
99 return resample.GetOutput() 99 return resample.GetOutput()
100 100
  101 +
  102 +def resize_slice(im_array, resolution_percentage):
  103 + """
  104 + Uses ndimage.zoom to resize a slice.
  105 +
  106 + input:
  107 + im_array: slice as a numpy array.
  108 + resolution_percentage: percentage of resize.
  109 + """
  110 + out = zoom(im_array, resolution_percentage, im_array.dtype, order=2)
  111 + return out
  112 +
  113 +
  114 +def read_dcm_slice_as_np(filename, resolution_percentage=1.0):
  115 + """
  116 + read a dicom slice file and return the slice as numpy ndarray
  117 + """
  118 + dcm_reader = vtkgdcm.vtkGDCMImageReader()
  119 + dcm_reader.SetFileName(filename)
  120 + dcm_reader.Update()
  121 + image = dcm_reader.GetOutput()
  122 + if resolution_percentage < 1.0:
  123 + image = ResampleImage2D(image, resolution_percentage=resolution_percentage)
  124 + dx, dy, dz = image.GetDimensions()
  125 + im_array = numpy_support.vtk_to_numpy(image.GetPointData().GetScalars())
  126 + im_array.shape = dy, dx
  127 + return im_array
  128 +
  129 +
101 def FixGantryTilt(matrix, spacing, tilt): 130 def FixGantryTilt(matrix, spacing, tilt):
102 """ 131 """
103 Fix gantry tilt given a vtkImageData and the tilt value. Return new 132 Fix gantry tilt given a vtkImageData and the tilt value. Return new
@@ -525,70 +554,35 @@ def dcm2memmap(files, slice_size, orientation, resolution_percentage): @@ -525,70 +554,35 @@ def dcm2memmap(files, slice_size, orientation, resolution_percentage):
525 message = _("Generating multiplanar visualization...") 554 message = _("Generating multiplanar visualization...")
526 update_progress= vtk_utils.ShowProgress(len(files) - 1, dialog_type = "ProgressDialog") 555 update_progress= vtk_utils.ShowProgress(len(files) - 1, dialog_type = "ProgressDialog")
527 556
  557 + first_slice = read_dcm_slice_as_np(files[0], resolution_percentage)
  558 + slice_size = first_slice.shape[::-1]
  559 +
528 temp_file = tempfile.mktemp() 560 temp_file = tempfile.mktemp()
529 561
530 if orientation == 'SAGITTAL': 562 if orientation == 'SAGITTAL':
531 - if resolution_percentage == 1.0:  
532 - shape = slice_size[0], slice_size[1], len(files)  
533 - else:  
534 - shape = int(math.ceil(slice_size[0]*resolution_percentage)),\  
535 - int(math.ceil(slice_size[1]*resolution_percentage)), len(files)  
536 - 563 + shape = slice_size[0], slice_size[1], len(files)
537 elif orientation == 'CORONAL': 564 elif orientation == 'CORONAL':
538 - if resolution_percentage == 1.0:  
539 - shape = slice_size[1], len(files), slice_size[0]  
540 - else:  
541 - shape = int(math.ceil(slice_size[1]*resolution_percentage)), len(files),\  
542 - int(math.ceil(slice_size[0]*resolution_percentage)) 565 + shape = slice_size[1], len(files), slice_size[0]
543 else: 566 else:
544 - if resolution_percentage == 1.0:  
545 - shape = len(files), slice_size[1], slice_size[0]  
546 - else:  
547 - shape = len(files), int(math.ceil(slice_size[1]*resolution_percentage)),\  
548 - int(math.ceil(slice_size[0]*resolution_percentage)) 567 + shape = len(files), slice_size[1], slice_size[0]
549 568
550 matrix = numpy.memmap(temp_file, mode='w+', dtype='int16', shape=shape) 569 matrix = numpy.memmap(temp_file, mode='w+', dtype='int16', shape=shape)
551 - dcm_reader = vtkgdcm.vtkGDCMImageReader()  
552 - cont = 0  
553 - max_scalar = None  
554 - min_scalar = None  
555 -  
556 for n, f in enumerate(files): 570 for n, f in enumerate(files):
557 - dcm_reader.SetFileName(f)  
558 - dcm_reader.Update()  
559 - image = dcm_reader.GetOutput()  
560 -  
561 - if resolution_percentage != 1.0:  
562 - image_resized = ResampleImage2D(image, px=None, py=None,\  
563 - resolution_percentage = resolution_percentage, update_progress = None)  
564 -  
565 - image = image_resized  
566 -  
567 - min_aux, max_aux = image.GetScalarRange()  
568 - if min_scalar is None or min_aux < min_scalar:  
569 - min_scalar = min_aux  
570 -  
571 - if max_scalar is None or max_aux > max_scalar:  
572 - max_scalar = max_aux 571 + im_array = read_dcm_slice_as_np(f, resolution_percentage)
573 572
574 - array = numpy_support.vtk_to_numpy(image.GetPointData().GetScalars())  
575 if orientation == 'CORONAL': 573 if orientation == 'CORONAL':
576 - array.shape = matrix.shape[0], matrix.shape[2]  
577 - matrix[:, shape[1] - n - 1, :] = array 574 + matrix[:, shape[1] - n - 1, :] = im_array
578 elif orientation == 'SAGITTAL': 575 elif orientation == 'SAGITTAL':
579 - array.shape = matrix.shape[0], matrix.shape[1]  
580 # TODO: Verify if it's necessary to add the slices swapped only in 576 # TODO: Verify if it's necessary to add the slices swapped only in
581 # sagittal rmi or only in # Rasiane's case or is necessary in all 577 # sagittal rmi or only in # Rasiane's case or is necessary in all
582 # sagittal cases. 578 # sagittal cases.
583 - matrix[:, :, n] = array 579 + matrix[:, :, n] = im_array
584 else: 580 else:
585 - array.shape = matrix.shape[1], matrix.shape[2]  
586 - matrix[n] = array  
587 - update_progress(cont,message)  
588 - cont += 1 581 + matrix[n] = im_array
  582 + update_progress(n, message)
589 583
590 matrix.flush() 584 matrix.flush()
591 - scalar_range = min_scalar, max_scalar 585 + scalar_range = matrix.min(), matrix.max()
592 586
593 return matrix, scalar_range, temp_file 587 return matrix, scalar_range, temp_file
594 588