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 27 import vtkgdcm
28 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 31 from vtk.util import numpy_support
32 32  
33 33 import invesalius.constants as const
... ... @@ -69,20 +69,20 @@ def ResampleImage2D(imagedata, px=None, py=None, resolution_percentage = None,
69 69 dimensions = imagedata.GetDimensions()
70 70  
71 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 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 87 resample = vtk.vtkImageResample()
88 88 resample.SetInputData(imagedata)
... ... @@ -98,6 +98,35 @@ def ResampleImage2D(imagedata, px=None, py=None, resolution_percentage = None,
98 98  
99 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 130 def FixGantryTilt(matrix, spacing, tilt):
102 131 """
103 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 554 message = _("Generating multiplanar visualization...")
526 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 560 temp_file = tempfile.mktemp()
529 561  
530 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 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 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 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 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 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 575 elif orientation == 'SAGITTAL':
579   - array.shape = matrix.shape[0], matrix.shape[1]
580 576 # TODO: Verify if it's necessary to add the slices swapped only in
581 577 # sagittal rmi or only in # Rasiane's case or is necessary in all
582 578 # sagittal cases.
583   - matrix[:, :, n] = array
  579 + matrix[:, :, n] = im_array
584 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 584 matrix.flush()
591   - scalar_range = min_scalar, max_scalar
  585 + scalar_range = matrix.min(), matrix.max()
592 586  
593 587 return matrix, scalar_range, temp_file
594 588  
... ...