Как добавить метаданные к изображению (с кодом java), а затем преобразовать его в dicom

Я нашел код Java, который преобразует файлы jpg и Dicom (он берет метаданные из этого файла) в окончательный файл Dicom. Что я хочу сделать, так это преобразовать изображение jpg в изображение Dicom, создав метаданные с помощью java-кода.

BufferedImage jpg = ImageIO.read(new File("myjpg.jpg"));

// Convert the image to a byte array    
DataBuffer buff = jpg.getData().getDataBuffer();
DataBufferUShort buffer = new DataBufferUShort(buff.getSize());

for (int i = 0; i < buffer.getSize(); ++i)
    buffer.setElem(i, buff.getElem(i));

short[] data = buffer.getData();
ByteBuffer byteBuf = ByteBuffer.allocate(2 * data.length);
int i = 0;
while (data.length > i) {
    byteBuf.putShort(data[i]);
    i++;
}
// Copy a header
DicomInputStream dis = new DicomInputStream(new File("fileToCopyheaderFrom.dcm"));
Attributes meta = dis.readFileMetaInformation();
Attributes attribs = dis.readDataset(-1, Tag.PixelData);
dis.close();
// Change the rows and columns
attribs.setInt(Tag.Rows, VR.US, jpg.getHeight());
attribs.setInt(Tag.Columns, VR.US, jpg.getWidth());
System.out.println(byteBuf.array().length);
// Write the file
attribs.setBytes(Tag.PixelData, VR.OW, byteBuf.array());
DicomOutputStream dcmo = new DicomOutputStream(new File("myDicom.dcm"));
dcmo.writeFileMetaInformation(meta);
attribs.writeTo(dcmo);
dcmo.close();
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
0
1 115
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Я не эксперт в наборе инструментов (и, конечно, в Java).

Ваш раздел «// Копировать заголовок» читает исходный файл DICOM и содержит все атрибуты в переменной Attributes attribs.

Затем ваш раздел «// Изменить строки и столбцы» изменяет несколько атрибутов по мере необходимости.

Затем ваш раздел «// Запись файла» просто добавляет атрибуты, считанные из исходного файла, в целевой файл.

Теперь вы хотите обойти исходный файл DICOM и самостоятельно преобразовать обычный JPEG в DICOM с добавлением атрибутов.

Замените раздел «// Скопируйте заголовок» на строить экземпляром Attributes.

Attributes attribs = new Attributes();
attribs.setString(Tag.StudyDate, VR.DA, "20110404");
attribs.setString(Tag.StudyTime, VR.TM, "15");

Теги, упомянутые в приведенном выше примере, приведены только для примера. Вы должны решить сами, какие теги вы хотите включить. Обратите внимание, что в спецификациях определены типы 1, 1C, 2, 2C и 3 для тегов в зависимости от класса SOP, с которым вы имеете дело.
При добавлении тегов вы также должны позаботиться о правильном VR. Спецификации также говорят об этом.
Я не могу объяснить все это здесь; слишком широкий.

Я не могу помочь с dcm4che, но если вы можете использовать другую библиотеку Java DICOM, эта задача довольно проста с использованием DeCaMino (http://dicomplugin.com):

  BufferedImage jpg = ImageIO.read(new File("myjpg.jpg"));
  DicomWriter dw = new DicomWriter();
  dw.setOutput(new File("myjpg.dcm"));
  DicomMetadata dmd = new DicomMetadata();
  dw.write(dmd, new IIOImage(jpg, null, null), null);

Это запишет файл соответствия DICOM с классом SOP «вторичный захват» и метаданными по умолчанию.

Чтобы настроить метаданные, добавьте элементы данных в dmd перед записью, например. :

  DataSet ds = dmd.getDataSet();
  ds.set(Tag.StudyDate, LocalDate.of(2011, 4, 4));
  ds.set(Tag.StudyTime, LocalTime.of(15, 0, 0));

Вы также можете изменить синтаксис передачи (таким образом контролируя кодировку данных пикселей):

  dw.setTransferSyntax(UID.JPEG2000TS);

Отказ от ответственности: я автор DeCaMino.

Обновлено: Как говорит kritzel_sw, я настоятельно рекомендую не изменять и существующий объект DICOM, изменяя данные пикселей и некоторые элементы данных, вы в основном закончите с несоответствующим объектом. Лучше написать объект с нуля, а самые простые объекты — из вторичного класса захвата. DeCaMino помогает вам, создавая соответствующий вторичный объект захвата с обязательными элементами данных, но он не поможет вам создать объект модальности (например, сбор данных КТ).

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

kritzel_sw 19.07.2019 13:10

Вопрос, насколько я понял, был "как преобразовать изображение jpg в изображение Dicom, сгенерировав метаданные с помощью java-кода". Я считаю, что мой пост действительно приносит ответ. Что касается целостности данных, вы правы, но класс DeCaMino по умолчанию SOP — это вторичный захват, что означает, что некоторые неоригинальные данные и любое программное обеспечение DICOM распознают их как таковые. Разработчик должен добавить необходимые метаданные, чтобы сделать файл полезным для того, для чего он предназначен, например, имя пациента и т. д.

Hervé Guillemet 19.07.2019 16:09

Вы правы, я согласен. Я вернул свой отрицательный голос. Спасибо за добавление "EDIT".

kritzel_sw 22.07.2019 07:55

Просто примечание:

attribs.setBytes(Tag.PixelData, VR.OW, byteBuf.array());

VR.OW означает 16 бит на пиксель/канал. Поскольку вы заменяете данные пикселей данными пикселей, считанными из изображения JPEG, и вы назвали буфер «byteBuf», я подозреваю, что это непоследовательно. VR.OB — это представление значения для 8 бит на пиксель/канал изображения.

Говоря о каналах, я понимаю, что вы хотите упростить создание объекта DICOM, изменив существующее изображение DICOM, а не создавая новое с нуля. Однако данные цветных пикселей подходят не для всех типов изображений DICOM. Например. если ваш файлToCopyheaderFrom.dcm является изображением радиографии, КТ или МРТ (или многих других типов радиологии), в него нельзя добавлять данные цветовых пикселей.

Кроме того, каждое изображение содержит идентифицирующую информацию (наиболее важными из них являются UID исследования, серии, экземпляра SOP), которые должны быть заменены вновь сгенерированными значениями.

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

Другие вопросы по теме