There is something that I probably misunderstand about data types in images. Lets say we have an uint8 image. Since uint8 is between 0 and 255, 0 is the darkest and 255 is the brightest intensity value.
Same logic would make -32768 the darkest and 32767 the brightest intensity value for an int16 image. However, I have an int16 image(it is originally a dicom) where the darkest pixel is -1024 and the brightest is 4095. I say int16 because pixels are saved in an int16 type numpy array.
In addition, when I concatenate two int16 numpy arrays where one of them is a = np.ones((100,100), dtype=np.int16) * 32767
and the other is b = np.ones((100,100), dtype=np.int16) * 32766
, It results in a binary image where 32767s is white and 32766s are black.
Can someone help me about what I am getting wrong?
Short answer
Nothing is wrong, this is how DICOM works.
Long answer
In DICOM standard, pixel value is not directly related to its color (gray level). These values should correspond to physical properties of the acquired item (e.g. in Computed Tomography pixel values are measured in Hounsfield Units. *(unless they are linearly rescaled, see below)).
Gray level of the pixel image is displayed dynamically based on arbitrary chosen minimal and maximal values, which are set by the user. Every pixel value less or equal minimum is black, every pixel greater or equal maximum is white, the others are linearly interpolated gray levels.
So it is perfectly fine that in binary image black minimum is equal to 32766 and white maximum is equal to 32767.
If you use DICOM viewer, you will have possibility to change dynamically these minimal and maximal values, so you will change total contrast and brightness of the image. It is necessary for radiologists, to diagnose e.g. lungs and bones in different ranges. And if you export DICOM to other file format, you should choose, what is the color mapping. Normally it is full range (the lowest value gets black, the brightest gets white).
There are two other values, which are often used instead of minimum and maximum: "window width" (ww) and "window level" (wl). ww = max-min
, wl=(max+min)/2
.
You should look at these questions and answers:
*you should also consider tags "rescale intercept" (0028,1052), and "rescale slope" (0028,1053), that lineary rescale value of pixel array to the final value, but normally it is implemented in dicom toolkit.
FinalPixelValue = (RawPixelValue * RescaleSlope) + RescaleIntercept