2013-01-16 3 views
3

표준 크기 (512 x 512 또는 256 x 256) numpy 배열에서 mew dicom 이미지를 만들려고합니다. 이것은 간단해야하며, 동일한 프로세스를 실행하는 것처럼 보이는 http://code.google.com/p/pydicom/source/browse/source/dicom/examples/write_new.py의 코드를 수정했지만 파일을 저장할 때 RadiAnt 또는 MicroDicom에서 볼 수는 없습니다.numpy 배열에서 pydicom 파일 만들기

import dicom, dicom.UID 
from dicom.dataset import Dataset, FileDataset 

def write_dicom(pixel_array,filename): 

    file_meta = Dataset() 
    ds = FileDataset(filename, {},file_meta = file_meta,preamble="\0"*128) 
    ds.PixelData = pixel_array.tostring() 
    ds.save_as(filename) 
    return 

if __name__ == "__main__": 
    import numpy as np 
    pixel_array = np.tile(np.arange(256).reshape(16,16), (16,16)) * 4 
    write_dicom(pixel_array,'pretty.dcm') 
+3

'write_dicom' 함수에 여기에 표시 한 것보다 많은 연산이 포함되어 있습니까? 그렇지 않으면 픽셀 데이터 만있는 파일을 만드는 것처럼 보이며 유효한 DICOM 파일이 아닙니다. 파일이 DICOM을 준수하도록하려면 연구, 시리즈, 인스턴스 UID : s, 이미지 양식, 환자 데이터 등을 입력해야합니다. –

+0

파일에 DICOM 헤더 정보의 덤프를 제공 할 수 있습니까? 물론 환자 이름 등이 적혀 있습니다. 다음은 DICOM 파일에 대한이 정보를 볼 수있는 워싱턴 대학교의 매우 유용한 (무료) 도구에 대한 링크입니다. http://nrg.wustl.edu/software/dicom-browser/ – Matt

+0

GDCM의 FAQ에는 왜 무작위 래스터 이미지 형식의 합법적 인 DICOM은 어렵습니다. http://sourceforge.net/apps/mediawiki/gdcm/index.php?title=General_questions#How_do_I_convert_my_raster_image_format_X_into_DICOM_.3F – timday

답변

1

위의 예는 작동하지만 DICOMs에 대해 불평하는 많은 도구를 야기하고 심지어 스택으로/SimpleITK ITK를 사용하여 전혀 읽을 수 없습니다 . DICOM을 numpy에서 만드는 가장 좋은 방법은 SimpleITK 도구를 사용하고 DICOM 슬라이스를 생성하는 것입니다. 기본적인 예 (https://github.com/zivy/SimpleITK/blob/8e94451e4c0e90bcc6a1ffdd7bc3d56c81f58d80/Examples/DicomSeriesReadModifyWrite/DicomSeriesReadModifySeriesWrite.py)은 매우 큰, 스택으로로드 변환을 수행하고 파일을 다시 저장 있지만 쉽게 궁극적으로 출력 이미지 태그

import SimpleITK as sitk 
filtered_image = sitk.GetImageFromArray(my_numpy_array) 

개수를 이용하여 수정 될 수있는 방법을 도시 수동으로 생성하는 것은 지루합니다. 또한 SimpleITK는 8, 16, 32 비트 이미지와 RGB를 지원하므로 pydicom에서 만드는 것보다 훨씬 쉽습니다.

(0008, 0008) Image Type       CS: ['DERIVED', 'SECONDARY'] 
(0008, 0016) SOP Class UID      UI: Secondary Capture Image Storage 
(0008, 0018) SOP Instance UID     UI: 1.2.826.0.1.3680043.2.1125.1.35596048796922805578234000521866725 
(0008, 0020) Study Date       DA: '20170803' 
(0008, 0021) Series Date       DA: '20170803' 
(0008, 0023) Content Date      DA: 0 
(0008, 0030) Study Time       TM: '080429.171808' 
(0008, 0031) Series Time       TM: '080429' 
(0008, 0033) Content Time      TM: 0 
(0008, 0050) Accession Number     SH: '' 
(0008, 0060) Modality       CS: 'OT' 
(0008, 0064) Conversion Type      CS: 'WSD' 
(0008, 0090) Referring Physician's Name   PN: '' 
(0010, 0010) Patient's Name      PN: '' 
(0010, 0020) Patient ID       LO: '' 
(0010, 0030) Patient's Birth Date    DA: '' 
(0010, 0040) Patient's Sex      CS: '' 
(0018, 2010) Nominal Scanned Pixel Spacing  DS: ['1', '3'] 
(0020, 000d) Study Instance UID     UI: 1.2.826.0.1.3680043.2.1125.1.33389357207068897066210100430826006 
(0020, 000e) Series Instance UID     UI: 1.2.826.0.1.3680043.2.1125.1.51488923827429438625199681257282809 
(0020, 0010) Study ID       SH: '' 
(0020, 0011) Series Number      IS: '' 
(0020, 0013) Instance Number      IS: '' 
(0020, 0020) Patient Orientation     CS: '' 
(0020, 0052) Frame of Reference UID    UI: 1.2.826.0.1.3680043.2.1125.1.35696880630664441938326682384062489 
(0028, 0002) Samples per Pixel     US: 1 
(0028, 0004) Photometric Interpretation   CS: 'MONOCHROME2' 
(0028, 0010) Rows        US: 40 
(0028, 0011) Columns        US: 50 
(0028, 0100) Bits Allocated      US: 32 
(0028, 0101) Bits Stored       US: 32 
(0028, 0102) High Bit       US: 31 
(0028, 0103) Pixel Representation    US: 1 
(0028, 1052) Rescale Intercept     DS: "0" 
(0028, 1053) Rescale Slope      DS: "1" 
(0028, 1054) Rescale Type      LO: 'US' 
(7fe0, 0010) Pixel Data       OW: Array of 8000 bytes 
0

DICOM은 실제로 복잡한 형식입니다. 많은 방언이 있으며, 호환성은 오히려 운의 문제입니다. 대안으로 nibabel을 시도해보십시오. 아마도 방언이 RadiAnt 또는 MicroDicom에 더 매력적일 수 있습니다.

일반적으로 가능한 경우 Nifti 형식을 사용하는 것이 좋습니다. 표준은 훨씬 간결하며 비 호환성은 거의 없습니다. nibabel도 이것을 지원합니다.

+0

dicom이되어야하지만 감사합니다! –

+0

Dicom 용 nibabel을 사용해 보셨습니까? –

3

다음은 작성해야하는 코드의 기능 버전입니다. 주어진 2D 픽셀 배열로부터 16 비트 그레이 스케일 DICOM 이미지를 씁니다. DICOM 표준에 따르면 UID는 실제로 UID가 무엇인지 모르기 때문에이 코드가 걱정하지 않는 각 이미지 및 시리즈마다 고유해야합니다. 다른 사람이하는 경우에, 나는 그것을 추가 할 수있을 것입니다.

import dicom, dicom.UID 
from dicom.dataset import Dataset, FileDataset 
import numpy as np 
import datetime, time 

def write_dicom(pixel_array,filename): 
    """ 
    INPUTS: 
    pixel_array: 2D numpy ndarray. If pixel_array is larger than 2D, errors. 
    filename: string name for the output file. 
    """ 

    ## This code block was taken from the output of a MATLAB secondary 
    ## capture. I do not know what the long dotted UIDs mean, but 
    ## this code works. 
    file_meta = Dataset() 
    file_meta.MediaStorageSOPClassUID = 'Secondary Capture Image Storage' 
    file_meta.MediaStorageSOPInstanceUID = '1.3.6.1.4.1.9590.100.1.1.111165684411017669021768385720736873780' 
    file_meta.ImplementationClassUID = '1.3.6.1.4.1.9590.100.1.0.100.4.0' 
    ds = FileDataset(filename, {},file_meta = file_meta,preamble="\0"*128) 
    ds.Modality = 'WSD' 
    ds.ContentDate = str(datetime.date.today()).replace('-','') 
    ds.ContentTime = str(time.time()) #milliseconds since the epoch 
    ds.StudyInstanceUID = '1.3.6.1.4.1.9590.100.1.1.124313977412360175234271287472804872093' 
    ds.SeriesInstanceUID = '1.3.6.1.4.1.9590.100.1.1.369231118011061003403421859172643143649' 
    ds.SOPInstanceUID = '1.3.6.1.4.1.9590.100.1.1.111165684411017669021768385720736873780' 
    ds.SOPClassUID = 'Secondary Capture Image Storage' 
    ds.SecondaryCaptureDeviceManufctur = 'Python 2.7.3' 

    ## These are the necessary imaging components of the FileDataset object. 
    ds.SamplesPerPixel = 1 
    ds.PhotometricInterpretation = "MONOCHROME2" 
    ds.PixelRepresentation = 0 
    ds.HighBit = 15 
    ds.BitsStored = 16 
    ds.BitsAllocated = 16 
    ds.SmallestImagePixelValue = '\\x00\\x00' 
    ds.LargestImagePixelValue = '\\xff\\xff' 
    ds.Columns = pixel_array.shape[0] 
    ds.Rows = pixel_array.shape[1] 
    if pixel_array.dtype != np.uint16: 
     pixel_array = pixel_array.astype(np.uint16) 
    ds.PixelData = pixel_array.tostring() 

    ds.save_as(filename) 
    return 



if __name__ == "__main__": 
# pixel_array = np.arange(256*256).reshape(256,256) 
# pixel_array = np.tile(np.arange(256).reshape(16,16),(16,16)) 
    x = np.arange(16).reshape(16,1) 
    pixel_array = (x + x.T) * 32 
    pixel_array = np.tile(pixel_array,(16,16)) 
    write_dicom(pixel_array,'pretty.dcm') 
+0

방금 ​​여기에 귀하의 방법을 보았습니다. "긴 점으로 구분 된 UID"는 정의에 따라 연구/환자/데이터 세트에 대해 고유해야 함을 알려 드리고자합니다. 따라서 모든 데이터 세트를주는 것을 피할 수 있습니다. 이 데이터를 다른 곳으로 가져올 때 충돌로 이어질 수 있기 때문에 동일한 UID 세트를 생성합니다. – Chris

+0

또한 실제 메소드를 공유해 주셔서 감사합니다 :) – Chris

+1

pydicom은 실제로 처음부터 dicom 파일을 만드는 예제를 제공합니다. https : // github.com/darcymason/pydicom/blob/master/source/dicom/examples/write_new.py – Chris

관련 문제