Использование изображений dicom с OpenCV в Python

Я пытаюсь использовать изображение dicom и манипулировать им, используя OpenCV в среде Python. До сих пор я использовал библиотеку pydicom для чтения данных изображения dicom(.dcm) и использования атрибута массива пикселей для отображения изображения с помощью метода OpenCV imshow. Но вывод - просто пустое окно. Вот фрагмент кода, который я использую в данный момент.

import numpy as np
import cv2
import pydicom as dicom

ds=dicom.dcmread('sample.dcm')
cv2.imshow('sample image dicom',ds.pixel_array)

cv2.waitkey()

Если я распечатаю массив, который используется здесь, результат будет отличаться от того, что я получу с обычным массивом numpy. Я также попытался использовать метод matplotlib imshow, и он смог отобразить изображение с некоторыми искажениями цвета. Есть ли способ конвертировать массив в удобочитаемый формат для OpenCV?

4 ответа

Решение

Я нашел способ заставить изображение показать. Как отметил Дэн в комментариях, значение матрицы было уменьшено, и из-за функции imshow выходные данные были слишком темными, чтобы человеческий глаз не мог их различить. Итак, в конце концов, единственное, что мне нужно было сделать, - это умножить все данные по мату на 128. Изображение теперь отлично видно. умножение матрицы на 255 обнажает изображение и приводит к потере определенных функций. Вот пересмотренный код.

import numpy as np
import cv2
import pydicom as dicom

ds=dicom.dcmread('sample.dcm')
dcm_sample=ds.pixel_array*128
cv2.imshow('sample image dicom',dcm_sample)

cv2.waitkey()

Столкнулся с аналогичной проблемой. Используемыйexposure.equalize_adapthist()(источник). Полученное изображение не является стопроцентным по сравнению с тем, которое вы могли бы увидеть с помощью средства просмотра DICOM Viewer, но это лучшее, что мне удалось получить.

import numpy as np
import cv2
import pydicom as dicom
from skimage import exposure

ds=dicom.dcmread('sample.dcm')
dcm_sample=ds.pixel_array
dcm_sample=exposure.equalize_adapthist(dcm_sample)
cv2.imshow('sample image dicom',dcm_sample)

cv2.waitkey()

Это лучший способ (на мой взгляд) открыть изображение в opencv в виде массива numpy, сохраняя при этом качество изображения:

      import numpy as np
import pydicom, os, cv2

def dicom_to_numpy(ds):
    DCM_Img = ds
    rows = DCM_Img.get(0x00280010).value #Get number of rows from tag (0028, 0010)
    cols = DCM_Img.get(0x00280011).value #Get number of cols from tag (0028, 0011)
    
    Instance_Number = int(DCM_Img.get(0x00200013).value) #Get actual slice instance number from tag (0020, 0013)

    Window_Center = int(DCM_Img.get(0x00281050).value) #Get window center from tag (0028, 1050)
    
    Window_Width = int(DCM_Img.get(0x00281051).value) #Get window width from tag (0028, 1051)

    Window_Max = int(Window_Center + Window_Width / 2)
    Window_Min = int(Window_Center - Window_Width / 2)


    if (DCM_Img.get(0x00281052) is None):
        Rescale_Intercept = 0
    else:
        Rescale_Intercept = int(DCM_Img.get(0x00281052).value)

    if (DCM_Img.get(0x00281053) is None):
        Rescale_Slope = 1
    else:
        Rescale_Slope = int(DCM_Img.get(0x00281053).value)

    New_Img = np.zeros((rows, cols), np.uint8)
    Pixels = DCM_Img.pixel_array

    for i in range(0, rows):
        for j in range(0, cols):
            Pix_Val = Pixels[i][j]
            Rescale_Pix_Val = Pix_Val * Rescale_Slope + Rescale_Intercept

            if (Rescale_Pix_Val > Window_Max): #if intensity is greater than max window
                New_Img[i][j] = 255
            elif (Rescale_Pix_Val < Window_Min): #if intensity is less than min window
                New_Img[i][j] = 0
            else:
                New_Img[i][j] = int(((Rescale_Pix_Val - Window_Min) / (Window_Max - Window_Min)) * 255) #Normalize the intensities
                
    return New_Img


file_path = "C:/example.dcm"
image = pydicom.read_file(file_path)
image = dicom_to_numpy(image)

#show image
cv2.imshow('sample image dicom',image)
cv2.waitKey(0)
cv2.destroyAllWindows()

Я не думаю, что это правильный ответ. Это работает для этого конкретного изображения, потому что большинство ваших значений пикселей находятся в нижнем диапазоне. Отметьте этот OpenCV: Как визуализировать изображение глубины. Он предназначен для C++, но легко адаптируется к Python.

Другие вопросы по тегам