преобразование 12-битного изображения DICOM в 8-битный jpeg

Я пытаюсь загрузить файлы DICOM в python, используя библиотеку dicom. Я сделал следующее

ds=dicom.read_file(r"C:\Users\Z003SPFR.AD005\ML\GLCM AND SVM\data\NECT\1.IMA")
#    # store the raw image data
DicomImage = ds.pixel_array

Это дает мне значения, которые кажутся 12-битными, поскольку наибольшее полученное значение было около 3047, а самое низкое значение было 0. Затем я сделал свою собственную функцию отображения, чтобы привести ее к диапазону 0-255. Я использовал следующий код:

leftMin = 0
leftMax = np.amax(DicomImage)

rightMin = 0
rightMax = 255



def translate(value, leftMin, leftMax, rightMin, rightMax):
    # Figure out how 'wide' each range is
    leftSpan = leftMax - leftMin
    rightSpan = rightMax - rightMin

    # Convert the left range into a 0-1 range (float)
    valueScaled = float(value - leftMin) / float(leftSpan)

    # Convert the 0-1 range into a value in the right range.
    return rightMin + (valueScaled * rightSpan)

#print(translate(value, leftMin, leftMax, rightMin, rightMax))



def int12_to_int8(img):
    img_array = []

    for eachRow in img:
        for eachPix in eachRow:
            img_array.append(translate(eachPix,leftMin, leftMax, rightMin, rightMax))
    img_array = np.array(img_array)
    img_array = img_array.reshape(512,512)  
    return img_array

correct_range_image = int12_to_int8(DicomImage)

После этого я понял, что массив img_array имеет тип uint16. Я хотел, чтобы это было как uint8, поэтому я использовал следующую строку для преобразования в uint8:

cvuint8 = cv2.convertScaleAbs(correct_range_image)

Затем я отобразил полученное изображение. Но я получил изображение, которое не очень хорошо представляло исходное изображение. Я разместил фотографии исходного изображения и преобразованного изображения. Как я могу улучшить преобразование, чтобы получить лучшее представление исходного изображения?? Код, который я использовал для отображения, находится здесь:

cv2.imwrite('1.jpeg', cvuint8 )
cv2.imshow('image',cvuint8 )[enter image description here][1]
cv2.waitKey(0)

КАРТИНКИ

[1] Преобразованное изображение: https://i.stack.imgur.com/wdGCo.jpg [2] Исходное изображение: https://i.stack.imgur.com/JyfYI.jpg


person Reshma    schedule 05.07.2017    source источник


Ответы (3)


Я нашел решение своей проблемы. Как упоминалось выше Ахмедом, DICOM играет с изменением масштаба наклона, точки пересечения и уровня/ширины окна для правильного отображения. После просмотра множества документов, вот способ визуализации DICOM в Python с использованием библиотек OpenCV, numpy и pydicom, которые упрощают работу.

Код: 1.Прочитайте изображение

ds=dicom.read_file("image_path")
# store the raw image data
img = ds.pixel_array
  1. Используйте масштабирование наклона и перехватите информацию из заголовка изображения и переведите ее.

    rescale_slope=1 rescale_intercept=-1024

    def translate(value,rescale_slope,rescale_intercept):
    
    return (value*rescale_slope)+rescale_intercept 
    
    def int12_to_int8(DicomImage):
        img_array = []
    
    for eachRow in DicomImage:
        for eachPix in eachRow:
            img_array.append(translate(eachPix,rescale_slope,rescale_intercept))
    img_array = np.array(img_array)
    img_array = img_array.reshape(512,512)  
    return img_array
    
    img_1 = int12_to_int8(img)
    

3. Используйте информацию об уровне и ширине окна из заголовка изображения для отображения в правильном диапазоне.

def get_LUT_value(data, window, level)

    return np.piecewise(data, 
        [data <= (level - 0.5 - (window-1)/2),
            data > (level - 0.5 + (window-1)/2)],
            [0, 255, lambda data: ((data - (level - 0.5))/(window-1) + 0.5)*(255-0)])

level=200
window=800

scaled_img=get_LUT_value(img, window, level)

4. Наконец, с окончательным изображением по желанию

scaled_img = cv2.convertScaleAbs(scaled_img)
cv2.imshow('image',scaled_img)
cv2.imwrite("hem.jpg",scaled_img)
cv2.waitKey(0)
person Reshma    schedule 24.07.2017

см. http://dicom.nema.org/DICOM/2013/output/chtml/part04/sect_N.2.html, чтобы увидеть, как данные пикселей медицинского изображения визуализируются до их отображения, не применяются все упомянутые концепции, но я предполагаю, что вы упускаете из виду важность уровня окна и центральные значения окна. прочитайте об уравнении Windowing здесь Ширина окна и вычисление центра изображения DICOM

Поэтому, если вы пытаетесь понизить битовую глубину изображения до его правильного отображения (с потерей наименее важных данных), вы наверняка получите плохое изображение. Рассмотрите возможность применения окна к исходным данным перед преобразованием. Вы можете поиграть с инструментом imageJ, чтобы увидеть операции с изображениями (WL, понижение глубины ) в действии, прежде чем писать для него код

person Ahmed Hussein    schedule 06.07.2017

Можно следовать этому: https://raw.githubusercontent.com/VolumeRC/AtlasConversionScripts/master/src/convertDICOM.py

где простым способом они упомянули рендеринг DICOM с использованием уровня/ширины окна, масштабирования наклона/пересечения

def get_LUT_value(data, window, level,rescaleSlope,rescaleIntercept):
    return np.piecewise(data,
                        [((data * rescaleSlope) + rescaleIntercept) <= (level - 0.5 - (window - 1) / 2),
                         ((data * rescaleSlope) + rescaleIntercept) > (level - 0.5 + (window - 1) / 2)],
                        [0, 255, lambda VAL: ((((VAL * rescaleSlope) + rescaleIntercept) - (level - 0.5)) / (
                        window - 1) + 0.5) * (255 - 0)])
person Reshma    schedule 24.07.2017