Commit cd0cef0954f13add478e94eb9795808562db9a0c
Committed by
GitHub
1 parent
8ba6ba8d
Exists in
master
Remove vtkgdcm (#201)
* generating thumbs only using gdcm + numpy * applying intercept slop * generating thumbnails and slices without vtkgdcmreader * Using numpy and gdcm in dicom_preview_panel * loading multiframe dicom * working with rgb dicoms * little improvements * removed all vtkgdcm importing * getting spacing from gdcmimagereader
Showing
7 changed files
with
114 additions
and
318 deletions
Show diff stats
invesalius/control.py
| ... | ... | @@ -824,7 +824,6 @@ class Controller(): |
| 824 | 824 | self.matrix, scalar_range, self.filename = image_utils.dcm2memmap(filelist, size, |
| 825 | 825 | orientation, resolution_percentage) |
| 826 | 826 | |
| 827 | - print(xyspacing, zspacing) | |
| 828 | 827 | if orientation == 'AXIAL': |
| 829 | 828 | spacing = xyspacing[0], xyspacing[1], zspacing |
| 830 | 829 | elif orientation == 'CORONAL': |
| ... | ... | @@ -832,7 +831,10 @@ class Controller(): |
| 832 | 831 | elif orientation == 'SAGITTAL': |
| 833 | 832 | spacing = zspacing, xyspacing[1], xyspacing[0] |
| 834 | 833 | else: |
| 835 | - self.matrix, spacing, scalar_range, self.filename = image_utils.dcmmf2memmap(filelist[0], orientation) | |
| 834 | + print(">>>>>> filelist", filelist) | |
| 835 | + self.matrix, scalar_range, spacing, self.filename = image_utils.dcmmf2memmap(filelist[0], orientation) | |
| 836 | + | |
| 837 | + print(">>>>>> spacing", spacing) | |
| 836 | 838 | |
| 837 | 839 | self.Slice = sl.Slice() |
| 838 | 840 | self.Slice.matrix = self.matrix | ... | ... |
invesalius/data/converters.py
| ... | ... | @@ -17,10 +17,13 @@ |
| 17 | 17 | # detalhes. |
| 18 | 18 | #-------------------------------------------------------------------------- |
| 19 | 19 | |
| 20 | -import numpy | |
| 20 | +import gdcm | |
| 21 | +import numpy as np | |
| 21 | 22 | import vtk |
| 23 | + | |
| 22 | 24 | from vtk.util import numpy_support |
| 23 | 25 | |
| 26 | + | |
| 24 | 27 | def to_vtk(n_array, spacing, slice_number, orientation, origin=(0, 0, 0), padding=(0, 0, 0)): |
| 25 | 28 | |
| 26 | 29 | if orientation == "SAGITTAL": |
| ... | ... | @@ -84,3 +87,40 @@ def np_rgba_to_vtk(n_array, spacing=(1.0, 1.0, 1.0)): |
| 84 | 87 | image.GetPointData().SetScalars(v_image) |
| 85 | 88 | |
| 86 | 89 | return image |
| 90 | + | |
| 91 | + | |
| 92 | +# Based on http://gdcm.sourceforge.net/html/ConvertNumpy_8py-example.html | |
| 93 | +def gdcm_to_numpy(image, apply_intercep_scale=True): | |
| 94 | + map_gdcm_np = { | |
| 95 | + gdcm.PixelFormat.UINT8 :np.uint8, | |
| 96 | + gdcm.PixelFormat.INT8 :np.int8, | |
| 97 | + #gdcm.PixelFormat.UINT12 :np.uint12, | |
| 98 | + #gdcm.PixelFormat.INT12 :np.int12, | |
| 99 | + gdcm.PixelFormat.UINT16 :np.uint16, | |
| 100 | + gdcm.PixelFormat.INT16 :np.int16, | |
| 101 | + gdcm.PixelFormat.UINT32 :np.uint32, | |
| 102 | + gdcm.PixelFormat.INT32 :np.int32, | |
| 103 | + #gdcm.PixelFormat.FLOAT16:np.float16, | |
| 104 | + gdcm.PixelFormat.FLOAT32:np.float32, | |
| 105 | + gdcm.PixelFormat.FLOAT64:np.float64, | |
| 106 | + } | |
| 107 | + | |
| 108 | + pf = image.GetPixelFormat() | |
| 109 | + if image.GetNumberOfDimensions() == 3: | |
| 110 | + shape = image.GetDimension(2), image.GetDimension(1), image.GetDimension(0), pf.GetSamplesPerPixel() | |
| 111 | + else: | |
| 112 | + shape = image.GetDimension(1), image.GetDimension(0), pf.GetSamplesPerPixel() | |
| 113 | + dtype = map_gdcm_np[pf.GetScalarType()] | |
| 114 | + gdcm_array = image.GetBuffer() | |
| 115 | + np_array = np.frombuffer(gdcm_array.encode('utf-8', errors="surrogateescape"), dtype=dtype) | |
| 116 | + np_array.shape = shape | |
| 117 | + np_array = np_array.squeeze() | |
| 118 | + | |
| 119 | + if apply_intercep_scale: | |
| 120 | + shift = image.GetIntercept() | |
| 121 | + scale = image.GetSlope() | |
| 122 | + output = np.empty_like(np_array, np.int16) | |
| 123 | + output[:] = scale * np_array + shift | |
| 124 | + return output | |
| 125 | + else: | |
| 126 | + return np_array | ... | ... |
invesalius/data/imagedata_utils.py
| ... | ... | @@ -23,9 +23,10 @@ import sys |
| 23 | 23 | import tempfile |
| 24 | 24 | |
| 25 | 25 | import gdcm |
| 26 | +import imageio | |
| 26 | 27 | import numpy |
| 28 | +import numpy as np | |
| 27 | 29 | import vtk |
| 28 | -import vtkgdcm | |
| 29 | 30 | from wx.lib.pubsub import pub as Publisher |
| 30 | 31 | |
| 31 | 32 | from scipy.ndimage import shift, zoom |
| ... | ... | @@ -124,20 +125,15 @@ def resize_slice(im_array, resolution_percentage): |
| 124 | 125 | return out |
| 125 | 126 | |
| 126 | 127 | |
| 127 | -def read_dcm_slice_as_np(filename, resolution_percentage=1.0): | |
| 128 | - """ | |
| 129 | - read a dicom slice file and return the slice as numpy ndarray | |
| 130 | - """ | |
| 131 | - dcm_reader = vtkgdcm.vtkGDCMImageReader() | |
| 132 | - dcm_reader.SetFileName(filename) | |
| 133 | - dcm_reader.Update() | |
| 134 | - image = dcm_reader.GetOutput() | |
| 128 | +def read_dcm_slice_as_np2(filename, resolution_percentage=1.0): | |
| 129 | + reader = gdcm.ImageReader() | |
| 130 | + reader.SetFileName(filename) | |
| 131 | + reader.Read() | |
| 132 | + image = reader.GetImage() | |
| 133 | + output = converters.gdcm_to_numpy(image) | |
| 135 | 134 | if resolution_percentage < 1.0: |
| 136 | - image = ResampleImage2D(image, resolution_percentage=resolution_percentage) | |
| 137 | - dx, dy, dz = image.GetDimensions() | |
| 138 | - im_array = numpy_support.vtk_to_numpy(image.GetPointData().GetScalars()) | |
| 139 | - im_array.shape = dy, dx | |
| 140 | - return im_array | |
| 135 | + output = zoom(output, resolution_percentage) | |
| 136 | + return output | |
| 141 | 137 | |
| 142 | 138 | |
| 143 | 139 | def FixGantryTilt(matrix, spacing, tilt): |
| ... | ... | @@ -240,17 +236,6 @@ def View(imagedata): |
| 240 | 236 | import time |
| 241 | 237 | time.sleep(10) |
| 242 | 238 | |
| 243 | -def ViewGDCM(imagedata): | |
| 244 | - viewer = vtkgdcm.vtkImageColorViewer() | |
| 245 | - viewer.SetInput(reader.GetOutput()) | |
| 246 | - viewer.SetColorWindow(500.) | |
| 247 | - viewer.SetColorLevel(50.) | |
| 248 | - viewer.Render() | |
| 249 | - | |
| 250 | - import time | |
| 251 | - time.sleep(5) | |
| 252 | - | |
| 253 | - | |
| 254 | 239 | |
| 255 | 240 | def ExtractVOI(imagedata,xi,xf,yi,yf,zi,zf): |
| 256 | 241 | """ |
| ... | ... | @@ -265,267 +250,33 @@ def ExtractVOI(imagedata,xi,xf,yi,yf,zi,zf): |
| 265 | 250 | return voi.GetOutput() |
| 266 | 251 | |
| 267 | 252 | |
| 268 | -def create_dicom_thumbnails(filename, window=None, level=None): | |
| 269 | - rvtk = vtkgdcm.vtkGDCMImageReader() | |
| 270 | - rvtk.SetFileName(utils.encode(filename, const.FS_ENCODE)) | |
| 271 | - rvtk.Update() | |
| 272 | - | |
| 273 | - img = rvtk.GetOutput() | |
| 253 | +def create_dicom_thumbnails(image, window=None, level=None): | |
| 254 | + pf = image.GetPixelFormat() | |
| 255 | + np_image = converters.gdcm_to_numpy(image, pf.GetSamplesPerPixel() == 1) | |
| 274 | 256 | if window is None or level is None: |
| 275 | - _min, _max = img.GetScalarRange() | |
| 257 | + _min, _max = np_image.min(), np_image.max() | |
| 276 | 258 | window = _max - _min |
| 277 | 259 | level = _min + window / 2 |
| 278 | 260 | |
| 279 | - dx, dy, dz = img.GetDimensions() | |
| 280 | - | |
| 281 | - if dz > 1: | |
| 261 | + if image.GetNumberOfDimensions() >= 3: | |
| 282 | 262 | thumbnail_paths = [] |
| 283 | - for i in range(dz): | |
| 284 | - img_slice = ExtractVOI(img, 0, dx-1, 0, dy-1, i, i+1) | |
| 285 | - | |
| 286 | - colorer = vtk.vtkImageMapToWindowLevelColors() | |
| 287 | - colorer.SetInputData(img_slice) | |
| 288 | - colorer.SetWindow(window) | |
| 289 | - colorer.SetLevel(level) | |
| 290 | - colorer.SetOutputFormatToRGB() | |
| 291 | - colorer.Update() | |
| 292 | - | |
| 293 | - resample = vtk.vtkImageResample() | |
| 294 | - resample.SetInputData(colorer.GetOutput()) | |
| 295 | - resample.SetAxisMagnificationFactor ( 0, 0.25 ) | |
| 296 | - resample.SetAxisMagnificationFactor ( 1, 0.25 ) | |
| 297 | - resample.SetAxisMagnificationFactor ( 2, 1 ) | |
| 298 | - resample.Update() | |
| 299 | - | |
| 300 | - thumbnail_path = tempfile.mktemp() | |
| 301 | - | |
| 302 | - write_png = vtk.vtkPNGWriter() | |
| 303 | - write_png.SetInputData(resample.GetOutput()) | |
| 304 | - write_png.SetFileName(thumbnail_path) | |
| 305 | - write_png.Write() | |
| 306 | - | |
| 263 | + for i in range(np_image.shape[0]): | |
| 264 | + thumb_image = zoom(np_image[i], 0.25) | |
| 265 | + thumb_image = np.array(get_LUT_value_255(thumb_image, window, level), dtype=np.uint8) | |
| 266 | + thumbnail_path = tempfile.mktemp(prefix='thumb_', suffix='.png') | |
| 267 | + imageio.imsave(thumbnail_path, thumb_image) | |
| 307 | 268 | thumbnail_paths.append(thumbnail_path) |
| 308 | - | |
| 309 | 269 | return thumbnail_paths |
| 310 | 270 | else: |
| 311 | - colorer = vtk.vtkImageMapToWindowLevelColors() | |
| 312 | - colorer.SetInputData(img) | |
| 313 | - colorer.SetWindow(window) | |
| 314 | - colorer.SetLevel(level) | |
| 315 | - colorer.SetOutputFormatToRGB() | |
| 316 | - colorer.Update() | |
| 317 | - | |
| 318 | - resample = vtk.vtkImageResample() | |
| 319 | - resample.SetInputData(colorer.GetOutput()) | |
| 320 | - resample.SetAxisMagnificationFactor ( 0, 0.25 ) | |
| 321 | - resample.SetAxisMagnificationFactor ( 1, 0.25 ) | |
| 322 | - resample.SetAxisMagnificationFactor ( 2, 1 ) | |
| 323 | - resample.Update() | |
| 324 | - | |
| 325 | - thumbnail_path = tempfile.mktemp() | |
| 326 | - | |
| 327 | - write_png = vtk.vtkPNGWriter() | |
| 328 | - write_png.SetInputData(resample.GetOutput()) | |
| 329 | - write_png.SetFileName(thumbnail_path) | |
| 330 | - write_png.Write() | |
| 331 | - | |
| 332 | - return thumbnail_path | |
| 333 | - | |
| 334 | - | |
| 335 | -def CreateImageData(filelist, zspacing, xyspacing,size, | |
| 336 | - bits, use_dcmspacing): | |
| 337 | - message = _("Generating multiplanar visualization...") | |
| 338 | - | |
| 339 | - if not const.VTK_WARNING: | |
| 340 | - log_path = os.path.join(inv_paths.USER_LOG_DIR, 'vtkoutput.txt') | |
| 341 | - fow = vtk.vtkFileOutputWindow() | |
| 342 | - fow.SetFileName(log_path) | |
| 343 | - ow = vtk.vtkOutputWindow() | |
| 344 | - ow.SetInstance(fow) | |
| 345 | - | |
| 346 | - x,y = size | |
| 347 | - px, py = utils.predict_memory(len(filelist), x, y, bits) | |
| 348 | - | |
| 349 | - utils.debug("Image Resized to >>> %f x %f" % (px, py)) | |
| 350 | - | |
| 351 | - if (x == px) and (y == py): | |
| 352 | - const.REDUCE_IMAGEDATA_QUALITY = 0 | |
| 353 | - else: | |
| 354 | - const.REDUCE_IMAGEDATA_QUALITY = 1 | |
| 355 | - | |
| 356 | - if not(const.REDUCE_IMAGEDATA_QUALITY): | |
| 357 | - update_progress= vtk_utils.ShowProgress(1, dialog_type = "ProgressDialog") | |
| 358 | - | |
| 359 | - array = vtk.vtkStringArray() | |
| 360 | - for x in range(len(filelist)): | |
| 361 | - array.InsertValue(x,filelist[x]) | |
| 362 | - | |
| 363 | - reader = vtkgdcm.vtkGDCMImageReader() | |
| 364 | - reader.SetFileNames(array) | |
| 365 | - reader.AddObserver("ProgressEvent", lambda obj,evt: | |
| 366 | - update_progress(reader,message)) | |
| 367 | - reader.Update() | |
| 368 | - | |
| 369 | - # The zpacing is a DicomGroup property, so we need to set it | |
| 370 | - imagedata = vtk.vtkImageData() | |
| 371 | - imagedata.DeepCopy(reader.GetOutput()) | |
| 372 | - if (use_dcmspacing): | |
| 373 | - spacing = xyspacing | |
| 374 | - spacing[2] = zspacing | |
| 375 | - else: | |
| 376 | - spacing = imagedata.GetSpacing() | |
| 377 | - | |
| 378 | - imagedata.SetSpacing(spacing[0], spacing[1], zspacing) | |
| 379 | - else: | |
| 380 | - | |
| 381 | - update_progress= vtk_utils.ShowProgress(2*len(filelist), | |
| 382 | - dialog_type = "ProgressDialog") | |
| 383 | - | |
| 384 | - # Reformat each slice and future append them | |
| 385 | - appender = vtk.vtkImageAppend() | |
| 386 | - appender.SetAppendAxis(2) #Define Stack in Z | |
| 387 | - | |
| 388 | - | |
| 389 | - # Reformat each slice | |
| 390 | - for x in range(len(filelist)): | |
| 391 | - # TODO: We need to check this automatically according | |
| 392 | - # to each computer's architecture | |
| 393 | - # If the resolution of the matrix is too large | |
| 394 | - reader = vtkgdcm.vtkGDCMImageReader() | |
| 395 | - reader.SetFileName(filelist[x]) | |
| 396 | - reader.AddObserver("ProgressEvent", lambda obj,evt: | |
| 397 | - update_progress(reader,message)) | |
| 398 | - reader.Update() | |
| 399 | - | |
| 400 | - if (use_dcmspacing): | |
| 401 | - spacing = xyspacing | |
| 402 | - spacing[2] = zspacing | |
| 403 | - else: | |
| 404 | - spacing = reader.GetOutput().GetSpacing() | |
| 405 | - | |
| 406 | - tmp_image = vtk.vtkImageData() | |
| 407 | - tmp_image.DeepCopy(reader.GetOutput()) | |
| 408 | - tmp_image.SetSpacing(spacing[0], spacing[1], zspacing) | |
| 409 | - tmp_image.Update() | |
| 410 | - | |
| 411 | - #Resample image in x,y dimension | |
| 412 | - slice_imagedata = ResampleImage2D(tmp_image, px, py, update_progress) | |
| 413 | - #Stack images in Z axes | |
| 414 | - appender.AddInput(slice_imagedata) | |
| 415 | - #appender.AddObserver("ProgressEvent", lambda obj,evt:update_progress(appender)) | |
| 416 | - appender.Update() | |
| 417 | - | |
| 418 | - spacing = appender.GetOutput().GetSpacing() | |
| 419 | - | |
| 420 | - # The zpacing is a DicomGroup property, so we need to set it | |
| 421 | - imagedata = vtk.vtkImageData() | |
| 422 | - imagedata.DeepCopy(appender.GetOutput()) | |
| 423 | - imagedata.SetSpacing(spacing[0], spacing[1], zspacing) | |
| 424 | - | |
| 425 | - imagedata.AddObserver("ProgressEvent", lambda obj,evt: | |
| 426 | - update_progress(imagedata,message)) | |
| 427 | - imagedata.Update() | |
| 428 | - | |
| 429 | - return imagedata | |
| 430 | - | |
| 431 | - | |
| 432 | -class ImageCreator: | |
| 433 | - def __init__(self): | |
| 434 | - self.running = True | |
| 435 | - Publisher.subscribe(self.CancelImageDataLoad, "Cancel DICOM load") | |
| 436 | - | |
| 437 | - def CancelImageDataLoad(self, evt_pusub): | |
| 438 | - utils.debug("Canceling") | |
| 439 | - self.running = False | |
| 440 | - | |
| 441 | - def CreateImageData(self, filelist, zspacing, size, bits): | |
| 442 | - message = _("Generating multiplanar visualization...") | |
| 443 | - | |
| 444 | - if not const.VTK_WARNING: | |
| 445 | - log_path = os.path.join(inv_paths.USER_LOG_DIR, 'vtkoutput.txt') | |
| 446 | - fow = vtk.vtkFileOutputWindow() | |
| 447 | - fow.SetFileName(log_path) | |
| 448 | - ow = vtk.vtkOutputWindow() | |
| 449 | - ow.SetInstance(fow) | |
| 450 | - | |
| 451 | - x,y = size | |
| 452 | - px, py = utils.predict_memory(len(filelist), x, y, bits) | |
| 453 | - utils.debug("Image Resized to >>> %f x %f" % (px, py)) | |
| 454 | - | |
| 455 | - if (x == px) and (y == py): | |
| 456 | - const.REDUCE_IMAGEDATA_QUALITY = 0 | |
| 271 | + thumbnail_path = tempfile.mktemp(prefix='thumb_', suffix='.png') | |
| 272 | + if pf.GetSamplesPerPixel() == 1: | |
| 273 | + thumb_image = zoom(np_image, 0.25) | |
| 274 | + thumb_image = np.array(get_LUT_value_255(thumb_image, window, level), dtype=np.uint8) | |
| 457 | 275 | else: |
| 458 | - const.REDUCE_IMAGEDATA_QUALITY = 1 | |
| 459 | - | |
| 460 | - if not(const.REDUCE_IMAGEDATA_QUALITY): | |
| 461 | - update_progress= vtk_utils.ShowProgress(1, dialog_type = "ProgressDialog") | |
| 462 | - | |
| 463 | - array = vtk.vtkStringArray() | |
| 464 | - for x in range(len(filelist)): | |
| 465 | - if not self.running: | |
| 466 | - return False | |
| 467 | - array.InsertValue(x,filelist[x]) | |
| 468 | - | |
| 469 | - if not self.running: | |
| 470 | - return False | |
| 471 | - reader = vtkgdcm.vtkGDCMImageReader() | |
| 472 | - reader.SetFileNames(array) | |
| 473 | - reader.AddObserver("ProgressEvent", lambda obj,evt: | |
| 474 | - update_progress(reader,message)) | |
| 475 | - reader.Update() | |
| 476 | - | |
| 477 | - if not self.running: | |
| 478 | - reader.AbortExecuteOn() | |
| 479 | - return False | |
| 480 | - # The zpacing is a DicomGroup property, so we need to set it | |
| 481 | - imagedata = vtk.vtkImageData() | |
| 482 | - imagedata.DeepCopy(reader.GetOutput()) | |
| 483 | - spacing = imagedata.GetSpacing() | |
| 484 | - imagedata.SetSpacing(spacing[0], spacing[1], zspacing) | |
| 485 | - else: | |
| 486 | - | |
| 487 | - update_progress= vtk_utils.ShowProgress(2*len(filelist), | |
| 488 | - dialog_type = "ProgressDialog") | |
| 489 | - | |
| 490 | - # Reformat each slice and future append them | |
| 491 | - appender = vtk.vtkImageAppend() | |
| 492 | - appender.SetAppendAxis(2) #Define Stack in Z | |
| 493 | - | |
| 494 | - | |
| 495 | - # Reformat each slice | |
| 496 | - for x in range(len(filelist)): | |
| 497 | - # TODO: We need to check this automatically according | |
| 498 | - # to each computer's architecture | |
| 499 | - # If the resolution of the matrix is too large | |
| 500 | - if not self.running: | |
| 501 | - return False | |
| 502 | - reader = vtkgdcm.vtkGDCMImageReader() | |
| 503 | - reader.SetFileName(filelist[x]) | |
| 504 | - reader.AddObserver("ProgressEvent", lambda obj,evt: | |
| 505 | - update_progress(reader,message)) | |
| 506 | - reader.Update() | |
| 507 | - | |
| 508 | - #Resample image in x,y dimension | |
| 509 | - slice_imagedata = ResampleImage2D(reader.GetOutput(), px, py, update_progress) | |
| 510 | - #Stack images in Z axes | |
| 511 | - appender.AddInput(slice_imagedata) | |
| 512 | - #appender.AddObserver("ProgressEvent", lambda obj,evt:update_progress(appender)) | |
| 513 | - appender.Update() | |
| 514 | - | |
| 515 | - # The zpacing is a DicomGroup property, so we need to set it | |
| 516 | - if not self.running: | |
| 517 | - return False | |
| 518 | - imagedata = vtk.vtkImageData() | |
| 519 | - imagedata.DeepCopy(appender.GetOutput()) | |
| 520 | - spacing = imagedata.GetSpacing() | |
| 521 | - | |
| 522 | - imagedata.SetSpacing(spacing[0], spacing[1], zspacing) | |
| 523 | - | |
| 524 | - imagedata.AddObserver("ProgressEvent", lambda obj,evt: | |
| 525 | - update_progress(imagedata,message)) | |
| 526 | - imagedata.Update() | |
| 276 | + thumb_image = zoom(np_image, (0.25, 0.25, 1)) | |
| 277 | + imageio.imsave(thumbnail_path, thumb_image) | |
| 278 | + return thumbnail_path | |
| 527 | 279 | |
| 528 | - return imagedata | |
| 529 | 280 | |
| 530 | 281 | def bitmap2memmap(files, slice_size, orientation, spacing, resolution_percentage): |
| 531 | 282 | """ |
| ... | ... | @@ -626,7 +377,6 @@ def bitmap2memmap(files, slice_size, orientation, spacing, resolution_percentage |
| 626 | 377 | return matrix, scalar_range, temp_file |
| 627 | 378 | |
| 628 | 379 | |
| 629 | - | |
| 630 | 380 | def dcm2memmap(files, slice_size, orientation, resolution_percentage): |
| 631 | 381 | """ |
| 632 | 382 | From a list of dicom files it creates memmap file in the temp folder and |
| ... | ... | @@ -635,7 +385,7 @@ def dcm2memmap(files, slice_size, orientation, resolution_percentage): |
| 635 | 385 | message = _("Generating multiplanar visualization...") |
| 636 | 386 | update_progress= vtk_utils.ShowProgress(len(files) - 1, dialog_type = "ProgressDialog") |
| 637 | 387 | |
| 638 | - first_slice = read_dcm_slice_as_np(files[0], resolution_percentage) | |
| 388 | + first_slice = read_dcm_slice_as_np2(files[0], resolution_percentage) | |
| 639 | 389 | slice_size = first_slice.shape[::-1] |
| 640 | 390 | |
| 641 | 391 | temp_file = tempfile.mktemp() |
| ... | ... | @@ -649,7 +399,7 @@ def dcm2memmap(files, slice_size, orientation, resolution_percentage): |
| 649 | 399 | |
| 650 | 400 | matrix = numpy.memmap(temp_file, mode='w+', dtype='int16', shape=shape) |
| 651 | 401 | for n, f in enumerate(files): |
| 652 | - im_array = read_dcm_slice_as_np(f, resolution_percentage) | |
| 402 | + im_array = read_dcm_slice_as_np2(f, resolution_percentage)[::-1] | |
| 653 | 403 | |
| 654 | 404 | if orientation == 'CORONAL': |
| 655 | 405 | matrix[:, shape[1] - n - 1, :] = im_array |
| ... | ... | @@ -669,37 +419,35 @@ def dcm2memmap(files, slice_size, orientation, resolution_percentage): |
| 669 | 419 | |
| 670 | 420 | |
| 671 | 421 | def dcmmf2memmap(dcm_file, orientation): |
| 672 | - r = vtkgdcm.vtkGDCMImageReader() | |
| 673 | - r.SetFileName(dcm_file) | |
| 674 | - r.Update() | |
| 675 | - | |
| 422 | + reader = gdcm.ImageReader() | |
| 423 | + reader.SetFileName(dcm_file) | |
| 424 | + reader.Read() | |
| 425 | + image = reader.GetImage() | |
| 426 | + xs, ys, zs = image.GetSpacing() | |
| 427 | + pf = image.GetPixelFormat() | |
| 428 | + np_image = converters.gdcm_to_numpy(image, pf.GetSamplesPerPixel() == 1) | |
| 676 | 429 | temp_file = tempfile.mktemp() |
| 677 | - | |
| 678 | - o = r.GetOutput() | |
| 679 | - x, y, z = o.GetDimensions() | |
| 680 | - spacing = o.GetSpacing() | |
| 681 | - | |
| 682 | - matrix = numpy.memmap(temp_file, mode='w+', dtype='int16', shape=(z, y, x)) | |
| 683 | - | |
| 684 | - d = numpy_support.vtk_to_numpy(o.GetPointData().GetScalars()) | |
| 685 | - d.shape = z, y, x | |
| 430 | + matrix = numpy.memmap(temp_file, mode='w+', dtype='int16', shape=np_image.shape) | |
| 431 | + print("Number of dimensions", np_image.shape) | |
| 432 | + z, y, x = np_image.shape | |
| 686 | 433 | if orientation == 'CORONAL': |
| 434 | + spacing = xs, zs, ys | |
| 687 | 435 | matrix.shape = y, z, x |
| 688 | 436 | for n in range(z): |
| 689 | - matrix[:, n, :] = d[n] | |
| 437 | + matrix[:, n, :] = np_image[n][::-1] | |
| 690 | 438 | elif orientation == 'SAGITTAL': |
| 691 | - matrix.shape = x, z, y | |
| 439 | + spacing = zs, ys, xs | |
| 440 | + matrix.shape = y, x, z | |
| 692 | 441 | for n in range(z): |
| 693 | - matrix[:, :, n] = d[n] | |
| 442 | + matrix[:, :, n] = np_image[n][::-1] | |
| 694 | 443 | else: |
| 695 | - matrix[:] = d | |
| 444 | + spacing = xs, ys, zs | |
| 445 | + matrix[:] = np_image[:, ::-1, :] | |
| 696 | 446 | |
| 697 | 447 | matrix.flush() |
| 698 | 448 | scalar_range = matrix.min(), matrix.max() |
| 699 | 449 | |
| 700 | - print("ORIENTATION", orientation) | |
| 701 | - | |
| 702 | - return matrix, spacing, scalar_range, temp_file | |
| 450 | + return matrix, scalar_range, spacing, temp_file | |
| 703 | 451 | |
| 704 | 452 | |
| 705 | 453 | def img2memmap(group): |
| ... | ... | @@ -753,3 +501,14 @@ def imgnormalize(data, srange=(0, 255)): |
| 753 | 501 | datan = datan.astype(numpy.int16) |
| 754 | 502 | |
| 755 | 503 | return datan |
| 504 | + | |
| 505 | + | |
| 506 | +def get_LUT_value_255(data, window, level): | |
| 507 | + shape = data.shape | |
| 508 | + data_ = data.ravel() | |
| 509 | + data = np.piecewise(data_, | |
| 510 | + [data_ <= (level - 0.5 - (window-1)/2), | |
| 511 | + data_ > (level - 0.5 + (window-1)/2)], | |
| 512 | + [0, 255, lambda data_: ((data_ - (level - 0.5))/(window-1) + 0.5)*(255)]) | |
| 513 | + data.shape = shape | |
| 514 | + return data | ... | ... |
invesalius/gui/bitmap_preview_panel.py
invesalius/gui/dicom_preview_panel.py
| ... | ... | @@ -35,7 +35,8 @@ import invesalius.constants as const |
| 35 | 35 | import invesalius.reader.dicom_reader as dicom_reader |
| 36 | 36 | import invesalius.data.vtk_utils as vtku |
| 37 | 37 | import invesalius.utils as utils |
| 38 | -import vtkgdcm | |
| 38 | +from invesalius.data import imagedata_utils | |
| 39 | +from invesalius.data import converters | |
| 39 | 40 | |
| 40 | 41 | if sys.platform == 'win32': |
| 41 | 42 | try: |
| ... | ... | @@ -890,20 +891,20 @@ class SingleImagePreview(wx.Panel): |
| 890 | 891 | reader.Update() |
| 891 | 892 | |
| 892 | 893 | image = reader.GetOutput() |
| 893 | - | |
| 894 | 894 | else: |
| 895 | - rdicom = vtkgdcm.vtkGDCMImageReader() | |
| 895 | + filename = dicom.image.file | |
| 896 | 896 | if _has_win32api: |
| 897 | - rdicom.SetFileName(win32api.GetShortPathName(dicom.image.file).encode(const.FS_ENCODE)) | |
| 898 | - else: | |
| 899 | - rdicom.SetFileName(dicom.image.file) | |
| 900 | - rdicom.Update() | |
| 897 | + filename = win32api.GetShortPathName(filename).encode(const.FS_ENCODE) | |
| 898 | + | |
| 899 | + np_image = imagedata_utils.read_dcm_slice_as_np2(filename) | |
| 900 | + print(">>> spacing", dicom.image.spacing) | |
| 901 | + vtk_image = converters.to_vtk(np_image, dicom.image.spacing, 0, 'AXIAL') | |
| 901 | 902 | |
| 902 | 903 | # ADJUST CONTRAST |
| 903 | 904 | window_level = dicom.image.level |
| 904 | 905 | window_width = dicom.image.window |
| 905 | 906 | colorer = vtk.vtkImageMapToWindowLevelColors() |
| 906 | - colorer.SetInputConnection(rdicom.GetOutputPort()) | |
| 907 | + colorer.SetInputData(vtk_image) | |
| 907 | 908 | colorer.SetWindow(float(window_width)) |
| 908 | 909 | colorer.SetLevel(float(window_level)) |
| 909 | 910 | colorer.Update() | ... | ... |
invesalius/reader/dicom.py
invesalius/reader/dicom_reader.py
| ... | ... | @@ -24,7 +24,6 @@ import sys |
| 24 | 24 | from multiprocessing import cpu_count |
| 25 | 25 | |
| 26 | 26 | import vtk |
| 27 | -import vtkgdcm | |
| 28 | 27 | import gdcm |
| 29 | 28 | from wx.lib.pubsub import pub as Publisher |
| 30 | 29 | |
| ... | ... | @@ -202,14 +201,11 @@ class LoadDicom: |
| 202 | 201 | level = None |
| 203 | 202 | window = None |
| 204 | 203 | |
| 205 | - if _has_win32api: | |
| 206 | - thumbnail_path = imagedata_utils.create_dicom_thumbnails(win32api.GetShortPathName(self.filepath), window, level) | |
| 207 | - else: | |
| 208 | - thumbnail_path = imagedata_utils.create_dicom_thumbnails(self.filepath, window, level) | |
| 204 | + img = reader.GetImage() | |
| 205 | + thumbnail_path = imagedata_utils.create_dicom_thumbnails(img, window, level) | |
| 209 | 206 | |
| 210 | 207 | #------ Verify the orientation -------------------------------- |
| 211 | 208 | |
| 212 | - img = reader.GetImage() | |
| 213 | 209 | direc_cosines = img.GetDirectionCosines() |
| 214 | 210 | orientation = gdcm.Orientation() |
| 215 | 211 | try: | ... | ... |