Accelerated DICOM Decoding with nvImageCodec and pydicom#

This notebook introduces how to use the nvImageCodec pydicom plugin for GPU-accelerated DICOM decoding.

The pydicom plugin is the easiest way to get GPU-accelerated DICOM decoding with nvImageCodec. This plugin integrates seamlessly with pydicom’s standard workflow - you just register it once, and then use pydicom normally. The plugin automatically accelerates decoding for supported transfer syntaxes when you access .pixel_array.

Supported Transfer Syntaxes#

The nvImageCodec pydicom plugin supports the following compressed transfer syntaxes:

  • JPEG Baseline (Process 1) - 1.2.840.10008.1.2.4.50

  • JPEG Lossless - 1.2.840.10008.1.2.4.57 & 1.2.840.10008.1.2.4.70

  • JPEG 2000 - 1.2.840.10008.1.2.4.90 & 1.2.840.10008.1.2.4.91

  • HTJ2K (High-Throughput JPEG 2000) - 1.2.840.10008.1.2.4.201, 1.2.840.10008.1.2.4.202, 1.2.840.10008.1.2.4.203

How to Use#

It’s just three simple steps:

  1. Import and register the plugin

  2. Load DICOM files with pydicom.dcmread()

  3. Access pixel data with .pixel_array - GPU acceleration happens automatically!

  4. Unregister (optionally) to stop using the plugin

Let’s see an example:

[1]:
import pydicom
from pydicom.data import get_testdata_file

# Use a JPEG 2000 test file that is bundled with pydicom
test_file = get_testdata_file("emri_small_jpeg_2k_lossless.dcm")
if test_file is None:
    raise FileNotFoundError("No JPEG 2000 test file found. Install pydicom with test data or provide your own DICOM path.")
ds = pydicom.dcmread(test_file, stop_before_pixels=True)
print("Transfer syntax:", ds.file_meta.TransferSyntaxUID)

from pydicom.pixels.decoders import JPEG2000Decoder
print(JPEG2000Decoder._available)
emri_small_jpeg_2k_lossless.dcm:   0%|          | 10.0/40.3k [00:00<00:03, 12.3kB/s]
Transfer syntax: 1.2.840.10008.1.2.4.90
{'pylibjpeg': <function _decode_frame at 0x7f78f6911090>, 'pillow': <function _decode_frame at 0x7f78f6912e60>}

We can see that pydicom has two plugins “pillow” and “pylibjpeg” that can decode JPEG2000 format. We can now register our nvImageCodec plugin to be the first choice:

[2]:
from nvidia.nvimgcodec.tools.dicom import pydicom_plugin
pydicom_plugin.register()
print(JPEG2000Decoder._available)
{'0.8.0+nvimgcodec': <function _decode_frame at 0x7f78b0763370>, 'pillow': <function _decode_frame at 0x7f78f6912e60>, 'pylibjpeg': <function _decode_frame at 0x7f78f6911090>}

We can even clear the list of available decoders to force our decoder to be the only choice for this format. We will do that in this example to be sure that what we decoded was the output of the nvImageCodec plugin

[3]:
pydicom_plugin.unregister()
old_decoder_class_available = {}
from nvidia.nvimgcodec.tools.dicom.pydicom_plugin import SUPPORTED_DECODER_CLASSES
for decoder_class in SUPPORTED_DECODER_CLASSES:
    old_decoder_class_available[decoder_class.UID] = decoder_class._available
    decoder_class._available = {}
pydicom_plugin.register()
print(JPEG2000Decoder._available)

{'0.8.0+nvimgcodec': <function _decode_frame at 0x7f78b0763370>}

Now we can access to pixel data, which will use accelerated GPU decoding via nvImageCodec:

[4]:
ds = pydicom.dcmread(test_file)
pixels = ds.pixel_array
print(pixels.shape)
pixels = pixels[0]  # first frame

# Plot the image pixel data
import matplotlib.pyplot as plt
plt.imshow(pixels, cmap="gray")
plt.title("DICOM Pixel Data (GPU Decoded via nvImageCodec)")
(10, 64, 64)
[4]:
Text(0.5, 1.0, 'DICOM Pixel Data (GPU Decoded via nvImageCodec)')
../_images/samples_DICOM-pydicom_8_2.png

Now that the plugin is registered, any time you load a DICOM file with a supported compressed transfer syntax and access .pixel_array, nvImageCodec will automatically handle the decoding on the GPU.

Performance Comparison#

Let’s compare the performance of the nvImageCodec plugin against the default pydicom decoders. We’ll use the performance test from the test suite to benchmark decoding speed across various DICOM files.

[5]:
# Run performance benchmarks
import sys
import os
from pathlib import Path
import io
from contextlib import redirect_stdout, redirect_stderr

test_dir_root = os.getenv("PYNVIMGCODEC_TEST_DIR", "../../test/python")
test_dir = Path(test_dir_root) / "integration" / "dicom"
if str(test_dir) not in sys.path:
    sys.path.insert(0, str(test_dir))

print("Downloading test DICOM files")
# Silence output from get_test_dicoms
with redirect_stdout(io.StringIO()), redirect_stderr(io.StringIO()):
    from pydicom.data  import get_testdata_files
    files = get_testdata_files("*.dcm")

from test_pydicom_plugin import performance_test_nvimgcodec_decoder_against_defaults

for decoder_class in SUPPORTED_DECODER_CLASSES:
    decoder_class._available = old_decoder_class_available[decoder_class.UID]

# Run the performance test with a small number of runs for demo purposes
print("Running performance benchmarks...")
print("This compares CPU-based decoders (baseline) vs GPU-accelerated nvImageCodec plugin\n")

performance_test_nvimgcodec_decoder_against_defaults(
    num_warmup_runs=2,
    num_test_runs=5,
    file_paths=files,
)
Downloading test DICOM files
/opt/.nvimgcodec_test_venv/lib/python3.10/site-packages/pydicom/filereader.py:402: UserWarning: Expected explicit VR, but found implicit VR - using implicit VR for reading
  warn_and_log(f"{msg} - using {found_vr} VR for reading", UserWarning)
Running performance benchmarks...
This compares CPU-based decoders (baseline) vs GPU-accelerated nvImageCodec plugin

Error testing ExplVR_BigEndNoMeta.dcm: File is missing DICOM File Meta Information header or the 'DICM' prefix is missing from the header. Use force=True to force reading.
Error testing JPEG2000-embedded-sequence-delimiter.dcm: Unable to decode as exceptions were raised by all available plugins:
  pillow: Image size (3811783737344 pixels) exceeds limit of 178956970 pixels, could be decompression bomb DOS attack.
  pylibjpeg: Error decoding the J2K data: failed to read the header
Error testing meta_missing_tsyntax.dcm: Unable to decode the pixel data as the dataset's 'file_meta' has no (0002,0010) 'Transfer Syntax UID' element
Error testing rtstruct.dcm: File is missing DICOM File Meta Information header or the 'DICM' prefix is missing from the header. Use force=True to force reading.
/opt/.nvimgcodec_test_venv/lib/python3.10/site-packages/pydicom/pixels/decoders/base.py:814: UserWarning: The pixel data is 8320 bytes long, which indicates it contains 128 bytes of excess padding to be removed
  warn_and_log(
Error testing priv_SQ.dcm: The dataset has no 'Pixel Data', 'Float Pixel Data' or 'Double Float Pixel Data' element, no pixel data to decode
Error testing waveform_ecg.dcm: The dataset has no 'Pixel Data', 'Float Pixel Data' or 'Double Float Pixel Data' element, no pixel data to decode
Error testing JPEG-lossy.dcm: Unable to decode as exceptions were raised by all available plugins:
  pylibjpeg: libjpeg error code '-1038' returned from Decode(): A misplaced marker segment was found - scan start must be zero and scan stop must be 63 for the sequential operating modes
  pillow: Pillow does not support 'JPEG Extended' for samples with 12-bit precision
Error testing reportsi.dcm: The dataset has no 'Pixel Data', 'Float Pixel Data' or 'Double Float Pixel Data' element, no pixel data to decode
Error testing rtplan_truncated.dcm: The dataset has no 'Pixel Data', 'Float Pixel Data' or 'Double Float Pixel Data' element, no pixel data to decode
Error testing MR_truncated.dcm: The number of bytes of pixel data is less than expected (8130 vs 8192 bytes) - the dataset may be corrupted, have an invalid group 0028 element value, or the transfer syntax may be incorrect
Error testing ExplVR_LitEndNoMeta.dcm: File is missing DICOM File Meta Information header or the 'DICM' prefix is missing from the header. Use force=True to force reading.
/opt/.nvimgcodec_test_venv/lib/python3.10/site-packages/pydicom/pixels/decoders/base.py:302: UserWarning: The (0028,0004) 'Photometric Interpretation' value is 'RGB' however the encoded image's codestream contains a JFIF APP marker which indicates it should be 'YBR_FULL_422'
  warn_and_log(
Error testing test-SR.dcm: The dataset has no 'Pixel Data', 'Float Pixel Data' or 'Double Float Pixel Data' element, no pixel data to decode
Error testing no_meta_group_length.dcm: The dataset has no 'Pixel Data', 'Float Pixel Data' or 'Double Float Pixel Data' element, no pixel data to decode
Error testing rtplan.dcm: The dataset has no 'Pixel Data', 'Float Pixel Data' or 'Double Float Pixel Data' element, no pixel data to decode
Error testing no_meta.dcm: File is missing DICOM File Meta Information header or the 'DICM' prefix is missing from the header. Use force=True to force reading.
Error testing UN_sequence.dcm: The dataset has no 'Pixel Data', 'Float Pixel Data' or 'Double Float Pixel Data' element, no pixel data to decode
Error testing nested_priv_SQ.dcm: Missing required element: (0028,0100) 'Bits Allocated'
/opt/.nvimgcodec_test_venv/lib/python3.10/site-packages/pydicom/valuerep.py:440: UserWarning: Invalid value for VR IS: '1A'. Please see <https://dicom.nema.org/medical/dicom/current/output/html/part05.html#table_6.2-1> for allowed values for each VR.
  warn_and_log(msg)
Error testing badVR.dcm: invalid literal for int() with base 10: '1A'
Error testing reportsi_with_empty_number_tags.dcm: The dataset has no 'Pixel Data', 'Float Pixel Data' or 'Double Float Pixel Data' element, no pixel data to decode
Error testing empty_charset_LEI.dcm: The dataset has no 'Pixel Data', 'Float Pixel Data' or 'Double Float Pixel Data' element, no pixel data to decode
/opt/.nvimgcodec_test_venv/lib/python3.10/site-packages/pydicom/filereader.py:487: UserWarning: End of file reached before delimiter (FFFE,E0DD) found in file /root/.pydicom/data/emri_small_jpeg_2k_lossless_too_short.dcm
  warn_and_log(msg, UserWarning)
Error testing emri_small_jpeg_2k_lossless_too_short.dcm: The dataset has no 'Pixel Data', 'Float Pixel Data' or 'Double Float Pixel Data' element, no pixel data to decode
Error testing OT-PAL-8-face.dcm: File is missing DICOM File Meta Information header or the 'DICM' prefix is missing from the header. Use force=True to force reading.
Error testing JLSL_RGB_ILV0.dcm: File is missing DICOM File Meta Information header or the 'DICM' prefix is missing from the header. Use force=True to force reading.
Error testing JLSL_RGB_ILV1.dcm: File is missing DICOM File Meta Information header or the 'DICM' prefix is missing from the header. Use force=True to force reading.
Error testing JLSL_RGB_ILV2.dcm: File is missing DICOM File Meta Information header or the 'DICM' prefix is missing from the header. Use force=True to force reading.
Error testing JLSN_RGB_ILV0.dcm: File is missing DICOM File Meta Information header or the 'DICM' prefix is missing from the header. Use force=True to force reading.

## Performance Results (2 warmup, 5 test runs)

| Transfer Syntax | Shape | Baseline (s) | Std | nvimgcodec (s) | Std | Speedup | File |
| --- | --- | --- | --- | --- | --- | --- | --- |
| 1.2.840.10008.1.2.4.50 | 100x100x3 | 0.0018 | 0.0001 | 0.0013 | 0.0000 | 1.38x | SC_rgb_dcmtk_+eb+cy+np.dcm |
| 1.2.840.10008.1.2.2 | 15x10x10 | 0.0009 | 0.0000 | 0.0009 | 0.0000 | 1.03x | rtdose_expb.dcm |
| 1.2.840.10008.1.2.4.50 | 100x100x3 | 0.0021 | 0.0000 | 0.0015 | 0.0000 | 1.42x | SC_rgb_jpeg_lossy_gdcm.dcm |
| 1.2.840.10008.1.2.1 | 64x64 | 0.0012 | 0.0000 | 0.0012 | 0.0000 | 1.01x | MR_small_padded.dcm |
| 1.2.840.10008.1.2.5 | 100x100x3 | 0.0013 | 0.0000 | 0.0013 | 0.0000 | 1.00x | SC_rgb_rle.dcm |
| 1.2.840.10008.1.2.4.90 | 400x400x3 | 0.0344 | 0.0013 | 0.0261 | 0.0005 | 1.32x | GDCMJ2K_TextGBR.dcm |
| 1.2.840.10008.1.2 | 10x10 | 0.0008 | 0.0000 | 0.0007 | 0.0000 | 1.02x | rtdose_1frame.dcm |
| 1.2.840.10008.1.2.5 | 15x10x10 | 0.0015 | 0.0001 | 0.0015 | 0.0001 | 1.02x | rtdose_rle.dcm |
| 1.2.840.10008.1.2.4.81 | 100x100x3 | 0.0012 | 0.0000 | 0.0012 | 0.0000 | 1.02x | SC_rgb_jls_lossy_line.dcm |
| 1.2.840.10008.1.2.1 | 64x64 | 0.0009 | 0.0000 | 0.0009 | 0.0000 | 0.95x | MR_small.dcm |
| 1.2.840.10008.1.2.4.90 | 64x64 | 0.0027 | 0.0001 | 0.0047 | 0.0000 | 0.56x | MR_small_jp2klossless.dcm |
| 1.2.840.10008.1.2.4.81 | 50x10 | 0.0014 | 0.0000 | 0.0014 | 0.0000 | 1.01x | JPEGLSNearLossless_16.dcm |
| 1.2.840.10008.1.2.5 | 2x100x100x3 | 0.0021 | 0.0001 | 0.0021 | 0.0000 | 0.99x | SC_rgb_rle_32bit_2frame.dcm |
| 1.2.840.10008.1.2.1 | 512x512 | 0.0024 | 0.0001 | 0.0024 | 0.0001 | 1.01x | liver_1frame.dcm |
| 1.2.840.10008.1.2.1 | 100x100x3 | 0.0017 | 0.0002 | 0.0015 | 0.0001 | 1.08x | SC_ybr_full_422_uncompressed.dcm |
| 1.2.840.10008.1.2.2 | 64x64 | 0.0009 | 0.0000 | 0.0008 | 0.0000 | 1.08x | MR_small_bigendian.dcm |
| 1.2.840.10008.1.2.5 | 10x10 | 0.0009 | 0.0000 | 0.0009 | 0.0000 | 0.96x | rtdose_rle_1frame.dcm |
| 1.2.840.10008.1.2 | 15x10x10 | 0.0008 | 0.0000 | 0.0008 | 0.0000 | 0.99x | rtdose.dcm |
| 1.2.840.10008.1.2.4.50 | 100x100x3 | 0.0012 | 0.0000 | 0.0012 | 0.0000 | 0.96x | SC_rgb_dcmtk_+eb+cr.dcm |
| 1.2.840.10008.1.2.4.50 | 3x3x3 | 0.0012 | 0.0000 | 0.0013 | 0.0000 | 0.97x | SC_rgb_small_odd_jpeg.dcm |
| 1.2.840.10008.1.2.4.50 | 100x100x3 | 0.0017 | 0.0000 | 0.0012 | 0.0000 | 1.44x | SC_rgb_dcmtk_+eb+cy+n2.dcm |
| 1.2.840.10008.1.2.1 | 350x800 | 0.0011 | 0.0001 | 0.0011 | 0.0001 | 0.99x | examples_palette.dcm |
| 1.2.840.10008.1.2.4.90 | 480x640x3 | 0.0883 | 0.0007 | 0.0127 | 0.0002 | 6.95x | examples_jpeg2k.dcm |
| 1.2.840.10008.1.2.4.81 | 100x100x3 | 0.0014 | 0.0000 | 0.0014 | 0.0001 | 1.01x | SC_rgb_jls_lossy_sample.dcm |
| 1.2.840.10008.1.2.4.91 | 512x512 | 0.0083 | 0.0001 | 0.0030 | 0.0000 | 2.76x | 693_J2KI.dcm |
| 1.2.840.10008.1.2.4.50 | 30x240x320x3 | 0.0914 | 0.0037 | 0.0128 | 0.0008 | 7.11x | examples_ybr_color.dcm |
| 1.2.840.10008.1.2.4.51 | 1024x256 | 0.0050 | 0.0002 | 0.0052 | 0.0001 | 0.96x | JPGExtended.dcm |
| 1.2.840.10008.1.2.4.50 | 256x256x3 | 0.0014 | 0.0001 | 0.0013 | 0.0000 | 1.07x | SC_jpeg_no_color_transform.dcm |
| 1.2.840.10008.1.2.4.50 | 100x100x3 | 0.0023 | 0.0008 | 0.0014 | 0.0004 | 1.66x | SC_rgb_jpeg_dcmtk.dcm |
| 1.2.840.10008.1.2 | 64x64 | 0.0008 | 0.0000 | 0.0008 | 0.0000 | 1.04x | MR_small_implicit.dcm |
| 1.2.840.10008.1.2.1.99 | 512x512 | 0.0010 | 0.0000 | 0.0011 | 0.0001 | 0.91x | image_dfl.dcm |
| 1.2.840.10008.1.2.4.50 | 256x256x3 | 0.0015 | 0.0000 | 0.0013 | 0.0000 | 1.16x | SC_jpeg_no_color_transform_2.dcm |
| 1.2.840.10008.1.2.2 | 60x80x3 | 0.0009 | 0.0000 | 0.0009 | 0.0000 | 1.08x | ExplVR_BigEnd.dcm |
| 1.2.840.10008.1.2 | 256x256x3 | 0.0008 | 0.0000 | 0.0008 | 0.0000 | 1.00x | SC_rgb_jpeg_dcmd.dcm |
| 1.2.840.10008.1.2.4.50 | 100x100x3 | 0.0018 | 0.0001 | 0.0012 | 0.0000 | 1.44x | SC_rgb_dcmtk_+eb+cy+s4.dcm |
| 1.2.840.10008.1.2.4.50 | 100x100x3 | 0.0017 | 0.0001 | 0.0012 | 0.0000 | 1.42x | SC_rgb_dcmtk_+eb+cy+s2.dcm |
| 1.2.840.10008.1.2.5 | 2x100x100x3 | 0.0016 | 0.0000 | 0.0016 | 0.0000 | 1.00x | SC_rgb_rle_16bit_2frame.dcm |
| 1.2.840.10008.1.2.4.91 | 1024x256 | 0.0091 | 0.0001 | 0.0021 | 0.0000 | 4.37x | JPEG2000.dcm |
| 1.2.840.10008.1.2.1 | 128x128 | 0.0016 | 0.0002 | 0.0014 | 0.0000 | 1.13x | CT_small.dcm |
| 1.2.840.10008.1.2.4.80 | 64x64 | 0.0023 | 0.0000 | 0.0023 | 0.0000 | 1.01x | MR_small_jpeg_ls_lossless.dcm |
| 1.2.840.10008.1.2.1 | 240x320x3 | 0.0009 | 0.0000 | 0.0009 | 0.0000 | 0.97x | examples_rgb_color.dcm |
| 1.2.840.10008.1.2.4.91 | 100x100x3 | 0.0032 | 0.0001 | 0.0077 | 0.0001 | 0.41x | SC_rgb_gdcm_KY.dcm |
| 1.2.840.10008.1.2.1 | 3x3x3 | 0.0010 | 0.0001 | 0.0009 | 0.0000 | 1.05x | SC_rgb_small_odd.dcm |
| 1.2.840.10008.1.2.5 | 100x100x3 | 0.0016 | 0.0000 | 0.0015 | 0.0000 | 1.07x | SC_rgb_rle_32bit.dcm |
| 1.2.840.10008.1.2.4.81 | 45x10 | 0.0009 | 0.0000 | 0.0009 | 0.0000 | 0.95x | JPEGLSNearLossless_08.dcm |
| 1.2.840.10008.1.2.1 | 300x484 | 0.0012 | 0.0000 | 0.0013 | 0.0000 | 0.98x | examples_overlay.dcm |
| 1.2.840.10008.1.2.2 | 512x512 | 0.0009 | 0.0000 | 0.0009 | 0.0000 | 1.01x | liver_expb_1frame.dcm |
| 1.2.840.10008.1.2.4.50 | 256x256x3 | 0.0014 | 0.0001 | 0.0013 | 0.0000 | 1.10x | SC_rgb_jpeg.dcm |
| 1.2.840.10008.1.2.2 | 64x64 | 0.0009 | 0.0000 | 0.0009 | 0.0000 | 1.03x | MR_small_expb.dcm |
| 1.2.840.10008.1.2.2 | 10x10 | 0.0008 | 0.0000 | 0.0008 | 0.0000 | 1.01x | rtdose_expb_1frame.dcm |
| 1.2.840.10008.1.2.4.50 | 256x256x3 | 0.0015 | 0.0000 | 0.0013 | 0.0000 | 1.18x | SC_rgb_jpeg_app14_dcmd.dcm |
| 1.2.840.10008.1.2.4.70 | 100x100x3 | 0.0019 | 0.0001 | 0.0014 | 0.0000 | 1.37x | SC_rgb_jpeg_gdcm.dcm |
| 1.2.840.10008.1.2.4.90 | 512x512 | 0.0607 | 0.0008 | 0.0289 | 0.0081 | 2.10x | J2K_pixelrep_mismatch.dcm |
| 1.2.840.10008.1.2.2 | 3x3x3 | 0.0009 | 0.0000 | 0.0010 | 0.0000 | 0.93x | SC_rgb_small_odd_big_endian.dcm |
| 1.2.840.10008.1.2.5 | 2x100x100x3 | 0.0013 | 0.0000 | 0.0014 | 0.0003 | 0.88x | SC_rgb_rle_2frame.dcm |
| 1.2.840.10008.1.2.5 | 64x64 | 0.0012 | 0.0000 | 0.0012 | 0.0000 | 1.01x | MR_small_RLE.dcm |
| 1.2.840.10008.1.2.4.50 | 100x100x3 | 0.0018 | 0.0000 | 0.0012 | 0.0000 | 1.52x | SC_rgb_dcmtk_+eb+cy+n1.dcm |
| 1.2.840.10008.1.2.5 | 100x100x3 | 0.0012 | 0.0000 | 0.0012 | 0.0000 | 1.00x | SC_rgb_rle_16bit.dcm |
| 1.2.840.10008.1.2.4.90 | 512x512 | 0.0486 | 0.0014 | 0.0155 | 0.0001 | 3.13x | 693_J2KR.dcm |
| 1.2.840.10008.1.2.1 | 512x512 | 0.0014 | 0.0001 | 0.0013 | 0.0000 | 1.03x | 693_UNCI.dcm |
| 1.2.840.10008.1.2.1 | 512x512 | 0.0012 | 0.0001 | 0.0012 | 0.0001 | 0.99x | 693_UNCR.dcm |
| 1.2.840.10008.1.2.4.70 | 512x512 | 0.0164 | 0.0003 | 0.0036 | 0.0001 | 4.56x | bad_sequence.dcm |
| 1.2.840.10008.1.2.1 | 120x256x3 | 0.0011 | 0.0000 | 0.0010 | 0.0000 | 1.03x | color-pl.dcm |
| 1.2.840.10008.1.2.1 | 120x256x3 | 0.0010 | 0.0004 | 0.0008 | 0.0000 | 1.22x | color-px.dcm |
| 1.2.840.10008.1.2.4.50 | 120x480x640x3 | 1.5533 | 0.0079 | 0.1333 | 0.0003 | 11.65x | color3d_jpeg_baseline.dcm |
| 1.2.840.10008.1.2.1 | 2x512x512 | 0.0025 | 0.0000 | 0.0025 | 0.0000 | 1.01x | eCT_Supplemental.dcm |
| 1.2.840.10008.1.2.1 | 10x64x64 | 0.0012 | 0.0000 | 0.0012 | 0.0000 | 0.99x | emri_small.dcm |
| 1.2.840.10008.1.2.2 | 10x64x64 | 0.0013 | 0.0000 | 0.0012 | 0.0000 | 1.01x | emri_small_big_endian.dcm |
| 1.2.840.10008.1.2.4.90 | 10x64x64 | 0.0161 | 0.0001 | 0.0463 | 0.0130 | 0.35x | emri_small_jpeg_2k_lossless.dcm |
| 1.2.840.10008.1.2.4.80 | 10x64x64 | 0.0145 | 0.0003 | 0.0145 | 0.0003 | 1.00x | emri_small_jpeg_ls_lossless.dcm |
| 1.2.840.10008.1.2.5 | 10x64x64 | 0.0025 | 0.0000 | 0.0024 | 0.0001 | 1.05x | emri_small_RLE.dcm |
| 1.2.840.10008.1.2.4.90 | 512x512 | 0.0693 | 0.0014 | 0.0162 | 0.0002 | 4.27x | explicit_VR-UN.dcm |
| 1.2.840.10008.1.2 | 480x640 | 0.0011 | 0.0000 | 0.0010 | 0.0000 | 1.00x | gdcm-US-ALOKA-16.dcm |
| 1.2.840.10008.1.2.2 | 480x640 | 0.0011 | 0.0000 | 0.0011 | 0.0000 | 1.00x | gdcm-US-ALOKA-16_big.dcm |
| 1.2.840.10008.1.2.4.70 | 1024x256 | 0.0164 | 0.0002 | 0.0046 | 0.0000 | 3.53x | JPEG-LL.dcm |
| 1.2.840.10008.1.2.1 | 1024x256 | 0.0015 | 0.0000 | 0.0015 | 0.0000 | 1.00x | JPEG2000_UNC.dcm |
| 1.2.840.10008.1.2.4.70 | 768x1024 | 0.0336 | 0.0003 | 0.0104 | 0.0005 | 3.22x | JPGLosslessP14SV1_1s_1f_8b.dcm |
| 1.2.840.10008.1.2.1 | 3x512x512 | 0.0030 | 0.0003 | 0.0026 | 0.0000 | 1.13x | liver.dcm |
| 1.2.840.10008.1.2.2 | 3x512x512 | 0.0010 | 0.0000 | 0.0010 | 0.0000 | 1.00x | liver_expb.dcm |
| 1.2.840.10008.1.2.1 | 3x510x510 | 0.0026 | 0.0000 | 0.0026 | 0.0000 | 1.00x | liver_nonbyte_aligned.dcm |
| 1.2.840.10008.1.2.1 | 512x512 | 0.0010 | 0.0000 | 0.0010 | 0.0000 | 0.97x | mlut_18.dcm |
| 1.2.840.10008.1.2.1 | 484x484 | 0.0012 | 0.0000 | 0.0013 | 0.0000 | 0.95x | MR-SIEMENS-DICOM-WithOverlays.dcm |
| 1.2.840.10008.1.2.4.91 | 1024x1024 | 0.0716 | 0.0024 | 0.0103 | 0.0001 | 6.94x | MR2_J2KI.dcm |
| 1.2.840.10008.1.2.4.90 | 1024x1024 | 0.2225 | 0.0020 | 0.0261 | 0.0013 | 8.53x | MR2_J2KR.dcm |
| 1.2.840.10008.1.2.1 | 1024x1024 | 0.0021 | 0.0001 | 0.0021 | 0.0000 | 1.01x | MR2_UNCI.dcm |
| 1.2.840.10008.1.2.1 | 1024x1024 | 0.0019 | 0.0000 | 0.0019 | 0.0001 | 1.00x | MR2_UNCR.dcm |
| 1.2.840.10008.1.2.1 | 600x800 | 0.0015 | 0.0001 | 0.0014 | 0.0000 | 1.06x | OBXXXX1A.dcm |
| 1.2.840.10008.1.2.1 | 2x600x800 | 0.0017 | 0.0001 | 0.0017 | 0.0000 | 0.98x | OBXXXX1A_2frame.dcm |
| 1.2.840.10008.1.2.2 | 600x800 | 0.0012 | 0.0000 | 0.0012 | 0.0000 | 1.02x | OBXXXX1A_expb.dcm |
| 1.2.840.10008.1.2.2 | 2x600x800 | 0.0015 | 0.0001 | 0.0015 | 0.0000 | 0.99x | OBXXXX1A_expb_2frame.dcm |
| 1.2.840.10008.1.2.5 | 600x800 | 0.0057 | 0.0001 | 0.0058 | 0.0002 | 0.99x | OBXXXX1A_rle.dcm |
| 1.2.840.10008.1.2.5 | 2x600x800 | 0.0101 | 0.0002 | 0.0098 | 0.0001 | 1.03x | OBXXXX1A_rle_2frame.dcm |
| 1.2.840.10008.1.2.4.91 | 1955x1841 | 0.3237 | 0.0035 | 0.0396 | 0.0001 | 8.18x | RG1_J2KI.dcm |
| 1.2.840.10008.1.2.4.90 | 1955x1841 | 1.3623 | 0.0097 | 0.0452 | 0.0044 | 30.12x | RG1_J2KR.dcm |
| 1.2.840.10008.1.2.1 | 1955x1841 | 0.0052 | 0.0001 | 0.0050 | 0.0001 | 1.03x | RG1_UNCI.dcm |
| 1.2.840.10008.1.2.1 | 1955x1841 | 0.0048 | 0.0001 | 0.0047 | 0.0001 | 1.03x | RG1_UNCR.dcm |
| 1.2.840.10008.1.2.4.91 | 1760x1760 | 0.1613 | 0.0023 | 0.0212 | 0.0001 | 7.60x | RG3_J2KI.dcm |
| 1.2.840.10008.1.2.4.90 | 1760x1760 | 0.3576 | 0.0049 | 0.0291 | 0.0001 | 12.30x | RG3_J2KR.dcm |
| 1.2.840.10008.1.2.1 | 1760x1760 | 0.0043 | 0.0000 | 0.0042 | 0.0001 | 1.00x | RG3_UNCI.dcm |
| 1.2.840.10008.1.2.1 | 1760x1760 | 0.0043 | 0.0001 | 0.0044 | 0.0001 | 0.99x | RG3_UNCR.dcm |
| 1.2.840.10008.1.2.1 | 100x100x3 | 0.0015 | 0.0000 | 0.0009 | 0.0000 | 1.69x | SC_rgb.dcm |
| 1.2.840.10008.1.2.1 | 100x100x3 | 0.0009 | 0.0000 | 0.0009 | 0.0000 | 1.00x | SC_rgb_16bit.dcm |
| 1.2.840.10008.1.2.1 | 2x100x100x3 | 0.0010 | 0.0001 | 0.0010 | 0.0001 | 1.00x | SC_rgb_16bit_2frame.dcm |
| 1.2.840.10008.1.2.1 | 2x100x100x3 | 0.0009 | 0.0000 | 0.0009 | 0.0000 | 0.99x | SC_rgb_2frame.dcm |
| 1.2.840.10008.1.2.1 | 100x100x3 | 0.0009 | 0.0000 | 0.0009 | 0.0000 | 1.05x | SC_rgb_32bit.dcm |
| 1.2.840.10008.1.2.1 | 2x100x100x3 | 0.0010 | 0.0000 | 0.0010 | 0.0000 | 1.02x | SC_rgb_32bit_2frame.dcm |
| 1.2.840.10008.1.2.1 | 100x100x3 | 0.0008 | 0.0000 | 0.0009 | 0.0001 | 0.97x | SC_rgb_dcmtk_ebcr_dcmd.dcm |
| 1.2.840.10008.1.2.1 | 100x100x3 | 0.0008 | 0.0000 | 0.0008 | 0.0000 | 1.01x | SC_rgb_dcmtk_ebcyn1_dcmd.dcm |
| 1.2.840.10008.1.2.1 | 100x100x3 | 0.0008 | 0.0000 | 0.0008 | 0.0000 | 1.00x | SC_rgb_dcmtk_ebcyn2_dcmd.dcm |
| 1.2.840.10008.1.2.1 | 100x100x3 | 0.0008 | 0.0000 | 0.0009 | 0.0000 | 0.94x | SC_rgb_dcmtk_ebcynp_dcmd.dcm |
| 1.2.840.10008.1.2.1 | 100x100x3 | 0.0009 | 0.0000 | 0.0009 | 0.0000 | 1.00x | SC_rgb_dcmtk_ebcys2_dcmd.dcm |
| 1.2.840.10008.1.2.1 | 100x100x3 | 0.0009 | 0.0000 | 0.0008 | 0.0000 | 1.05x | SC_rgb_dcmtk_ebcys4_dcmd.dcm |
| 1.2.840.10008.1.2.2 | 100x100x3 | 0.0008 | 0.0000 | 0.0008 | 0.0000 | 0.97x | SC_rgb_expb.dcm |
| 1.2.840.10008.1.2.2 | 100x100x3 | 0.0008 | 0.0000 | 0.0009 | 0.0000 | 0.92x | SC_rgb_expb_16bit.dcm |
| 1.2.840.10008.1.2.2 | 2x100x100x3 | 0.0009 | 0.0000 | 0.0009 | 0.0000 | 1.06x | SC_rgb_expb_16bit_2frame.dcm |
| 1.2.840.10008.1.2.2 | 2x100x100x3 | 0.0009 | 0.0000 | 0.0009 | 0.0000 | 0.95x | SC_rgb_expb_2frame.dcm |
| 1.2.840.10008.1.2.2 | 100x100x3 | 0.0008 | 0.0000 | 0.0008 | 0.0000 | 1.01x | SC_rgb_expb_32bit.dcm |
| 1.2.840.10008.1.2.2 | 2x100x100x3 | 0.0010 | 0.0000 | 0.0010 | 0.0000 | 1.00x | SC_rgb_expb_32bit_2frame.dcm |
| 1.2.840.10008.1.2.1 | 100x100x3 | 0.0011 | 0.0000 | 0.0010 | 0.0000 | 1.03x | SC_rgb_gdcm2k_uncompressed.dcm |
| 1.2.840.10008.1.2.1 | 100x100x3 | 0.0014 | 0.0001 | 0.0015 | 0.0001 | 0.99x | SC_ybr_full_uncompressed.dcm |
| 1.2.840.10008.1.2.4.91 | 480x640x3 | 0.0568 | 0.0013 | 0.0151 | 0.0000 | 3.76x | US1_J2KI.dcm |
| 1.2.840.10008.1.2.4.90 | 480x640x3 | 0.0883 | 0.0006 | 0.0163 | 0.0001 | 5.43x | US1_J2KR.dcm |
| 1.2.840.10008.1.2.1 | 480x640x3 | 0.0012 | 0.0000 | 0.0013 | 0.0000 | 0.92x | US1_UNCI.dcm |
| 1.2.840.10008.1.2.1 | 480x640x3 | 0.0011 | 0.0000 | 0.0015 | 0.0008 | 0.74x | US1_UNCR.dcm |
| 1.2.840.10008.1.2.1 | 512x512 | 0.0008 | 0.0000 | 0.0008 | 0.0000 | 1.04x | vlut_04.dcm |
| 1.2.840.10008.1.2.4.201 | 480x640x3 | 0.0170 | 0.0004 | 0.0028 | 0.0000 | 6.10x | HTJ2KLossless_08_RGB.dcm |
| 1.2.840.10008.1.2.4.203 | 480x640x3 | 0.0157 | 0.0004 | 0.0029 | 0.0000 | 5.47x | HTJ2K_08_RGB.dcm |
| 1.2.840.10008.1.2.4.80 | 128x128 | 0.0030 | 0.0002 | 0.0028 | 0.0001 | 1.10x | JLSL_08_07_0_1F.dcm |
| 1.2.840.10008.1.2.4.80 | 128x128 | 0.0038 | 0.0001 | 0.0039 | 0.0001 | 0.97x | JLSL_16_15_1_1F.dcm |
| 1.2.840.10008.1.2.1 | 128x128 | 0.0008 | 0.0000 | 0.0008 | 0.0001 | 1.03x | parametric_map_float.dcm |
| 1.2.840.10008.1.2.1 | 128x128 | 0.0009 | 0.0000 | 0.0008 | 0.0000 | 1.07x | parametric_map_double_float.dcm |
| **TOTAL** | - | 4.9130 | - | 0.7140 | - | 6.88x | - |

__Errors__: ['ExplVR_BigEndNoMeta.dcm', 'JPEG2000-embedded-sequence-delimiter.dcm', 'meta_missing_tsyntax.dcm', 'rtstruct.dcm', 'priv_SQ.dcm', 'waveform_ecg.dcm', 'JPEG-lossy.dcm', 'reportsi.dcm', 'rtplan_truncated.dcm', 'MR_truncated.dcm', 'ExplVR_LitEndNoMeta.dcm', 'test-SR.dcm', 'no_meta_group_length.dcm', 'rtplan.dcm', 'no_meta.dcm', 'UN_sequence.dcm', 'nested_priv_SQ.dcm', 'badVR.dcm', 'reportsi_with_empty_number_tags.dcm', 'empty_charset_LEI.dcm', 'emri_small_jpeg_2k_lossless_too_short.dcm', 'OT-PAL-8-face.dcm', 'JLSL_RGB_ILV0.dcm', 'JLSL_RGB_ILV1.dcm', 'JLSL_RGB_ILV2.dcm', 'JLSN_RGB_ILV0.dcm']

Understanding the Results#

The performance comparison shows speedup factors for different DICOM files. Key observations:

For Small Images:

  • GPU decoding may be slower than CPU for small images

  • This is due to the overhead of transferring data between CPU and GPU memory

  • The time spent copying data back and forth can exceed the decoding time savings

For Large Images:

  • GPU decoding becomes significantly faster as image size increases

  • The parallel processing power of the GPU outweighs the transfer overhead

  • Speedups of 2-10x or more are common for larger medical images

Further Acceleration: The pydicom plugin provides easy GPU acceleration with zero code changes. However, for even better performance with multiple slices or large series, see the Advanced Batch Decoding section which demonstrates:

  • Batch decoding: Process multiple DICOM slices simultaneously

  • GPU-only workflows: Consume decoded data directly on GPU without CPU copies

  • Direct nvImageCodec API: Fine-grained control for maximum throughput

These advanced techniques can provide additional speedups, especially when processing entire DICOM series or integrating with GPU-based processing pipelines.