在Python中使用带有OpenCV的DICOM图像

jk9hmnmh  于 2022-12-23  发布在  Python
关注(0)|答案(4)|浏览(217)

我尝试使用dicom图像,并在Python环境中使用OpenCV对其进行操作。到目前为止,我已经使用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可读的格式?

wwtsj6pe

wwtsj6pe1#

我遇到了类似的问题。使用exposure.equalize_adapthist()source)。结果图像不是百分之百的,你会看到使用DICOM查看器,但它是最好的,我能得到的。

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()
ddhy6vgd

ddhy6vgd2#

我已经想出了一个让图像显示出来的方法,正如Dan在评论中提到的,矩阵的值被按比例缩小了,由于imshow函数的原因,输出太暗,人眼无法区分。所以,最后我唯一需要做的就是把整个垫子数据乘以128。现在图像显示得很完美。将矩阵乘以255会使图片曝光,并导致某些功能崩溃。2以下是修改后的代码。

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()
j8yoct9x

j8yoct9x3#

我不认为这是一个正确的答案。它适用于特定的图像,因为你的大多数像素值都在较低的范围内。检查这个OpenCV: How to visualize a depth image。它是为c++,但很容易适应Python。

uqjltbpv

uqjltbpv4#

这是在opencv中将image作为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()

相关问题