convert 16 bit image to 8 bit image

167 visualizaciones (últimos 30 días)
mohd
mohd el 5 de Mzo. de 2012
Editada: DGM el 30 de Dic. de 2023
how to convert 16 bit image to 8 bit image

Respuesta aceptada

Jan
Jan el 5 de Mzo. de 2012
The uint16 image used values from 0 to 2^16-1, while the uint8 images use a range from, 0 to 2^8-1 only. If you just cast the original values to uint8, the saturation will destroy a lot of information. Better use:
img8 = uint8(img16 / 256);
  2 comentarios
Wayne King
Wayne King el 5 de Mzo. de 2012
good point Jan, I forgot to say that.
dror yemini
dror yemini el 10 de Sept. de 2020
yes but you loase somthing better before take bits with information so maybe do equalization of histogram before conversion ?

Iniciar sesión para comentar.

Más respuestas (3)

Rasmus Herlo
Rasmus Herlo el 11 de Feb. de 2021
OBS: Jan's answer will do absolutely fine, if your image is optimized to use the entire scale. However, if your pixel values are only occupying a fraction of the available bits (common in much imaging), the direct conversion will lead to a significant loss of information. In addition, you might want to get your image on 1:2^16 (instead of 0:2^16-1) before normalizing.
Image conversion in software like ImageJ therefore uses linear scaling, and one would typically apply a similar approach here, by:
Input: Im16 'uint16' (any 16bit image)
dbIm16 = double(Im16)+1
dbIm16 = min(dbIm16(:)); db16max = max(dbIm16(:));
TgBit = 8; % or any other lower bit scale
% example with 16bit to 8bit
Norm_wOffSet = dbIm16/db16max; % maintaining putative offset from 0 in the data
Im8_wOffSet = uint8(Norm_wOffSet*2^TgBit-1); % back to 0:2^8-1
Norm_woOffSet = (dbIm16-db16min)/(db16max-db16min); % Scales linearly to full range
Im8_woOffSet = uint8(Norm_woOffSet*2^TgBit-1); % back to 0:2^8-1
  1 comentario
Tiziana
Tiziana el 21 de Nov. de 2022
Thank so much for your answer. Could I ask you the reasons of this "you might want to get your image on 1:2^16 (instead of 0:2^16-1) before normalizing"? Thank you very much.

Iniciar sesión para comentar.


Wayne King
Wayne King el 5 de Mzo. de 2012
You can use uint8() to cast the image into unsigned 8-bit integers. Or int8() for signed 8-bit integers.
X = uint8(ones(10,10,'uint16'));
class(X)

DGM
DGM el 30 de Dic. de 2023
Editada: DGM el 30 de Dic. de 2023
I don't know why nobody brought it up in 10+ years, but:
outpict = im2uint8(inpict); % recast with appropriate scaling
This will preserve the relative scale of the image regardless of the input class. Everything within the expected range of the input class (i.e. [-32768 32767] for int16) will fit within [0 255]. This works regardless of whether the input is int16 or uint16 or double, etc.
@Rasmus Herlo has a good point, though. A lot of technical and medical images in 16b seem to be unscaled raw values that occupy a small portion of the available dynamic range. Depending on the goals, it might be prudent to rescale them. That's easy enough.
outpict = im2uint8(mat2gray(inpict)); % normalize to extrema, then recast/scale
... though if the image is some sort of raw sensor data, a contextually-relevant nonlinear scaling might be more appropriate.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by