Основы DICOM с использованием .NET и C#: понимание файла DICOM

Файл DICOM содержит изображения (или другие данные) и данные о пациенте  с использованием концепции тегов, которая будет объяснена позже. Информация, хранящаяся в файле DICOM, гораздо более структурирована и разнообразна, чем в других стандартах хранения изображений, с помощью словаря тегов DICOM. Этот словарь, содержащий несколько тысяч таких тегов, помогает кодировать такую ​​информацию, как, например, когда и где было сделано изображение, кому оно принадлежит, ФИО направившего врача и т.д., и сохранять её вместе с пиксельными данными изображения. Это сводит к минимуму риск приписать важную медицинскую информацию не тому пациенту.

Большинство файлов DICOM обычно содержат данные одного изображения, а иногда могут содержать несколько изображений (или « кадров», как их часто называют в DICOM), чтобы обеспечить то, что называется "кинопетлей" , которая позволяет просмотрщику DICOM визуализировать всю последовательность изображений в виде фильма. Однако файлы DICOM не обязательно должны содержать изображения, как предполагает большинство людей, а могут также использоваться для хранения другой информации, такой как текстовые отчеты, сигналы ЭКГ и даже аудио или видео.

Заглянем внутрь файла DICOM

Каждый файл DICOM состоит из трех основных частей.

Первая часть - заголовок файла - состоит из 128-байтовой преамбулы файла, за которой следует 4-байтовый префикс. Этот подход очень распространен во многих других стандартах изображений, таких как TIFF, который вы, возможно, уже видели/использовали. Префикс длиной 4 байта состоит из символов верхнего регистра «DICM» (обратите внимание, это не «DICOM», а «DICM»). Стандарт не заботится о том, как должна быть структурирована преамбула и что в ней хранить. Насколько я понимаю, использование преамбулы файла предназначено просто для обеспечения совместимости или согласованности приложения обработки при работе с файлами DICOM, как и с некоторыми другими существующими форматами файлов изображений. Стандарт не заботится о том, что вы в нем храните или как вы его используете. Таким образом, теоретически ваше приложение может полностью пропустить эти данные при анализе файла DICOM, если вы захотите.

Прежде чем мы рассмотрим следующую часть файла DICOM, необходимо сказать кое-что о концепции синтаксиса передачи и его роли в стандарте DICOM. Стандарт DICOM позволяет устройствам передавать информацию друг другу, даже если они работают на разных операционных системах. Различные операционные системы и устройства используют разные форматы хранения данных, например, порядок байтов при хранении двоичных данных. Из-за высоких требований к сети для обмена большими изображениями, полученными с помощью таких методов сканирования, как КТ или МРТ, в стандарте также предусмотрены положения для обмена данными изображений с использованием сжатия, когда это необходимо. Все три критерия (тип кодирования VR, тип порядка байтов и используемое сжатие) должны быть сначала поняты и согласованы, чтобы гарантировать, что две системы DICOM, обменивающиеся информацией, понимают друг друга во время любого взаимодействия между ними. Синтаксис передачи — это набор правил кодирования, который указывается посредством использования специальных уникальных идентификаторов - UID . Например, Implicit VR с прямым порядком байтов обозначается значением UID 1.2.840.10008.1.2), Explicit VR с прямым порядком байтов — 1.2.840.10008.1.2.1,  JPEG Lossless — 1.2.840.10008.1.2.4.57 — это некоторые из синтаксисов передачи, доступных для обработки DICOM.

Теперь, когда мы вкратце понимаем, что такое синтаксис передачи, давайте посмотрим на следующую часть файла, а именно на заголовок метаинформации файла . Этот раздел следует сразу после заголовка файла и состоит из набора данных, состоящего из последовательности тегированной информации (называемой «Элементы Dicom» ), которая определяет такие детали, как синтаксис передачи (поясняется выше), а также другую информацию, касающуюся устройства или реализации, кто создал этот файл и для кого была создана эта информация (приложение-получатель) (см. подробную информацию на стр. 32 данного документа )

За этим разделом следует третья и последняя часть файла DICOM, представляющая собой объект данных. Эта часть файла DICOM также определяется в виде набора данных, состоящего из ряда тегов, которые, в свою очередь, могут быть вложенными и сами нести дополнительные дочерние теги. Эти теги несут информацию об исследование, серии, пациенте, которому они принадлежат, а также другие сведения об изображении и т. д. Исследование, серии и информация о пациенте часто используются для индексации изображения в большинстве систем PACS для более быстрого поиска данных. Иллюстрация ниже дает краткий обзор общей структуры файла, а также показывает, что отдельные элементы DICOM (каждый элемент включает в себя тег и связанную с ним информацию) являются частью всей структуры.

Например, в первом из трех элементов DICOM в разделе объекта данных, показанном на этой иллюстрации, «(0008, 0070)» указывает на тег, принадлежащий группе с номером 0008 с номером атрибута 0070, «LO» указывает тип данных или представление значения (VR) , как его называет DICOM (LO относится к типу данных Long String, см. Типы данных в DICOM), «PHILIPS» — это фактическое значение тега, «#8» указывает длину значения - 8 (Обратите внимание, что DICOM всегда кодирует данные, используя четное количество символов для текста, поэтому используется дополнительный символ заполнения, даже если длина значения PHILIPS составляет всего 7 символов), 1 представляет здесь кратность значения (некоторые данные могут быть повторяется), а «Manufacturer» — это фактическое имя тега, указанное в словаре DICOM. Номер группы и атрибута, VR, значение, кратность значения и имя тега вместе называются элементом DICOM . Поскольку словарь DICOM (см. стр. 23 и далее) неявно определяет VR, связанный с каждым тегом, то VR является избыточным и иногда опускается. Несмотря на это, общепринятой практикой и рекомендацией является явное указание VR при сериализации объектов DICOM в файлы или при обмене информацией DICOM по сети. Теперь мы можем лучше понять, что такое IOD (Определение информационного объекта)

Что на самом деле означают эти термины в DICOM — SCU, SCP, SOP и IOD?

DICOM определяет концепции сервисов и данных, которые эти сервисы используют или на основе которых действуют. Примером службы может быть служба CT Store, которая отвечает за сохранение изображения, сгенерированного с помощью модальности CT, на сервере PACS. Служба состоит из двух частей: потребителя службы, также известного как пользователь класса обслуживания или SCU , и поставщика службы, также известного как поставщик класса обслуживания или SCP . Например, в операции хранилища CT модальность, которая генерирует изображение, действует как SCU C-Store и передает данные для хранения в C-Store SCP, которым является сервер PACS. В стандарте DICOM комбинация классов обслуживания и объектов, связанных с этими услугами, известна как пара объектов обслуживания или SOP. Абстрактное определение SOP называется классом SOP, и они определяются уникальными идентификаторами (называемыми UID ). Таким образом, хранилище изображений CT SOP, которое идентифицируется UID класса SOP 1.2.840.10008.5.1.4.1.1.2, помогает определить, что это операция хранения изображений CT. В ходе этой операции между участвующими машинами происходит обмен командами (называемый DIMSE), а также некоторыми данными, которые включают в себя информацию о пикселях изображения и другую идентификационную информацию о пациенте, исследовании, серии и оборудовании. Вместе эти конкретные детали этой операции известны как экземпляр SOP . Каждый из этих экземпляров SOP также идентифицируется уникальным идентификатором, и генерируется приложением, ответственным за их передачу. Эти идентификаторы называются UID экземпляра SOP . Фактические данные, используемые в этой паре SOP, называются IOD (Определением информационного объекта), определяющим, какие модули DICOM (модули, по сути, представляют собой группы элементов DICOM) должны присутствовать для успешного завершения обработки.

Объекты IOD сами разбиты на подгруппы, называемые информационными объектами (сокращенно IE), а информационные объекты, в свою очередь, разбиваются на небольшие группы информационных модулей . Информационные модули состоят из ряда элементов DICOM , которые мы уже видели. DICOM определяет правила относительно того, какие модули являются обязательными, какие присутствуют условно, а какие необязательными. Сами IOD подразделяются на нормализованные IOD и составные IOD . Нормализованные IOD представляют данные, относящиеся только к одному объекту, тогда как составные IOD представляют данные из смеси различных объектов, связанных друг с другом, как показано на иллюстрации ниже. По сути, это общая структура информационной модели DICOM. Объединив все это, вы теперь увидите, что любой файл DICOM, с которым мы до сих пор имели дело, на самом деле является экземпляром IOD (сериализованной версии информации), который также передается между двумя машинами во время любого рабочего процесса обработки изображений. А в рассматриваемом нами случае — операция, помогающая сохранить изображение, созданное с помощью метода КТ, на сервере PACS. IOD и кодирование DICOM — это нечто большее, чем то, что описано здесь, но мы будем иметь дело с этими областями при обсуждении создания файлов и каталогов DICOM.

Fellow Oak (fo-dicom) Набор инструментов DICOM — краткий обзор

В целях иллюстрации многих аспектов DICOM, которые я планирую осветить, я буду использовать свободно доступный и мощный набор инструментов DICOM под названием fo-dicom DICOM Toolkit . Это полностью автономный набор инструментов DICOM, который реализует такие функции, как обработка файлов и каталогов DICOM, а также операции, связанные с сетью DICOM. Этот набор инструментов совершенно бесплатен как для коммерческого, так и для некоммерческого использования. Использование этого набора инструментов в моем руководстве ни в коем случае не означает моего официального одобрения его для реализации производственного приложения. Каждая ситуация уникальна, и только вы в конечном итоге можете ее решить. Эта статья также не является учебным пособием по набору инструментов Fellow Oak DICOM, и моя цель здесь — просто связать теорию DICOM с тем, как может выглядеть практическая (хотя и простая) реализация. Если ваша цель — научиться использовать библиотеку DICOM Fellow Oak, я бы посоветовал вам посетить ее веб-сайт   для получения более подробной информации. Библиотека используется для разработки на языке программирования C#, поэтому для опробования кода удобно будет использовать Visual Studio от Microsoft. Подключение библиотеки к проекту не представляет труда, т.к. существует ее nuget-пакет, который можно найти и установить прямо из интерфейса студии.

Вывод определенных тегов файла DICOM на консоль

На иллюстрации кода показан простой способ составить список некоторых основных часто используемых тегов DICOM. В этом наборе инструментов имеется ряд перегрузок и удобных методов извлечения тегов DICOM.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using FellowOakDicom;

    namespace MakingSenseOfDicomFile
    {
      public class Program
      {
        private static readonly string PathToDicomTestFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Test Files", "0002.dcm");

        public static void Main(string[] args)
        {
          try
          {
            LogToDebugConsole($"Attempting to extract information from DICOM file:{PathToDicomTestFile}...");

            var file = DicomFile.Open(PathToDicomTestFile,readOption:FileReadOption.ReadAll);
            var dicomDataset = file.Dataset;
            var studyInstanceUid = dicomDataset.GetSingleValue(DicomTag.StudyInstanceUID);
            var seriesInstanceUid = dicomDataset.GetSingleValue(DicomTag.SeriesInstanceUID);
            var sopClassUid = dicomDataset.GetSingleValue(DicomTag.SOPClassUID);
            var sopInstanceUid = dicomDataset.GetSingleValue(DicomTag.SOPInstanceUID);
            var transferSyntaxUid = file.FileMetaInfo.TransferSyntax;

            LogToDebugConsole($" StudyInstanceUid - {studyInstanceUid}");
            LogToDebugConsole($" SeriesInstanceUid - {seriesInstanceUid}");
            LogToDebugConsole($" SopClassUid - {sopClassUid}");
            LogToDebugConsole($" SopInstanceUid - {sopInstanceUid}");
            LogToDebugConsole($" TransferSyntaxUid - {transferSyntaxUid}");

            LogToDebugConsole($"Extract operation from DICOM file successful. Press Enter for continue...");
            Console.ReadLine();
          }
          catch (Exception e)
          {
            LogToDebugConsole($"Error occured during DICOM file dump operation -> {e.StackTrace}");
          }
      }

      private static void LogToDebugConsole(string informationToLog)
      {
          Debug.WriteLine(informationToLog);
      }
  }
}

Результат выполнения приведенного выше кода показан ниже:

Вывод всех тегов файла DICOM на консоль

Иногда нужно получить все теги, содержащиеся в файле DICOM, включая номер группы и атрибута, представление значения (VR), значение, длину значения, кратность значения и информацию об имени тега. Этот легко достигается путем перебора набора данных DICOM, что иллюстрирует приведенный ниже код.

try
 {
   LogToDebugConsole($"Attempting to extract information from DICOM file:{PathToDicomTestFile}...");
   var file = DicomFile.Open(PathToDicomTestFile);

   foreach (var tag in file.Dataset)
   {
      LogToDebugConsole($" {tag} '{file.Dataset.GetValueOrDefault(tag.Tag, 0, "")}'");
   }
   LogToDebugConsole($"Extract operation from DICOM file successful. Press Enter for close console");
   Console.ReadLine();
 }
 catch (Exception e)
 {
   LogToDebugConsole($"Error occured during DICOM file dump operation -> {e.StackTrace}");
 }

Результат выполнения:

Данный материал является моим (Александр Кузнецов) творческим переводом статьи "DICOM Basics using .NET and C# - Making Sense of the DICOM File", автором которой является Saravanan Subramanian. Приведенные примеры кода основаны на первоисточнике, но переработаны мной в связи с устареванием приведенных определений используемой библиотеки.

 

 

Scroll to top