Pydicom का उपयोग करके JPEG संपीड़ित DICOM डेटासेट कैसे बनाएं?


14

मैं pydicom का उपयोग कर एक JPEG संकुचित DICOM छवि बनाने की कोशिश कर रहा हूं । रंगीन DICOM छवियों के बारे में एक अच्छा स्रोत सामग्री यहाँ मिल सकती है , लेकिन यह ज्यादातर सिद्धांत और C ++ है। नीचे दिए गए कोड उदाहरण में मैं अंदर एक पीला नीला दीर्घवृत्त output-raw.dcm(असम्पीडित) बनाता हूं जो इस तरह ठीक दिखता है:

नमूना DICOM छवि

import io
from PIL import Image, ImageDraw
from pydicom.dataset import Dataset
from pydicom.uid import generate_uid, JPEGExtended
from pydicom._storage_sopclass_uids import SecondaryCaptureImageStorage

WIDTH = 100
HEIGHT = 100


def ensure_even(stream):
    # Very important for some viewers
    if len(stream) % 2:
        return stream + b"\x00"
    return stream


def bob_ross_magic():
    image = Image.new("RGB", (WIDTH, HEIGHT), color="red")
    draw = ImageDraw.Draw(image)
    draw.rectangle([10, 10, 90, 90], fill="black")
    draw.ellipse([30, 20, 70, 80], fill="cyan")
    draw.text((11, 11), "Hello", fill=(255, 255, 0))
    return image


ds = Dataset()
ds.is_little_endian = True
ds.is_implicit_VR = True
ds.SOPClassUID = SecondaryCaptureImageStorage
ds.SOPInstanceUID = generate_uid()
ds.fix_meta_info()
ds.Modality = "OT"
ds.SamplesPerPixel = 3
ds.BitsAllocated = 8
ds.BitsStored = 8
ds.HighBit = 7
ds.PixelRepresentation = 0
ds.PhotometricInterpretation = "RGB"
ds.Rows = HEIGHT
ds.Columns = WIDTH

image = bob_ross_magic()
ds.PixelData = ensure_even(image.tobytes())

image.save("output.png")
ds.save_as("output-raw.dcm", write_like_original=False)  # File is OK

#
# Create compressed image
#
output = io.BytesIO()
image.save(output, format="JPEG")

ds.PixelData = ensure_even(output.getvalue())
ds.PhotometricInterpretation = "YBR_FULL_422"
ds.file_meta.TransferSyntaxUID = JPEGExtended

ds.save_as("output-jpeg.dcm", write_like_original=False)  # File is corrupt

बहुत अंत में मैं संकुचित DICOM बनाने की कोशिश कर रहा हूं: मैंने विभिन्न ट्रांसफ़र सिंटैक्स, पीआईएल के साथ कंप्रेशन सेट करने की कोशिश की, लेकिन भाग्य नहीं। मेरा मानना ​​है कि उत्पन्न DICOM फ़ाइल भ्रष्ट है। अगर मैं gdcm-tools के साथ कच्चे DICOM फ़ाइल को JPEG में परिवर्तित कर देता तो:

$ gdcmconv -J output-raw.dcm output-jpeg.dcm

एक ऐसा करने से dcmdumpइस पर बदली गई फ़ाइल हम एक दिलचस्प संरचना है, जो मैं pydicom का उपयोग कर पुन: पेश करने के लिए कैसे पता नहीं है देख सकते हैं:

$ dcmdump output-jpeg.dcm

# Dicom-File-Format

# Dicom-Meta-Information-Header
# Used TransferSyntax: Little Endian Explicit
(0002,0000) UL 240                                      #   4, 1 FileMetaInformationGroupLength
(0002,0001) OB 00\01                                    #   2, 1 FileMetaInformationVersion
(0002,0002) UI =SecondaryCaptureImageStorage            #  26, 1 MediaStorageSOPClassUID
(0002,0003) UI [1.2.826.0.1.3680043.8.498.57577581978474188964358168197934098358] #  64, 1 MediaStorageSOPInstanceUID
(0002,0010) UI =JPEGLossless:Non-hierarchical-1stOrderPrediction #  22, 1 TransferSyntaxUID
(0002,0012) UI [1.2.826.0.1.3680043.2.1143.107.104.103.115.2.8.4] #  48, 1 ImplementationClassUID
(0002,0013) SH [GDCM 2.8.4]                             #  10, 1 ImplementationVersionName
(0002,0016) AE [gdcmconv]                               #   8, 1 SourceApplicationEntityTitle

# Dicom-Data-Set
# Used TransferSyntax: JPEG Lossless, Non-hierarchical, 1st Order Prediction
...
... ### How to do the magic below?
...
(7fe0,0010) OB (PixelSequence #=2)                      # u/l, 1 PixelData
  (fffe,e000) pi (no value available)                     #   0, 1 Item
  (fffe,e000) pi ff\d8\ff\ee\00\0e\41\64\6f\62\65\00\64\00\00\00\00\00\ff\c3\00\11... # 4492, 1 Item
(fffe,e0dd) na (SequenceDelimitationItem)               #   0, 0 SequenceDelimitationItem

मैंने pydicom के इनकैप्स मॉड्यूल का उपयोग करने की कोशिश की , लेकिन मुझे लगता है कि यह ज्यादातर डेटा पढ़ने के लिए है, लिखने के लिए नहीं। किसी और के पास इस मुद्दे से निपटने के लिए कोई विचार है, इन PixelSequenceएस को कैसे बनाएं / एनकोड करें ? बाहरी उपकरणों को चलाने के बिना सादे अजगर में JPEG संकुचित DICOMs बनाना पसंद करेंगे।


आप PyDicom के माध्यम से JPEG संकुचित छवि को पढ़ने में सक्षम हैं?
नोरोक 2

हां, मैं इसे डिकम्प्रेस कर सकता हूं और पढ़ सकता हूं। बेशक, आपको कुछ अतिरिक्त पुस्तकालयों की आवश्यकता है, यहां संभव संयोजन हैं: pydicom.github.io/pydicom/stable/image_data_handlers.html
mseimys

क्या यह उपयोग मामला हर हल हो गया? मैं स्वयं इस पर कुछ दस्तावेज़ देखना पसंद करूंगा।
स्टीवन हार्ट

जवाबों:


4

DICOM संकुचित आवश्यकता पिक्सेल डाटा जा समझाया (टेबल विशेष रूप से देखें)। एक बार जब आपके पास अपनी संपीड़ित छवि डेटा हो तो आप पिक्सेल डेटा के साथ उपयोग के लिए उपयुक्त बनाने के लिए encaps.encapsulate () विधि का उपयोग कर सकते हैं :bytes

from pydicom.encaps import encapsulate

# encapsulate() requires a list of bytes, one item per frame
ds.PixelData = encapsulate([ensure_even(output.getvalue())])
# Need to set this flag to indicate the Pixel Data is compressed
ds['PixelData'].is_undefined_length = True
ds.PhotometricInterpretation = "YBR_FULL_422"
ds.file_meta.TransferSyntaxUID = JPEGExtended

ds.save_as("output-jpeg.dcm", write_like_original=False)

यह काम करता है, लेकिन केवल एकल फ्रेम jpeg के लिए। किसी को भी एक मल्टीप्लेयर जेपीईजी सांकेतिक शब्दों में बदलना पता है?
स्टीवन हार्ट

प्रत्येक फ्रेम को अलग से एन्कोड किया जाना आवश्यक है और फिर सभी फ्रेमों के साथ समझाया गया हैencapsulate([frame1, frame2, ...])
स्कारमैलियन

1

@Scaramallion से समाधान की कोशिश, अधिक विस्तार के साथ काम करने के लिए लग रहा है:

import numpy as np
from PIL import Image
import io

# set some parameters
num_frames = 4
img_size = 10

# Create a fake RGB dataset
random_image_array = (np.random.random((num_frames, img_size, img_size, 3))*255).astype('uint8')
# Convert to PIL
imlist = []
for i in range(num_frames):   # convert the multiframe image into RGB of single frames (Required for compression)
    imlist.append(Image.fromarray(tmp))

# Save the multipage tiff with jpeg compression
f = io.BytesIO()
        imlist[0].save(f, format='tiff', append_images=imlist[1:], save_all=True, compression='jpeg')
# The BytesIO object cursor is at the end of the object, so I need to tell it to go back to the front
f.seek(0)
img = Image.open(f)

# Get each one of the frames converted to even numbered bytes
img_byte_list = []
for i in range(num_frames):
    try:
        img.seek(i)
        with io.BytesIO() as output:
            img.save(output, format='jpeg')
            img_byte_list.append(output.getvalue())
    except EOFError:
         # Not enough frames in img
         break

ds.PixelData = encapsulate([x for x in img_byte_list])
ds['PixelData'].is_undefined_length = True
ds.is_implicit_VR = False
ds.LossyImageCompression = '01'
ds.LossyImageCompressionRatio = 10 # default jpeg
ds.LossyImageCompressionMethod = 'ISO_10918_1'
ds.file_meta.TransferSyntaxUID = '1.2.840.10008.1.2.4.51'

ds.save_as("output-jpeg.dcm", write_like_original=False)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.