converting 12 bit DICOM image to 8 bit jpeg

笑着哭i 提交于 2019-12-22 17:28:31

问题


I am trying to load DICOM files into python using the dicom library. 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. 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. I wanted it as uint8, so i used the following line to convert to 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:


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. 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

Code: 1.Read the image

ds=dicom.read_file("image_path")
# store the raw image data
img = ds.pixel_array
  1. Use rescale slope and intercept information from the image header and translate it.

    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.

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

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



回答2:


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 . read about Windowing equation here Window width and center calculation of DICOM image

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 . 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




回答3:


Can follow this: 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

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)])


来源:https://stackoverflow.com/questions/44924335/converting-12-bit-dicom-image-to-8-bit-jpeg

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!