পেডিকোম ব্যবহার করে কীভাবে জেপিজি সংক্ষেপিত DICOM ডেটাসেট তৈরি করবেন?


14

আমি পাইডিকম ব্যবহার করে একটি জেপিইজি সংক্ষেপিত ডিকম চিত্র তৈরি করার চেষ্টা করছি । রঙিন DICOM চিত্র সম্পর্কে একটি দুর্দান্ত উত্স উপাদান এখানে পাওয়া যাবে , তবে এটি বেশিরভাগ তত্ত্ব এবং সি ++। নীচের কোড উদাহরণে আমি ভিতরে ফ্যাকাশে নীল উপবৃত্ত তৈরি করি 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 ফাইলটি দূষিত। আমি যদি কাঁচা ডিকম ফাইলটি জিডিইগিএম-সরঞ্জামগুলির সাথে সংকুচিত জেপিজিতে রূপান্তর করতে পারি:

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

dcmdumpএই রূপান্তরিত ফাইলটিতে একটি করে আমরা একটি আকর্ষণীয় কাঠামো দেখতে পেলাম, যা আমি পাইডিকোম ব্যবহার করে পুনরুত্পাদন করতে জানি না:

$ 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

আমি পাইডিকমের এনক্যাপস মডিউলটি ব্যবহার করার চেষ্টা করেছি , তবে আমি মনে করি এটি বেশিরভাগ ডেটা পড়ার জন্য, লেখার জন্য নয়। এই সমস্যাটি কীভাবে মোকাবেলা করবেন, এইগুলি কীভাবে তৈরি / এনকোড করবেন তার অন্য কারও ধারনা রয়েছে PixelSequence? বাহ্যিক সরঞ্জামগুলি চালনা না করে প্লে পাইথনে জেপিজি সংক্ষেপিত ডিকমগুলি তৈরি করতে পছন্দ করবে।


আপনি কি পাইডিকোমের মাধ্যমে জেপিজি সংক্ষেপিত চিত্রটি পড়তে সক্ষম?
norok2

হ্যাঁ অবশ্যই আমি এটি সংক্ষেপিত করতে এবং পড়তে পারি। অবশ্যই আপনার কয়েকটি অতিরিক্ত লাইব্রেরি ইনস্টল করা দরকার, এখানে সম্ভাব্য সংমিশ্রণগুলি রয়েছে: pydicom.github.io/pydicom/stable/image_data_handlers.html
mseimys

এই ব্যবহারের ক্ষেত্রে কি প্রতিটি সমস্যার সমাধান হয়েছে? আমি নিজে এটিতে কিছু ডকুমেন্টেশন দেখতে চাই।
স্টিভেন হার্ট

উত্তর:


4

DICOM সংকুচিত প্রয়োজন পিক্সেল ডেটা করা encapsulated (টেবিল বিশেষত দেখুন)। একবার আপনার সংকুচিত চিত্রের ডেটা পেলে আপনি পিক্সেল ডেটা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

@ স্যাকারম্যালিয়ন থেকে সমাধানটি চেষ্টা করে আরও বিশদে কাজ করা দেখায়:

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)
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.