我正在尝试使用dicom库将DICOM文件加载到python中。我做了以下
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)
IMAGES
[1]转换后的图片:https://i.stack.imgur.com/wdGCo.jpg [2]原始图片:https://i.stack.imgur.com/JyfYI.jpg
答案 0 :(得分:1)
我找到了解决问题的方法。正如上面提到的Ahmed,DICOM围绕重新缩放斜率,截距和窗口水平/宽度进行正常显示。经过大量的文档后,这里是使用OpenCV,numpy和pydicom库在Python中呈现DICOM的方法,这使得所有工作变得轻松
代码: 1.阅读图片
ds=dicom.read_file("image_path")
# store the raw image data
img = ds.pixel_array
使用重新缩放斜率和截取图像标题中的信息并进行翻译。
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)
答案 1 :(得分:0)
请参考http://dicom.nema.org/DICOM/2013/output/chtml/part04/sect_N.2.html查看医学图像像素数据在显示之前的呈现方式 并非所有提到的概念都适用,但我假设您错过了窗口级别和窗口中心值的重要性。 在这里阅读关于窗口方程 Window width and center calculation of DICOM image
因此,如果您在正确渲染之前尝试降低Image的bitDepth(丢失最不重要的数据),那么肯定会得到一个糟糕的图像。 考虑在转换前对原始数据应用窗口,您可以使用imageJ工具在编写代码之前查看图像操作(WL,降级深度)
答案 2 :(得分:0)
可以遵循这个: 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)])