Getting rid of DICOM images in Python Part 2

This is a continuation of Getting rid of DICOM images in Python. The information is as of September 2017.

PyDicom now seems to have a version of 1.0.0a1 when downloaded from github.

_versions.py


"""Pure python package for DICOM medical file reading and writing."""

__version__ = '1.0.0a1'
__version_info__ = (1, 0, 0, 'alpha', 0)

However, it seems that pydicom that can be installed with conda-forge or PyPI is still 0.9.9. Since 1.0 and later, there are various changes, so the document also has a chapter called Transition to pydicom 1.x. For the time being, I will create this page in compliance with 0.9.9.

Get a sample DICOM image

In the previous Getting rid of DICOM images with Python, Osirix's [DICOM Image Library](http: //) is the source of DICOM image samples. I introduced www.osirix-viewer.com/resources/dicom-image-library/), but now it seems that only Osirix users can access it.

For that reason, I would like to introduce the following two sources for obtaining DICOM image samples.

Show all DICOM headers

For the DICOM headers you know, you can display them as follows: What Modality is this image taken? It is displayed.

import dicom
dcm = dicom.read_file('CT_small.dcm')
print(dcm.Modality)

Also, if you just want to display everything in text, you don't need to do anything.

import dicom
dcm = dicom.read_file('CT_small.dcm')
print(dcm)

So what if you want to print all the headers (but not the images) like this `` `print (dcm) ```? So, I tried to chase the source code a little.

Then there was a hint in pydicom / dataelem.py.

dataelem.py


def __str__(self):
  """Return str representation of the element."""
  repVal = self.repval
  if self.showVR:
    s = "%s %-*s %s: %s" % (str(self.tag), self.descripWidth,
                            self.description()[:self.descripWidth],
                            self.VR, repVal)
  else:
    s = "%s %-*s %s" % (str(self.tag), self.descripWidth,
                        self.description()[:self.descripWidth], repVal)
  return s

Apparently, does the property `` `showVR``` show the data type of the DICOM header? It seems that it is a flag of.

What kind of VR is there? That's because you should definitely look at the DICOM Specifications (http://dicom.nema.org/dicom/2013/output/chtml/part05/sect_6.2.html).

With that in mind, if you just squeeze `__str__ ()` of `` `dataelem.py``` as it is, all the metadata tags, names, types and displays will be listed in .append () It seems that you can get all the data by doing something like that.

import dicom
dcm = dicom.read_file('CT_small.dcm')
dcm_header_list = []
for data_element in dcm:
    dcm_header = '{0}\t{1}\t{2}\n'.format(str(data_element.tag),
                                          data_element.name,
                                          data_element.repval)
    dcm_header_list.append(dcm_header)

Create a MIP image from 3D image data

As described in Getting rid of DICOM images with Python, you can combine slices to create 3D data. Image data from DICOM files can be retrieved from pixel_array as a numpy array.

import os
import dicom
import numpy as np

dcm_list = []
for root_d, _, files in os.walk('BRAINIX'):
  for f in files:
    _, ext = os.path.splitext(f)
    if ext == '.dcm':
      dcm_list.append(os.path.join(root_d, f))

ref_dcm = dicom.read_file(dcm_list[0])
width = ref_dcm.Columns
height = ref_dcm.Rows
depth = len(ref_dcm)

img3d = np.zeros((depth, height, width), 
                  dtype = ref_dcm.pixel_array.dtype)
for dcm_file in dcm_list:
  idx = dcm_list.index(dcm_file)
  dcm = dicom.read_file(dcm_file)
  img3d[idx, :, :] = dcm.pixel_array()

As a result, DICOM image data is stored in a three-dimensional array called img3d. In order to visualize this, it is converted into a two-dimensional image using a method called MIP (Maximum Intensity Projection) or MinIP (Minimum Intensity Projection).

Which axis should be used to create a cross-sectional image of 3D image data? And which axis of pixels should be used as the representative value when creating a two-dimensional image along that axis? That being said, MIP uses the pixel with the highest brightness, and MinIP uses the pixel with the lowest brightness as a representative value.

Which cross section should be used for the human body? For that, each cross section has a name. Wikipedia article: Anatomical_plane

Whether you use the maximum value or the minimum value, you'll be able to use the numpy array from here.

#Omission
max0 = np.nanmax(img3d, axis=0)
max1 = np.nanmax(img3d, axis=1)
max2 = np.nanmax(img3d, axis=2)

In the case of the BRAINIX MRI image this time, axis = 0 corresponds to the Coronal Plane, so max0 stores the MIP image of the Coronal Plane. After that, `matplotlib.imshow ()`, im = Image.fromarray (max0) `` `in PIL, then im.show () I think it's OK.

Whether the cross section of the original image is axial, coronal, or sagittal seems to have to be judged from the original image, but if you make a 3D array like img3d in this way, from which cross section It will also be possible to cut out.

In general, CT is imaged in the axial plane, so I think it is three-dimensional [axial, coronal, sagittal].


Summary

I wrote the continuation of Getting rid of DICOM images with Python.

Recommended Posts

Getting rid of DICOM images in Python Part 2
Get rid of DICOM images in Python
Pixel manipulation of images in Python
Working with DICOM images in Python
Sample of getting module name and class name in Python
Bordering images with python Part 1
Base64 encoding images in Python 3
Equivalence of objects in Python
UI Automation Part 2 in Python
Faster loading of Python images
Implementation of quicksort in Python
Getting list elements in Python
Basics of Python × GIS (Part 1)
Displaying DICOM images in rudimentary Python as a medical professional
Number recognition in images with Python
Basics of Python x GIS (Part 3)
Getting the arXiv API in Python
How to collect images in Python
Division of timedelta in Python 2.7 series
MySQL-automatic escape of parameters in python
Handling of JSON files in Python
Waveform display of audio in Python
Getting Started with Python Basics of Python
Extract text from images in Python
Basics of Python x GIS (Part 2)
Law of large numbers in python
Implementation of original sorting in Python
Reversible scrambling of integers in Python
Wrap (part of) the AtCoder Library in Cython for use in Python
Basic Linear Algebra Learned in Python (Part 1)
Conversion of string <-> date (date, datetime) in Python
GUI creation in python using tkinter part 1
AM modulation and demodulation in Python Part 2
(Bad) practice of using this in Python
General Theory of Relativity in Python: Introduction
Mosaic images in various shapes (Python, OpenCV)
Output tree structure of files in Python
Display a list of alphabets in Python 3
Comparison of Japanese conversion module in Python3
Implement part of the process in C ++
Summary of various for statements in Python
The result of installing python in Anaconda
Gang of Four (GoF) Patterns in Python
Download images from URL list in Python
The basics of running NoxPlayer in Python
I want to color a part of an Excel string in Python
Bulk replacement of strings in Python arrays
Project Euler # 16 "Sum of Powers" in Python
Traffic Safety-kun: Recognition of traffic signs in Python
Summary of built-in methods in Python list
Non-logical operator usage of or in python
In search of the fastest FizzBuzz in Python
Practical example of Hexagonal Architecture in Python
I tried to refactor the template code posted in "Getting images from Flickr API with Python" (Part 2)
Project Euler # 17 "Number of Characters" in Python
Double pendulum equation of motion in python
Read text in images with python OCR
Status of each Python processing system in 2020
Project Euler # 1 "Multiples of 3 and 5" in Python
Meaning of using DI framework in Python
Japanese translation of self-study "A Beginner's Guide to Getting User Input in Python"