def create_image_reader(ds: "Dataset") -> "gdcm.ImageReader": """Return a ``gdcm.ImageReader``. Parameters ---------- ds : pydicom.dataset.Dataset The dataset to create the reader from. Returns ------- gdcm.ImageReader """ image_reader = gdcm.ImageReader() fname = getattr(ds, 'filename', None) if fname and isinstance(fname, str): pass else: # Copy the relevant elements and write to a temporary file to avoid # having to deal with all the possible objects the dataset may # originate with new = ds.group_dataset(0x0028) new["PixelData"] = ds["PixelData"] # avoid ambiguous VR new.file_meta = ds.file_meta # type: ignore[has-type] tfile = NamedTemporaryFile('wb') new.save_as(tfile.name) fname = tfile.name image_reader.SetFileName(fname) return image_reader
def decomp(file1, file2='temp_file_22.dcm', return_dcm=False): #file1 = '/data/gabriel/TAVR/TAVR_Sample_Study/IM-0003-1528.dcm'#sys.argv[1] # input filename #file2 = file2#sys.argv[2] # output filename if os.path.isfile(file2): os.remove(file2) reader = gdcm.ImageReader() reader.SetFileName(file1) reader.GetFile() if not reader.Read(): sys.exit(1) change = gdcm.ImageChangeTransferSyntax() change.SetTransferSyntax( gdcm.TransferSyntax(gdcm.TransferSyntax.ImplicitVRLittleEndian)) change.SetInput(reader.GetImage()) if not change.Change(): sys.exit(1) writer = gdcm.ImageWriter() writer.SetFileName(file2) writer.SetFile(reader.GetFile()) writer.SetImage(change.GetOutput()) if not writer.Write(): sys.exit(1) if return_dcm: return pydicom.dcmread(file2, force=True) else: return pydicom.dcmread(file2, force=True).pixel_array
def decompress(inFile, outFile): print("Extract (or copy) %s to %s" % (inFile, outFile)) try: reader = gdcm.ImageReader() reader.SetFileName(inFile) if not reader.Read(): raise Exception("Unable to read %s with gdcm.ImageReader()" % inFile) change = gdcm.ImageChangeTransferSyntax() change.SetTransferSyntax( gdcm.TransferSyntax(gdcm.TransferSyntax.ImplicitVRLittleEndian)) change.SetInput(reader.GetImage()) if not change.Change(): raise Exception( "Unable to change %s with gdcm.ImageChangeTransferSyntax()" % inFile) writer = gdcm.ImageWriter() writer.SetFileName(outFile) writer.SetFile(reader.GetFile()) writer.SetImage(change.GetOutput()) if not writer.Write(): raise Exception("Unable to write %s with gdcm.ImageWriter()" % outFile) except Exception as e: sys.stderr.write("%s, copying instead" % str(e)) if inFile is not outFile: shutil.copyfile(inFile, outFile)
def dcmmf2memmap(dcm_file, orientation): reader = gdcm.ImageReader() reader.SetFileName(dcm_file) reader.Read() image = reader.GetImage() xs, ys, zs = image.GetSpacing() pf = image.GetPixelFormat() np_image = converters.gdcm_to_numpy(image, pf.GetSamplesPerPixel() == 1) temp_file = tempfile.mktemp() matrix = numpy.memmap(temp_file, mode='w+', dtype='int16', shape=np_image.shape) print("Number of dimensions", np_image.shape) z, y, x = np_image.shape if orientation == 'CORONAL': spacing = xs, zs, ys matrix.shape = y, z, x for n in range(z): matrix[:, n, :] = np_image[n][::-1] elif orientation == 'SAGITTAL': spacing = zs, ys, xs matrix.shape = y, x, z for n in range(z): matrix[:, :, n] = np_image[n][::-1] else: spacing = xs, ys, zs matrix[:] = np_image[:, ::-1, :] matrix.flush() scalar_range = matrix.min(), matrix.max() return matrix, scalar_range, spacing, temp_file
def dcmmf2memmap(dcm_file, orientation): reader = gdcm.ImageReader() reader.SetFileName(dcm_file) reader.Read() image = reader.GetImage() xs, ys, zs = image.GetSpacing() pf = image.GetPixelFormat() samples_per_pixel = pf.GetSamplesPerPixel() np_image = converters.gdcm_to_numpy(image, pf.GetSamplesPerPixel() == 1) if samples_per_pixel == 3: np_image = image_normalize(rgb2gray(np_image), 0, 255) temp_file = tempfile.mktemp() matrix = numpy.memmap(temp_file, mode="w+", dtype="int16", shape=np_image.shape) z, y, x = np_image.shape if orientation == "CORONAL": spacing = xs, zs, ys matrix.shape = y, z, x for n in range(z): matrix[:, n, :] = np_image[n][::-1] elif orientation == "SAGITTAL": spacing = zs, ys, xs matrix.shape = y, x, z for n in range(z): matrix[:, :, n] = np_image[n][::-1] else: spacing = xs, ys, zs matrix[:] = np_image[:, ::-1, :] matrix.flush() scalar_range = matrix.min(), matrix.max() return matrix, scalar_range, spacing, temp_file
def numpy(self): """ Grabs image data and converts it to a numpy array """ # load GDCM's image reading functionality image_reader = gdcm.ImageReader() image_reader.SetFileName(self.fname) if not image_reader.Read(): raise IOError("Could not read DICOM image") pixel_array = self._gdcm_to_numpy(image_reader.GetImage()) return pixel_array
def read_dcm_slice_as_np2(filename, resolution_percentage=1.0): reader = gdcm.ImageReader() reader.SetFileName(filename) reader.Read() image = reader.GetImage() output = converters.gdcm_to_numpy(image) if resolution_percentage < 1.0: output = zoom(output, resolution_percentage) return output
def TestKakadu(filename, kdu_expand): fn = gdcm.Filename(filename) testdir = fn.GetPath() testbasename = fn.GetName() ext = fn.GetExtension() #print ext #kakadu_path = '/home/mmalaterre/Software/Kakadu60' kakadu_path = os.path.dirname(kdu_expand) #kdu_expand = kakadu_path + '/kdu_expand' kdu_args = ' -quiet -i ' output_dcm = testdir + '/kakadu/' + testbasename output_j2k = output_dcm + '.j2k' output_ppm = output_dcm + '.ppm' # output_raw = output_dcm + '.rawl' # FIXME: little endian only... kdu_expand += kdu_args + output_j2k + ' -o ' + output_raw # $ ./bin/gdcmraw -i .../TestImageChangeTransferSyntax2/012345.002.050.dcm -o toto.j2k executable_output_path = gdcm.GDCM_EXECUTABLE_OUTPUT_PATH gdcmraw = executable_output_path + '/gdcmraw' outputfilename = output_j2k gdcmraw_args = ' -i ' + filename + ' -o ' + outputfilename gdcmraw += gdcmraw_args #print gdcmraw ret = os.system(gdcmraw) #print "ret:",ret #print kdu_expand os.environ["LD_LIBRARY_PATH"] = kakadu_path ret = os.system(kdu_expand) # now need to skip the ppm header: dd_cmd = 'dd bs=15 skip=1 if=%s of = %s' % (output_ppm, output_raw) #print "ret:",ret md5 = gdcm.Testing.ComputeFileMD5(output_raw) # ok this is the md5 as computed after decompression using kdu_expand # let see if it match out previously (stored) md5: ref = gdcm.Testing.GetMD5FromFile(filename) #print ref retval = 0 if ref != md5: img = gdcm.ImageReader() img.SetFileName(filename) img.Read() if img.GetImage().GetDimension(2) != 1: print("Test do not handle multiframes for now") elif img.GetImage().GetPixelFormat().GetSamplesPerPixel() != 1: print( "Test do not handle RGB for now. kdu_expand expand as RRR GGG BBB by default" ) else: print("md5 are different: %s should be: %s for file %s" % (md5, ref, filename)) print("raw file was: %s" % (output_raw)) retval = 1 return retval
def ProcessOneFilePublic(filename, outfilename, tmpfile): gdcm.ImageHelper.SetForceRescaleInterceptSlope(True) vtkreader = vtkgdcm.vtkGDCMImageReader() vtkreader.SetFileName(filename) vtkreader.Update() cast = vtk.vtkImageCast() cast.SetInput(vtkreader.GetOutput()) cast.SetOutputScalarTypeToUnsignedShort() # vtkGDCMImageWriter does not support Sequence, so let's write a tmp file first: # Some operation will actually be discarded (we simply need a temp storage) vtkwriter = vtkgdcm.vtkGDCMImageWriter() vtkwriter.SetFileName(tmpfile) vtkwriter.SetMedicalImageProperties(vtkreader.GetMedicalImageProperties()) vtkwriter.SetDirectionCosines(vtkreader.GetDirectionCosines()) print "Format:", vtkreader.GetImageFormat() vtkwriter.SetImageFormat(vtkreader.GetImageFormat()) vtkwriter.SetInput(cast.GetOutput()) #vtkwriter.Update() vtkwriter.Write() # ok now rewrite the exact same file as the original (keep all info) # but use the Pixel Data Element from the written file tmpreader = gdcm.ImageReader() tmpreader.SetFileName(tmpfile) if not tmpreader.Read(): sys.exit(1) reader = gdcm.Reader() reader.SetFileName(filename) if not reader.Read(): sys.exit(1) # Make sure to remove Slope/Rescale to avoid re-execution ds = reader.GetFile().GetDataSet() tags = [ gdcm.Tag(0x0028, 0x1052), gdcm.Tag(0x0028, 0x1053), gdcm.Tag(0x0028, 0x1053), ] for tag in tags: ds.Remove(tag) writer = gdcm.ImageWriter() writer.SetFileName(outfilename) # Pass image from vtk written file writer.SetImage(tmpreader.GetImage()) # pass dataset from initial 'reader' writer.SetFile(reader.GetFile()) if not writer.Write(): sys.exit(1)
def __init__(self, dcm_path): try: self.dcm_path = dcm_path pygdcm.gdcm_Reader = gdcm.ImageReader() pygdcm.gdcm_Reader.SetFileName(self.dcm_path) file = pygdcm.gdcm_Reader.GetFile() self.dataset = file.GetDataSet() self.strFilter = gdcm.StringFilter() self.strFilter.SetFile(pygdcm.gdcm_Reader.GetFile()) self.image_u16 = [] except Exception as e: print(traceback.print_exc()) return
def __init__(self, filename): self.image_reader = gdcm.ImageReader() self.image_reader.SetFileName(filename) self.reader = gdcm.Reader() self.reader.SetFileName(filename) if not self.reader.Read(): raise DicomFileReadFailed("{} dicom file read failed.".format( filename)) self.dicom_file = self.reader.GetFile() self.dicom_dataset = self.dicom_file.GetDataSet() self.dicom_header = self.dicom_file.GetHeader() if not self.image_reader.Read(): raise DicomImageReadFailed("{} image read failed.".format( filename))
def readFile(filename): r = gdcm.ImageReader() r.SetFileName(filename) if not r.Read(): sys.exit(1) numpy_array = gdcm_to_numpy(r.GetImage()) pilImage = Image.frombuffer('L', numpy_array.shape, numpy_array.astype(numpy.uint8), 'raw', 'L', 0, 1) pilImage = ImageOps.autocontrast(pilImage, cutoff=.1) pilImage.save(filename + '.jpg') print(filename + '.jpg')
def create_image_reader(filename): """Return a ``gdcm.ImageReader``. Parameters ---------- filename: str or unicode The path to the DICOM dataset. Returns ------- gdcm.ImageReader """ image_reader = gdcm.ImageReader() image_reader.SetFileName(filename) return image_reader
def _get_pixel_str_fileio(ds: "Dataset") -> str: """Return the pixel data from `ds` as a str. Used for GDCM < 2.8.8. Parameters ---------- ds : pydicom.dataset.Dataset The dataset to create the str from. Returns ------- str The UTF-8 encoded pixel data. """ reader = gdcm.ImageReader() fname = getattr(ds, 'filename', None) if fname and isinstance(fname, str): reader.SetFileName(fname) if not reader.Read(): raise TypeError("GDCM could not read DICOM image") return cast(str, reader.GetImage().GetBuffer()) # Copy the relevant elements and write to a temporary file to avoid # having to deal with all the possible objects the dataset may # originate with new = ds.group_dataset(0x0028) new["PixelData"] = ds["PixelData"] # avoid ambiguous VR new.file_meta = ds.file_meta with NamedTemporaryFile('wb', delete=False) as t: new.save_as(t) reader.SetFileName(t.name) if not reader.Read(): raise TypeError("GDCM could not read DICOM image") pixel_str: str = reader.GetImage().GetBuffer() # Need to kill the gdcm.ImageReader to free file access reader = None os.remove(t.name) return pixel_str
def cn(self, file1): file2 = "tmp00.dcm" # output filename reader = gdcm.ImageReader() reader.SetFileName(file1) reader.Read() change = gdcm.ImageChangeTransferSyntax() change.SetTransferSyntax( gdcm.TransferSyntax(gdcm.TransferSyntax.ImplicitVRLittleEndian)) change.SetInput(reader.GetImage()) change.Change() writer = gdcm.ImageWriter() writer.SetFileName(file2) writer.SetFile(reader.GetFile()) writer.SetImage(change.GetOutput()) writer.Write() zz = pydicom.read_file("tmp00.dcm") os.remove("tmp00.dcm") return zz
def Load(self, dirname): try: if not XFile.PathExists(dirname): raise DIVError(-1) files = XFile.GetList(dirname, '*.' + DIV.DEFAULT_EXTENSION) if files is None or len(files) == 0: raise DIVError(-2) vol = None vdim = None for dfile in sorted(files): dicom = gdcm.ImageReader() dicom.SetFileName(dirname + '/' + dfile) if not dicom.Read(): raise DIVError(-3) image = dicom.GetImage() if vdim is None: vdim = image.GetDimensions() # Image dimensions fmt = image.GetPixelFormat() # Pixel format vs = image.GetSpacing() # Voxel size vdim.append(len(files)) dt = DIV_DTYPES[fmt.GetScalarType()] raw = np.frombuffer(image.GetBuffer(), dtype=dt) vol = raw if vol is None else np.append(vol, raw) xdim, ydim, zdim = vdim vol = vol.reshape((zdim, ydim, xdim)) vu = Volume.VOXEL_UNITS['mm'] cl = [0] * 8 nc = 1 except DIVError as err: print err.message % filename, err.info raise except Exception: raise else: self.data = vol self.xdim = xdim self.ydim = ydim self.zdim = zdim self.vdim = vdim self.vunit = vu self.vsize = vs self.nchan = nc self.clist = cl
def dc(inputFile, outputFile): reader = gdcm.ImageReader() reader.SetFileName(inputFile) if not reader.Read(): sys.exit(1) change = gdcm.ImageChangeTransferSyntax() change.SetTransferSyntax( gdcm.TransferSyntax(gdcm.TransferSyntax.ImplicitVRLittleEndian) ) change.SetInput( reader.GetImage() ) if not change.Change(): sys.exit(1) writer = gdcm.ImageWriter() writer.SetFileName(outputFile) writer.SetFile( reader.GetFile() ) writer.SetImage( change.GetOutput() ) if not writer.Write(): sys.exit(1)
def create_image_reader(filename): """Create a gdcm.ImageReader Parameters ---------- filename: str or unicode (Python 2) Returns ------- gdcm.ImageReader """ image_reader = gdcm.ImageReader() if compat.in_py2: if isinstance(filename, unicode): image_reader.SetFileName( filename.encode(sys.getfilesystemencoding())) else: image_reader.SetFileName(filename) else: image_reader.SetFileName(filename) return image_reader
def create_image_reader(filename): """Return a ``gdcm.ImageReader``. Parameters ---------- filename: str or unicode The path to the DICOM dataset. Returns ------- gdcm.ImageReader """ image_reader = gdcm.ImageReader() if compat.in_py2: if isinstance(filename, unicode): image_reader.SetFileName( filename.encode(sys.getfilesystemencoding())) else: image_reader.SetFileName(filename) else: image_reader.SetFileName(filename) return image_reader
def method2(file1, file2): reader = gdcm.ImageReader() reader.SetFileName(file1) if not reader.Read(): sys.exit(1) change = gdcm.ImageChangeTransferSyntax() change.SetTransferSyntax( gdcm.TransferSyntax(gdcm.TransferSyntax.ImplicitVRLittleEndian)) change.SetInput(reader.GetImage()) if not change.Change(): sys.exit(1) writer = gdcm.ImageWriter() writer.SetFileName(file2) writer.SetFile(reader.GetFile()) writer.SetImage(change.GetOutput()) if not writer.Write(): raise ValueError
def ExecuteInformation(reader, filename, dimz=1): import gdcm reffile = filename # filenames.GetValue(0) # Take first image as reference #print reader r = gdcm.ImageReader() r.SetFileName(reffile) success = r.Read() assert success #print r.GetImage().Print() image = r.GetImage() assert image.GetNumberOfDimensions() == 2 or image.GetNumberOfDimensions( ) == 3 dims = [0, 0, 0] dims[0] = image.GetDimension(0) dims[1] = image.GetDimension(1) dims[2] = dimz # filenames.GetNumberOfValues() #print dims #print image.GetPixelFormat().GetTPixelFormat() pixelformat = image.GetPixelFormat().GetScalarType() datascalartype = vtkType.VTK_VOID # dummy should not happen if pixelformat == gdcm.PixelFormat.INT8: datascalartype = vtkType.VTK_SIGNED_CHAR elif pixelformat == gdcm.PixelFormat.UINT8: datascalartype = vtkType.VTK_UNSIGNED_CHAR elif pixelformat == gdcm.PixelFormat.INT16: datascalartype = vtkType.VTK_SHORT elif pixelformat == gdcm.PixelFormat.UINT16: datascalartype = vtkType.VTK_UNSIGNED_SHORT else: print "Unhandled PixelFormat: ", pixelformat sys.exit(1) #print datascalartype numberOfScalarComponents = image.GetPixelFormat().GetSamplesPerPixel() #print numberOfScalarComponents #print gdcm.PhotometricInterpretation.GetPIString( image.GetPhotometricInterpretation().PIType() ) #reader.SetDataExtent( dataextent ); reader.SetDataExtent(0, dims[0] - 1, 0, dims[1] - 1, 0, dims[2] - 1) reader.SetDataScalarType(datascalartype) reader.SetNumberOfScalarComponents(numberOfScalarComponents)
def open_image(path, verbose=True): """ Open a two- or three-dimensional DICOM image at the given <path>. Return a tuple (ireader, data) where <ireader> represents a <gdcm.ImageReader> reference to the image as returned by the GDCM library, and <data> holds the actual image data in a Numpy array. Note that the image data as a <gdcm.Image> instance can be obtained from the <ireader> via <ireader.GetImage()>. However, the image instance is only valid as long as the <ireader> is not destroyed. This is the reason why the <ImageReader> rather than the <Image> instance is returned here. If unsuccessful, an <IOError> will be raised. """ # Create a reader for the image reader = gdcm.ImageReader() reader.SetFileName(path) # Try to actually read it read_success = reader.Read() if not read_success: raise IOError("Error opening dicom-file.") image = reader.GetImage() # Convert to Numpy array try: data = __to_array(image) except ValueError: # Re-raise as IOError with complete traceback import sys (value, traceback) = sys.exc_info()[1:] raise (IOError, value, traceback) if verbose: print "Image loaded:", path print "Meta data:" print image return (reader, data)
def run(self): grouper = self.grouper reader = gdcm.ImageReader() reader.SetFileName(self.filepath) if (reader.Read()): file = reader.GetFile() # Retrieve data set dataSet = file.GetDataSet() # Retrieve header header = file.GetHeader() stf = gdcm.StringFilter() field_dict = {} data_dict = {} tag = gdcm.Tag(0x0008, 0x0005) ds = reader.GetFile().GetDataSet() if ds.FindDataElement(tag): encoding_value = str( ds.GetDataElement(tag).GetValue()).split('\\')[0] if encoding_value.startswith("Loaded"): encoding = "ISO_IR 100" else: try: encoding = const.DICOM_ENCODING_TO_PYTHON[ encoding_value] except KeyError: encoding = 'ISO_IR 100' else: encoding = "ISO_IR 100" # Iterate through the Header iterator = header.GetDES().begin() while (not iterator.equal(header.GetDES().end())): dataElement = iterator.next() stf.SetFile(file) tag = dataElement.GetTag() data = stf.ToStringPair(tag) stag = tag.PrintAsPipeSeparatedString() group = str(tag.GetGroup()) field = str(tag.GetElement()) tag_labels[stag] = data[0] if not group in data_dict.keys(): data_dict[group] = {} if not (utils.VerifyInvalidPListCharacter(data[1])): data_dict[group][field] = data[1].decode(encoding) else: data_dict[group][field] = "Invalid Character" # Iterate through the Data set iterator = dataSet.GetDES().begin() while (not iterator.equal(dataSet.GetDES().end())): dataElement = iterator.next() stf.SetFile(file) tag = dataElement.GetTag() data = stf.ToStringPair(tag) stag = tag.PrintAsPipeSeparatedString() group = str(tag.GetGroup()) field = str(tag.GetElement()) tag_labels[stag] = data[0] if not group in data_dict.keys(): data_dict[group] = {} if not (utils.VerifyInvalidPListCharacter(data[1])): data_dict[group][field] = data[1].decode( encoding, 'replace') else: data_dict[group][field] = "Invalid Character" # -------------- To Create DICOM Thumbnail ----------- rvtk = vtkgdcm.vtkGDCMImageReader() rvtk.SetFileName(self.filepath) rvtk.Update() try: data = data_dict[str(0x028)][str(0x1050)] level = [float(value) for value in data.split('\\')][0] data = data_dict[str(0x028)][str(0x1051)] window = [float(value) for value in data.split('\\')][0] except (KeyError): level = 300.0 window = 2000.0 colorer = vtk.vtkImageMapToWindowLevelColors() colorer.SetInputConnection(rvtk.GetOutputPort()) colorer.SetWindow(float(window)) colorer.SetLevel(float(level)) colorer.SetOutputFormatToRGB() colorer.Update() resample = vtk.vtkImageResample() resample.SetInputConnection(colorer.GetOutputPort()) resample.SetAxisMagnificationFactor(0, 0.25) resample.SetAxisMagnificationFactor(1, 0.25) resample.SetAxisMagnificationFactor(2, 1) resample.Update() thumbnail_path = tempfile.mktemp() write_png = vtk.vtkPNGWriter() write_png.SetInputConnection(resample.GetOutputPort()) write_png.SetFileName(thumbnail_path) write_png.Write() #------ Verify the orientation -------------------------------- img = reader.GetImage() direc_cosines = img.GetDirectionCosines() orientation = gdcm.Orientation() try: type = orientation.GetType(tuple(direc_cosines)) except TypeError: type = orientation.GetType(direc_cosines) label = orientation.GetLabel(type) # ---------- Refactory -------------------------------------- data_dict['invesalius'] = {'orientation_label': label} # ------------------------------------------------------------- dict_file[self.filepath] = data_dict #---------- Verify is DICOMDir ------------------------------- is_dicom_dir = 1 try: if (data_dict[str(0x002)][str(0x002)] != "1.2.840.10008.1.3.10"): #DICOMDIR is_dicom_dir = 0 except (KeyError): is_dicom_dir = 0 if not (is_dicom_dir): parser = dicom.Parser() parser.SetDataImage(dict_file[self.filepath], self.filepath, thumbnail_path) dcm = dicom.Dicom() #self.l.acquire() dcm.SetParser(parser) grouper.AddFile(dcm)
It will produce a 'merge.dcm' output file, which contains all meta information from input1.dcm and copy the Stored Pixel values from input2.dcm This script even works when input2.dcm is a Secondary Capture and does not contains information such as IOP and IPP... """ import sys import gdcm if __name__ == "__main__": file1 = sys.argv[1] file2 = sys.argv[2] r1 = gdcm.ImageReader() r1.SetFileName( file1 ) if not r1.Read(): sys.exit(1) r2 = gdcm.ImageReader() r2.SetFileName( file2 ) if not r2.Read(): sys.exit(1) # Image from r2 could be Secondary Capture and thus would not contains neither IPP nor IOP # Instead always prefer to only copy the Raw Data Element. # Warning ! Image need to be identical ! Only the value of Stored Pixel can be different. r1.GetImage().SetDataElement( r2.GetImage().GetDataElement() ) w = gdcm.ImageWriter()
############################################################################ """ Usage: python DecompressImage.py gdcmData/012345.002.050.dcm decompress.dcm """ import gdcm import sys if __name__ == "__main__": file1 = sys.argv[1] file2 = sys.argv[2] r = gdcm.ImageReader() r.SetFileName(file1) if not r.Read(): sys.exit(1) # check GetFragment API: pd = r.GetFile().GetDataSet().GetDataElement(gdcm.Tag(0x7fe0, 0x0010)) frags = pd.GetSequenceOfFragments() frags.GetFragment(0) ir = r.GetImage() w = gdcm.ImageWriter() image = w.GetImage() image.SetNumberOfDimensions(ir.GetNumberOfDimensions()) dims = ir.GetDimensions()
def loadImage_gdcm(filename): """Load a DICOM image into a numpy array. This function uses the python-gdcm module to load a DICOM image into a numpy array. See also :func:`loadImage_dicom` for an equivalent using python-dicom. Parameters: - `file`: the name of a DICOM image file Returns a 3D array with the pixel data of all the images. The first axis is the `z` value, the last the `x`. As a side effect, this function sets the global variable `_dicom_spacing` to a (3,) array with the pixel/slice spacing factors, in order (x,y,z). """ import gdcm def get_gdcm_to_numpy_typemap(): """Returns the GDCM Pixel Format to numpy array type mapping.""" _gdcm_np = { gdcm.PixelFormat.UINT8: np.int8, gdcm.PixelFormat.INT8: np.uint8, #gdcm.PixelFormat.UINT12 :np.uint12, #gdcm.PixelFormat.INT12 :np.int12, gdcm.PixelFormat.UINT16: np.uint16, gdcm.PixelFormat.INT16: np.int16, gdcm.PixelFormat.UINT32: np.uint32, gdcm.PixelFormat.INT32: np.int32, #gdcm.PixelFormat.FLOAT16:np.float16, gdcm.PixelFormat.FLOAT32: np.float32, gdcm.PixelFormat.FLOAT64: np.float64 } return _gdcm_np def get_numpy_array_type(gdcm_pixel_format): """Returns a numpy array typecode given a GDCM Pixel Format.""" return get_gdcm_to_numpy_typemap()[gdcm_pixel_format] def gdcm_to_numpy(image): """Convert a GDCM image to a numpy array. """ fmt = image.GetPixelFormat() if fmt.GetScalarType() not in get_gdcm_to_numpy_typemap().keys(): raise ValueError, "Unsupported Pixel Format\n%s" % fmt shape = (image.GetDimension(0), image.GetDimension(1)) if image.GetNumberOfDimensions() == 3: shape = shape + (image.GetDimension(2), ) if fmt.GetSamplesPerPixel() != 1: raise ValueError, "Can not read images with multiple samples per pixel." dtype = get_numpy_array_type(fmt.GetScalarType()) gdcm_array = image.GetBuffer() data = np.frombuffer(gdcm_array, dtype=dtype).reshape(shape) spacing = np.array(image.GetSpacing()) return data, spacing global _dicom_spacing r = gdcm.ImageReader() r.SetFileName(filename) if not r.Read(): raise ValueError, "Could not read image file '%s'" % filename pix, _dicom_spacing = gdcm_to_numpy(r.GetImage()) return pix
def _pixel_data_numpy(self): """Return a NumPy array of the pixel data if NumPy is available. Falls back to GDCM in case of unsupported transfer syntaxes. Raises ------ TypeError If there is no pixel data or not a supported data type ImportError If NumPy isn't found, or in the case of fallback, if GDCM isn't found. Returns ------- NumPy array """ if not self._is_uncompressed_transfer_syntax(): if not have_gdcm: raise NotImplementedError( "Pixel Data is compressed in a format pydicom does not yet handle. Cannot return array. Pydicom might be able to convert the pixel data using GDCM if it is installed." ) elif not self.filename: raise NotImplementedError( "GDCM is only supported when the dataset has been created with a filename." ) if not have_numpy: msg = "The Numpy package is required to use pixel_array, and numpy could not be imported." raise ImportError(msg) if 'PixelData' not in self: raise TypeError("No pixel data found in this dataset.") # There are two cases: # 1) uncompressed PixelData -> use numpy # 2) compressed PixelData, filename is available and GDCM is available -> use GDCM is_single_bit = False if self._is_uncompressed_transfer_syntax(): # Make NumPy format code, e.g. "uint16", "int32" etc # from two pieces of info: # self.PixelRepresentation -- 0 for unsigned, 1 for signed; # self.BitsAllocated -- 8, 16, or 32 format_str = '%sint%d' % ( ('u', '')[self.PixelRepresentation], self.BitsAllocated) # Handle SINGLEBIT case if self.BitsAllocated == 1: is_single_bit = True format_str = "uint8" try: numpy_dtype = numpy.dtype(format_str) except TypeError: msg = ("Data type not understood by NumPy: " "format='%s', PixelRepresentation=%d, BitsAllocated=%d") raise TypeError( msg % (format_str, self.PixelRepresentation, self.BitsAllocated)) if (self.is_little_endian != sys_is_little_endian) and not is_single_bit: numpy_dtype = numpy_dtype.newbyteorder('S') pixel_bytearray = self.PixelData elif have_gdcm and self.filename: # read the file using GDCM # FIXME this should just use self.PixelData instead of self.filename # but it is unclear how this should be achieved using GDCM gdcm_image_reader = gdcm.ImageReader() gdcm_image_reader.SetFileName(self.filename) if not gdcm_image_reader.Read(): raise TypeError("GDCM could not read DICOM image") gdcm_image = gdcm_image_reader.GetImage() # determine the correct numpy datatype gdcm_numpy_typemap = { gdcm.PixelFormat.INT8: numpy.int8, gdcm.PixelFormat.UINT8: numpy.uint8, gdcm.PixelFormat.UINT16: numpy.uint16, gdcm.PixelFormat.INT16: numpy.int16, gdcm.PixelFormat.UINT32: numpy.uint32, gdcm.PixelFormat.INT32: numpy.int32, gdcm.PixelFormat.FLOAT32: numpy.float32, gdcm.PixelFormat.FLOAT64: numpy.float64, # Use numpy uint8 for single bits gdcm.PixelFormat.SINGLEBIT: numpy.uint8 } gdcm_pixel_format = gdcm_image.GetPixelFormat().GetScalarType() if gdcm_pixel_format in gdcm_numpy_typemap: numpy_dtype = gdcm_numpy_typemap[gdcm_pixel_format] else: raise TypeError( '{0} is not a GDCM supported pixel format'.format( gdcm_pixel_format)) # GDCM returns char* as type str. Under Python 2 `str` are # byte arrays by default. Python 3 decodes this to # unicode strings by default. # The SWIG docs mention that they always decode byte streams # as utf-8 strings for Python 3, with the `surrogateescape` # error handler configured. # Therefore, we can encode them back to their original bytearray # representation on Python 3 by using the same parameters. pixel_bytearray = gdcm_image.GetBuffer() if sys.version_info >= (3, 0): pixel_bytearray = pixel_bytearray.encode( "utf-8", "surrogateescape") # if GDCM indicates that a byte swap is in order, make sure to inform numpy as well if gdcm_image.GetNeedByteSwap(): numpy_dtype = numpy_dtype.newbyteorder('S') # Here we need to be careful because in some cases, GDCM reads a # buffer that is too large, so we need to make sure we only include # the first n_rows * n_columns * dtype_size bytes. # Only check padding in case other format than SingleBIT if gdcm_pixel_format != gdcm.PixelFormat.SINGLEBIT: n_bytes = self.Rows * self.Columns * numpy.dtype( numpy_dtype).itemsize if len(pixel_bytearray) > n_bytes: # We make sure that all the bytes after are in fact zeros padding = pixel_bytearray[n_bytes:] if numpy.any(numpy.fromstring(padding, numpy.byte)): pixel_bytearray = pixel_bytearray[:n_bytes] else: # We revert to the old behavior which should then result in a # Numpy error later on. pass else: is_single_bit = True # try: pixel_array = numpy.fromstring(pixel_bytearray, dtype=numpy_dtype) except TypeError: pixel_array = numpy.frombuffer(pixel_bytearray, dtype=numpy_dtype) # Handle SINGLEBIT encoding if is_single_bit: pixel_array = numpy.unpackbits(pixel_array[::-1]) # Note the following reshape operations return a new *view* onto pixel_array, but don't copy the data if 'NumberOfFrames' in self and self.NumberOfFrames > 1: if self.SamplesPerPixel > 1: # TODO: Handle Planar Configuration attribute assert self.PlanarConfiguration == 0 pixel_array = pixel_array.reshape(self.NumberOfFrames, self.Rows, self.Columns, self.SamplesPerPixel) else: pixel_array = pixel_array.reshape(self.NumberOfFrames, self.Rows, self.Columns) else: if self.SamplesPerPixel > 1: if self.BitsAllocated == 8: if self.PlanarConfiguration == 0: pixel_array = pixel_array.reshape( self.Rows, self.Columns, self.SamplesPerPixel) else: pixel_array = pixel_array.reshape( self.SamplesPerPixel, self.Rows, self.Columns) pixel_array = pixel_array.transpose(1, 2, 0) else: raise NotImplementedError( "This code only handles SamplesPerPixel > 1 if Bits Allocated = 8" ) else: pixel_array = pixel_array.reshape(self.Rows, self.Columns) return pixel_array
def get_pixeldata(dicom_dataset): """ Use the GDCM package to decode the PixelData attribute Returns ------- numpy.ndarray A correctly sized (but not shaped) numpy array of the entire data volume Raises ------ ImportError if the required packages are not available TypeError if the image could not be read by GDCM if the pixel data type is unsupported AttributeError if the decoded amount of data does not match the expected amount """ # read the file using GDCM # FIXME this should just use dicom_dataset.PixelData # instead of dicom_dataset.filename # but it is unclear how this should be achieved using GDCM if not can_use_gdcm: msg = ("GDCM requires both the gdcm package and numpy " "and one or more could not be imported") raise ImportError(msg) gdcm_image_reader = gdcm.ImageReader() if compat.in_py2: if isinstance(dicom_dataset.filename, unicode): gdcm_image_reader.SetFileName( dicom_dataset.filename.encode(sys.getfilesystemencoding())) else: gdcm_image_reader.SetFileName(dicom_dataset.filename) else: # python 3 gdcm_image_reader.SetFileName(dicom_dataset.filename) if not gdcm_image_reader.Read(): raise TypeError("GDCM could not read DICOM image") gdcm_image = gdcm_image_reader.GetImage() # determine the correct numpy datatype gdcm_numpy_typemap = { gdcm.PixelFormat.INT8: numpy.int8, gdcm.PixelFormat.UINT8: numpy.uint8, gdcm.PixelFormat.UINT16: numpy.uint16, gdcm.PixelFormat.INT16: numpy.int16, gdcm.PixelFormat.UINT32: numpy.uint32, gdcm.PixelFormat.INT32: numpy.int32, gdcm.PixelFormat.FLOAT32: numpy.float32, gdcm.PixelFormat.FLOAT64: numpy.float64 } gdcm_pixel_format = gdcm_image.GetPixelFormat().GetScalarType() if gdcm_pixel_format in gdcm_numpy_typemap: numpy_dtype = gdcm_numpy_typemap[gdcm_pixel_format] else: raise TypeError('{0} is not a GDCM supported ' 'pixel format'.format(gdcm_pixel_format)) # GDCM returns char* as type str. Under Python 2 `str` are # byte arrays by default. Python 3 decodes this to # unicode strings by default. # The SWIG docs mention that they always decode byte streams # as utf-8 strings for Python 3, with the `surrogateescape` # error handler configured. # Therefore, we can encode them back to their original bytearray # representation on Python 3 by using the same parameters. pixel_bytearray = gdcm_image.GetBuffer() if sys.version_info >= (3, 0): pixel_bytearray = pixel_bytearray.encode("utf-8", "surrogateescape") # if GDCM indicates that a byte swap is in order, make # sure to inform numpy as well if gdcm_image.GetNeedByteSwap(): numpy_dtype = numpy_dtype.newbyteorder('S') # Here we need to be careful because in some cases, GDCM reads a # buffer that is too large, so we need to make sure we only include # the first n_rows * n_columns * dtype_size bytes. n_bytes = (dicom_dataset.Rows * dicom_dataset.Columns * numpy.dtype(numpy_dtype).itemsize) try: n_bytes *= dicom_dataset.NumberOfFrames except Exception: pass try: n_bytes *= dicom_dataset.SamplesPerPixel except Exception: pass if len(pixel_bytearray) > n_bytes: # We make sure that all the bytes after are in fact zeros padding = pixel_bytearray[n_bytes:] if numpy.any(numpy.frombuffer(padding, numpy.byte)): pixel_bytearray = pixel_bytearray[:n_bytes] else: # We revert to the old behavior which should then result # in a Numpy error later on. pass pixel_array = numpy.frombuffer(pixel_bytearray, dtype=numpy_dtype) length_of_pixel_array = pixel_array.nbytes expected_length = dicom_dataset.Rows * dicom_dataset.Columns expected_length *= dicom_dataset.get("NumberOfFrames", 1) expected_length *= dicom_dataset.get("SamplesPerPixel", 1) if dicom_dataset.BitsAllocated > 8: expected_length *= (dicom_dataset.BitsAllocated // 8) if length_of_pixel_array != expected_length: raise AttributeError("Amount of pixel data %d does " "not match the expected data %d" % (length_of_pixel_array, expected_length)) if should_change_PhotometricInterpretation_to_RGB(dicom_dataset): dicom_dataset.PhotometricInterpretation = "RGB" return pixel_array
def TestImageRead(filename, verbose=False): r = gdcm.ImageReader() r.SetFileName(filename) success = r.Read() if verbose: print r.GetImage() return success
def run(self): grouper = self.grouper reader = gdcm.ImageReader() if _has_win32api: try: reader.SetFileName( utils.encode(win32api.GetShortPathName(self.filepath), const.FS_ENCODE)) except TypeError: reader.SetFileName(win32api.GetShortPathName(self.filepath)) else: try: reader.SetFileName(utils.encode(self.filepath, const.FS_ENCODE)) except TypeError: reader.SetFileName(self.filepath) if (reader.Read()): file = reader.GetFile() # Retrieve data set dataSet = file.GetDataSet() # Retrieve header header = file.GetHeader() stf = gdcm.StringFilter() stf.SetFile(file) field_dict = {} data_dict = {} tag = gdcm.Tag(0x0008, 0x0005) ds = reader.GetFile().GetDataSet() if ds.FindDataElement(tag): encoding_value = str( ds.GetDataElement(tag).GetValue()).split('\\')[0] if encoding_value.startswith("Loaded"): encoding = "ISO_IR 100" else: try: encoding = const.DICOM_ENCODING_TO_PYTHON[ encoding_value] except KeyError: encoding = 'ISO_IR 100' else: encoding = "ISO_IR 100" # Iterate through the Header iterator = header.GetDES().begin() while (not iterator.equal(header.GetDES().end())): dataElement = iterator.next() if not dataElement.IsUndefinedLength(): tag = dataElement.GetTag() data = stf.ToStringPair(tag) stag = tag.PrintAsPipeSeparatedString() group = str(tag.GetGroup()) field = str(tag.GetElement()) tag_labels[stag] = data[0] if not group in data_dict.keys(): data_dict[group] = {} if not (utils.VerifyInvalidPListCharacter(data[1])): data_dict[group][field] = utils.decode( data[1], encoding) else: data_dict[group][field] = "Invalid Character" # Iterate through the Data set iterator = dataSet.GetDES().begin() while (not iterator.equal(dataSet.GetDES().end())): dataElement = iterator.next() if not dataElement.IsUndefinedLength(): tag = dataElement.GetTag() # if (tag.GetGroup() == 0x0009 and tag.GetElement() == 0x10e3) \ # or (tag.GetGroup() == 0x0043 and tag.GetElement() == 0x1027): # continue data = stf.ToStringPair(tag) stag = tag.PrintAsPipeSeparatedString() group = str(tag.GetGroup()) field = str(tag.GetElement()) tag_labels[stag] = data[0] if not group in data_dict.keys(): data_dict[group] = {} if not (utils.VerifyInvalidPListCharacter(data[1])): data_dict[group][field] = utils.decode( data[1], encoding, 'replace') else: data_dict[group][field] = "Invalid Character" # -------------- To Create DICOM Thumbnail ----------- try: data = data_dict[str(0x028)][str(0x1050)] level = [float(value) for value in data.split('\\')][0] data = data_dict[str(0x028)][str(0x1051)] window = [float(value) for value in data.split('\\')][0] except (KeyError, ValueError): level = None window = None if _has_win32api: thumbnail_path = imagedata_utils.create_dicom_thumbnails( win32api.GetShortPathName(self.filepath), window, level) else: thumbnail_path = imagedata_utils.create_dicom_thumbnails( self.filepath, window, level) #------ Verify the orientation -------------------------------- img = reader.GetImage() direc_cosines = img.GetDirectionCosines() orientation = gdcm.Orientation() try: _type = orientation.GetType(tuple(direc_cosines)) except TypeError: _type = orientation.GetType(direc_cosines) label = orientation.GetLabel(_type) # ---------- Refactory -------------------------------------- data_dict['invesalius'] = {'orientation_label': label} # ------------------------------------------------------------- dict_file[self.filepath] = data_dict #---------- Verify is DICOMDir ------------------------------- is_dicom_dir = 1 try: if (data_dict[str(0x002)][str(0x002)] != "1.2.840.10008.1.3.10"): #DICOMDIR is_dicom_dir = 0 except (KeyError): is_dicom_dir = 0 if not (is_dicom_dir): parser = dicom.Parser() parser.SetDataImage(dict_file[self.filepath], self.filepath, thumbnail_path) dcm = dicom.Dicom() #self.l.acquire() dcm.SetParser(parser) grouper.AddFile(dcm)