[英]converting 12 bit DICOM image to 8 bit jpeg
I am trying to load DICOM files into python using the dicom library.我正在尝试使用 dicom 库将 DICOM 文件加载到 python 中。 I have done the following我做了以下
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
This gives me values that appear to be 12 bit, since the highest value obtained was around 3047 and lowest value was 0. Then i made my own mapping function to bring it to the range 0-255.这给了我看起来是 12 位的值,因为获得的最高值大约是 3047,而最低值是 0。然后我制作了自己的映射函数,将它带到 0-255 的范围内。 I used the following code:我使用了以下代码:
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)
After doing this I realized that the array img_array was of type uint16.这样做之后,我意识到数组 img_array 的类型是 uint16。 I wanted it as uint8, so i used the following line to convert to uint8:我想要它作为 uint8,所以我使用以下行转换为 uint8:
cvuint8 = cv2.convertScaleAbs(correct_range_image)
Then I displayed the resulting image.然后我显示了结果图像。 But i received an image that didn't represent the original image very well.但是我收到的图像不能很好地代表原始图像。 I have posted pictures of the original image and the converted image.我已经发布了原始图像和转换图像的图片。 How can I make the conversion better so that I get a better representation of the original image??如何使转换更好,以便更好地表示原始图像? Code I used to display is here :我用来显示的代码在这里:
cv2.imwrite('1.jpeg', cvuint8 )
cv2.imshow('image',cvuint8 )[enter image description here][1]
cv2.waitKey(0)
IMAGES图片
[1] Converted Image: https://i.stack.imgur.com/wdGCo.jpg [2] Original Image: https://i.stack.imgur.com/JyfYI.jpg [1] 转换图: https : //i.stack.imgur.com/wdGCo.jpg [2] 原图: https : //i.stack.imgur.com/JyfYI.jpg
I figured out the solution for my problem.As mentioned above by Ahmed, DICOM plays around rescale slope, intercept and window level/width for proper display.我找到了解决我的问题的方法。正如 Ahmed 上面提到的,DICOM 会围绕重新调整斜率、截距和窗口级别/宽度进行播放,以便正确显示。 After going through lot of documents, here is the way to render DICOM in Python using OpenCV,numpy and pydicom libraries which make all work easy在浏览了大量文档后,这里是使用 OpenCV、numpy 和 pydicom 库在 Python 中呈现 DICOM 的方法,这使所有工作变得容易
Code: 1.Read the image代码: 1.读取图像
ds=dicom.read_file("image_path")
# store the raw image data
img = ds.pixel_array
Use rescale slope and intercept information from the image header and translate it.使用重新调整斜率并截取图像标题中的信息并进行翻译。
rescale_slope=1 rescale_intercept=-1024 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.Use window level and width information from the image header to display in the proper range. 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.Finally, with final image as wanted 4.最后,根据需要使用最终图像
scaled_img = cv2.convertScaleAbs(scaled_img)
cv2.imshow('image',scaled_img)
cv2.imwrite("hem.jpg",scaled_img)
cv2.waitKey(0)
please refer to http://dicom.nema.org/DICOM/2013/output/chtml/part04/sect_N.2.html to see how the medical image pixel data is rendered before its displayed not all mentioned concepts is applied but i assume your missing the importance of Window level and window Center Values .请参阅http://dicom.nema.org/DICOM/2013/output/chtml/part04/sect_N.2.html以了解医学图像像素数据在显示之前是如何呈现的,并非所有提到的概念都适用,但我假设您错过了 Window level 和 window Center Values 的重要性。 read about Windowing equation here Window width and center calculation of DICOM image在此处阅读有关 Windowing equation 的 DICOM 图像的窗口宽度和中心计算
So if you are trying to downgrade the bitDepth of the Image before its correctly rendered (losing least important data) , for sure you will get a bad image .因此,如果您试图在图像正确呈现(丢失最不重要的数据)之前降级图像的 bitDepth,那么您肯定会得到一个糟糕的图像。 consider applying windowing on original data before conversion , you can play with imageJ tool to see image operations (WL , Downgrading Depth) in action before writing the code for it考虑在转换前对原始数据应用窗口化,您可以在为其编写代码之前使用imageJ工具查看图像操作(WL,降级深度)的实际效果
Can follow this: https://raw.githubusercontent.com/VolumeRC/AtlasConversionScripts/master/src/convertDICOM.py可以按照这个: https : //raw.githubusercontent.com/VolumeRC/AtlasConversionScripts/master/src/convertDICOM.py
where in simple way they have mentioned DICOM rendering using window level/width, rescale slope/intercept他们以简单的方式提到了使用窗口级别/宽度、重新调整斜率/截距的 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)])
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.