Próbuję utworzyć skompresowany obraz JPEG DICOM za pomocą pydicom . Fajny materiał źródłowy na temat kolorowych obrazów DICOM można znaleźć tutaj , ale to głównie teoria i C ++. W poniższym przykładzie kodu tworzę wewnątrz jasnoniebieską wielokropek output-raw.dcm
(nieskompresowany), który wygląda tak:
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
Na samym końcu próbuję stworzyć skompresowany DICOM: Próbowałem ustawić różne składnie transferu, kompresje za pomocą PIL, ale bez powodzenia. Uważam, że wygenerowany plik DICOM jest uszkodzony. Gdybym przekonwertował surowy plik DICOM na JPEG skompresowany za pomocą narzędzia gdcm-tools:
$ gdcmconv -J output-raw.dcm output-jpeg.dcm
Wykonując dcmdump
na tym przekonwertowanym pliku , mogliśmy zobaczyć interesującą strukturę, której nie wiem jak odtworzyć za pomocą 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
Próbowałem użyć modułu enkodowania pydicom , ale myślę, że jest to głównie do odczytu danych, a nie zapisu. Czy ktoś jeszcze ma pomysły na rozwiązanie tego problemu, jak je utworzyć / zakodować PixelSequence
? Chciałbym tworzyć skompresowane JPEG DICOM w zwykłym Pythonie bez uruchamiania zewnętrznych narzędzi.
Odpowiedzi:
DICOM wymaga skompresowane dane pikseli być zamknięty (patrz tabele zwłaszcza). Po skompresowaniu danych obrazu możesz użyć metody encaps.encapsulate () , aby utworzyć
bytes
odpowiednią do użycia z danymi Pixel :źródło
encapsulate([frame1, frame2, ...])
Wypróbowanie rozwiązania z @scaramallion, z bardziej szczegółowymi efektami:
źródło