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,7 +824,6 @@ class Controller(): | ||
824 | self.matrix, scalar_range, self.filename = image_utils.dcm2memmap(filelist, size, | 824 | self.matrix, scalar_range, self.filename = image_utils.dcm2memmap(filelist, size, |
825 | orientation, resolution_percentage) | 825 | orientation, resolution_percentage) |
826 | 826 | ||
827 | - print(xyspacing, zspacing) | ||
828 | if orientation == 'AXIAL': | 827 | if orientation == 'AXIAL': |
829 | spacing = xyspacing[0], xyspacing[1], zspacing | 828 | spacing = xyspacing[0], xyspacing[1], zspacing |
830 | elif orientation == 'CORONAL': | 829 | elif orientation == 'CORONAL': |
@@ -832,7 +831,10 @@ class Controller(): | @@ -832,7 +831,10 @@ class Controller(): | ||
832 | elif orientation == 'SAGITTAL': | 831 | elif orientation == 'SAGITTAL': |
833 | spacing = zspacing, xyspacing[1], xyspacing[0] | 832 | spacing = zspacing, xyspacing[1], xyspacing[0] |
834 | else: | 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 | self.Slice = sl.Slice() | 839 | self.Slice = sl.Slice() |
838 | self.Slice.matrix = self.matrix | 840 | self.Slice.matrix = self.matrix |
invesalius/data/converters.py
@@ -17,10 +17,13 @@ | @@ -17,10 +17,13 @@ | ||
17 | # detalhes. | 17 | # detalhes. |
18 | #-------------------------------------------------------------------------- | 18 | #-------------------------------------------------------------------------- |
19 | 19 | ||
20 | -import numpy | 20 | +import gdcm |
21 | +import numpy as np | ||
21 | import vtk | 22 | import vtk |
23 | + | ||
22 | from vtk.util import numpy_support | 24 | from vtk.util import numpy_support |
23 | 25 | ||
26 | + | ||
24 | def to_vtk(n_array, spacing, slice_number, orientation, origin=(0, 0, 0), padding=(0, 0, 0)): | 27 | def to_vtk(n_array, spacing, slice_number, orientation, origin=(0, 0, 0), padding=(0, 0, 0)): |
25 | 28 | ||
26 | if orientation == "SAGITTAL": | 29 | if orientation == "SAGITTAL": |
@@ -84,3 +87,40 @@ def np_rgba_to_vtk(n_array, spacing=(1.0, 1.0, 1.0)): | @@ -84,3 +87,40 @@ def np_rgba_to_vtk(n_array, spacing=(1.0, 1.0, 1.0)): | ||
84 | image.GetPointData().SetScalars(v_image) | 87 | image.GetPointData().SetScalars(v_image) |
85 | 88 | ||
86 | return image | 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,9 +23,10 @@ import sys | ||
23 | import tempfile | 23 | import tempfile |
24 | 24 | ||
25 | import gdcm | 25 | import gdcm |
26 | +import imageio | ||
26 | import numpy | 27 | import numpy |
28 | +import numpy as np | ||
27 | import vtk | 29 | import vtk |
28 | -import vtkgdcm | ||
29 | from wx.lib.pubsub import pub as Publisher | 30 | from wx.lib.pubsub import pub as Publisher |
30 | 31 | ||
31 | from scipy.ndimage import shift, zoom | 32 | from scipy.ndimage import shift, zoom |
@@ -124,20 +125,15 @@ def resize_slice(im_array, resolution_percentage): | @@ -124,20 +125,15 @@ def resize_slice(im_array, resolution_percentage): | ||
124 | return out | 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 | if resolution_percentage < 1.0: | 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 | def FixGantryTilt(matrix, spacing, tilt): | 139 | def FixGantryTilt(matrix, spacing, tilt): |
@@ -240,17 +236,6 @@ def View(imagedata): | @@ -240,17 +236,6 @@ def View(imagedata): | ||
240 | import time | 236 | import time |
241 | time.sleep(10) | 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 | def ExtractVOI(imagedata,xi,xf,yi,yf,zi,zf): | 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,267 +250,33 @@ def ExtractVOI(imagedata,xi,xf,yi,yf,zi,zf): | ||
265 | return voi.GetOutput() | 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 | if window is None or level is None: | 256 | if window is None or level is None: |
275 | - _min, _max = img.GetScalarRange() | 257 | + _min, _max = np_image.min(), np_image.max() |
276 | window = _max - _min | 258 | window = _max - _min |
277 | level = _min + window / 2 | 259 | level = _min + window / 2 |
278 | 260 | ||
279 | - dx, dy, dz = img.GetDimensions() | ||
280 | - | ||
281 | - if dz > 1: | 261 | + if image.GetNumberOfDimensions() >= 3: |
282 | thumbnail_paths = [] | 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 | thumbnail_paths.append(thumbnail_path) | 268 | thumbnail_paths.append(thumbnail_path) |
308 | - | ||
309 | return thumbnail_paths | 269 | return thumbnail_paths |
310 | else: | 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 | else: | 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 | def bitmap2memmap(files, slice_size, orientation, spacing, resolution_percentage): | 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,7 +377,6 @@ def bitmap2memmap(files, slice_size, orientation, spacing, resolution_percentage | ||
626 | return matrix, scalar_range, temp_file | 377 | return matrix, scalar_range, temp_file |
627 | 378 | ||
628 | 379 | ||
629 | - | ||
630 | def dcm2memmap(files, slice_size, orientation, resolution_percentage): | 380 | def dcm2memmap(files, slice_size, orientation, resolution_percentage): |
631 | """ | 381 | """ |
632 | From a list of dicom files it creates memmap file in the temp folder and | 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,7 +385,7 @@ def dcm2memmap(files, slice_size, orientation, resolution_percentage): | ||
635 | message = _("Generating multiplanar visualization...") | 385 | message = _("Generating multiplanar visualization...") |
636 | update_progress= vtk_utils.ShowProgress(len(files) - 1, dialog_type = "ProgressDialog") | 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 | slice_size = first_slice.shape[::-1] | 389 | slice_size = first_slice.shape[::-1] |
640 | 390 | ||
641 | temp_file = tempfile.mktemp() | 391 | temp_file = tempfile.mktemp() |
@@ -649,7 +399,7 @@ def dcm2memmap(files, slice_size, orientation, resolution_percentage): | @@ -649,7 +399,7 @@ def dcm2memmap(files, slice_size, orientation, resolution_percentage): | ||
649 | 399 | ||
650 | matrix = numpy.memmap(temp_file, mode='w+', dtype='int16', shape=shape) | 400 | matrix = numpy.memmap(temp_file, mode='w+', dtype='int16', shape=shape) |
651 | for n, f in enumerate(files): | 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 | if orientation == 'CORONAL': | 404 | if orientation == 'CORONAL': |
655 | matrix[:, shape[1] - n - 1, :] = im_array | 405 | matrix[:, shape[1] - n - 1, :] = im_array |
@@ -669,37 +419,35 @@ def dcm2memmap(files, slice_size, orientation, resolution_percentage): | @@ -669,37 +419,35 @@ def dcm2memmap(files, slice_size, orientation, resolution_percentage): | ||
669 | 419 | ||
670 | 420 | ||
671 | def dcmmf2memmap(dcm_file, orientation): | 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 | temp_file = tempfile.mktemp() | 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 | if orientation == 'CORONAL': | 433 | if orientation == 'CORONAL': |
434 | + spacing = xs, zs, ys | ||
687 | matrix.shape = y, z, x | 435 | matrix.shape = y, z, x |
688 | for n in range(z): | 436 | for n in range(z): |
689 | - matrix[:, n, :] = d[n] | 437 | + matrix[:, n, :] = np_image[n][::-1] |
690 | elif orientation == 'SAGITTAL': | 438 | elif orientation == 'SAGITTAL': |
691 | - matrix.shape = x, z, y | 439 | + spacing = zs, ys, xs |
440 | + matrix.shape = y, x, z | ||
692 | for n in range(z): | 441 | for n in range(z): |
693 | - matrix[:, :, n] = d[n] | 442 | + matrix[:, :, n] = np_image[n][::-1] |
694 | else: | 443 | else: |
695 | - matrix[:] = d | 444 | + spacing = xs, ys, zs |
445 | + matrix[:] = np_image[:, ::-1, :] | ||
696 | 446 | ||
697 | matrix.flush() | 447 | matrix.flush() |
698 | scalar_range = matrix.min(), matrix.max() | 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 | def img2memmap(group): | 453 | def img2memmap(group): |
@@ -753,3 +501,14 @@ def imgnormalize(data, srange=(0, 255)): | @@ -753,3 +501,14 @@ def imgnormalize(data, srange=(0, 255)): | ||
753 | datan = datan.astype(numpy.int16) | 501 | datan = datan.astype(numpy.int16) |
754 | 502 | ||
755 | return datan | 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,7 +35,8 @@ import invesalius.constants as const | ||
35 | import invesalius.reader.dicom_reader as dicom_reader | 35 | import invesalius.reader.dicom_reader as dicom_reader |
36 | import invesalius.data.vtk_utils as vtku | 36 | import invesalius.data.vtk_utils as vtku |
37 | import invesalius.utils as utils | 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 | if sys.platform == 'win32': | 41 | if sys.platform == 'win32': |
41 | try: | 42 | try: |
@@ -890,20 +891,20 @@ class SingleImagePreview(wx.Panel): | @@ -890,20 +891,20 @@ class SingleImagePreview(wx.Panel): | ||
890 | reader.Update() | 891 | reader.Update() |
891 | 892 | ||
892 | image = reader.GetOutput() | 893 | image = reader.GetOutput() |
893 | - | ||
894 | else: | 894 | else: |
895 | - rdicom = vtkgdcm.vtkGDCMImageReader() | 895 | + filename = dicom.image.file |
896 | if _has_win32api: | 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 | # ADJUST CONTRAST | 903 | # ADJUST CONTRAST |
903 | window_level = dicom.image.level | 904 | window_level = dicom.image.level |
904 | window_width = dicom.image.window | 905 | window_width = dicom.image.window |
905 | colorer = vtk.vtkImageMapToWindowLevelColors() | 906 | colorer = vtk.vtkImageMapToWindowLevelColors() |
906 | - colorer.SetInputConnection(rdicom.GetOutputPort()) | 907 | + colorer.SetInputData(vtk_image) |
907 | colorer.SetWindow(float(window_width)) | 908 | colorer.SetWindow(float(window_width)) |
908 | colorer.SetLevel(float(window_level)) | 909 | colorer.SetLevel(float(window_level)) |
909 | colorer.Update() | 910 | colorer.Update() |
invesalius/reader/dicom.py
@@ -19,7 +19,6 @@ | @@ -19,7 +19,6 @@ | ||
19 | #--------------------------------------------------------------------- | 19 | #--------------------------------------------------------------------- |
20 | import time | 20 | import time |
21 | #import gdcm | 21 | #import gdcm |
22 | -#import vtkgdcm | ||
23 | import sys | 22 | import sys |
24 | import invesalius.utils as utils | 23 | import invesalius.utils as utils |
25 | import invesalius.constants as const | 24 | import invesalius.constants as const |
invesalius/reader/dicom_reader.py
@@ -24,7 +24,6 @@ import sys | @@ -24,7 +24,6 @@ import sys | ||
24 | from multiprocessing import cpu_count | 24 | from multiprocessing import cpu_count |
25 | 25 | ||
26 | import vtk | 26 | import vtk |
27 | -import vtkgdcm | ||
28 | import gdcm | 27 | import gdcm |
29 | from wx.lib.pubsub import pub as Publisher | 28 | from wx.lib.pubsub import pub as Publisher |
30 | 29 | ||
@@ -202,14 +201,11 @@ class LoadDicom: | @@ -202,14 +201,11 @@ class LoadDicom: | ||
202 | level = None | 201 | level = None |
203 | window = None | 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 | #------ Verify the orientation -------------------------------- | 207 | #------ Verify the orientation -------------------------------- |
211 | 208 | ||
212 | - img = reader.GetImage() | ||
213 | direc_cosines = img.GetDirectionCosines() | 209 | direc_cosines = img.GetDirectionCosines() |
214 | orientation = gdcm.Orientation() | 210 | orientation = gdcm.Orientation() |
215 | try: | 211 | try: |