Convert an 8 bit image to 12 bit

22 visualizaciones (últimos 30 días)
Amir Cawich
Amir Cawich el 22 de Ag. de 2022
Editada: DGM el 6 de Jul. de 2024
I am trying to convert an image from 8bit to 12 bit. I understand 8 bit can go from 0-256 while 12 can go from 0-4095 i believe. Basically i am using the bit value for analysis purpose so using a 12 bit image makes more sense for me. However I don't have a lot of experience with image processing. Can i simply multiply the 8 bit values by a fraction of 256 or something similar? If anyone has any experience doing this can provide some feedback. I have read about going from 12 bit to 8 bit but it is hard to find information on going the other way.

Respuesta aceptada

Chunru
Chunru el 22 de Ag. de 2022
I = imread("peppers.png"); % 8-bit image
whos
Name Size Bytes Class Attributes I 384x512x3 589824 uint8 cmdout 1x33 66 char
I1 = double(I)/256; % 8->12bit
imwrite(I1, 'test.jpg', 'BitDepth', 12); % JPEG supports 12 bits
I2 = imread('test.jpg');
class(I2)
ans = 'uint16'
I2 = rescale(I2); % rescale
class(I2)
ans = 'double'
imshow(I2)
  2 comentarios
Amir Cawich
Amir Cawich el 22 de Ag. de 2022
Thank you so much. It works
DGM
DGM el 6 de Jul. de 2024
Editada: DGM el 6 de Jul. de 2024
I have to disagree, not only to using JPG temp files, but the scaling is wrong.
% images don't always span the domain implied by their class
I0 = imread("peppers.png"); % uint8
I = imadjust(I0,[0 1],[0.25 0.75]); % reduce the contrast
% this scaling factor is incorrect
% [0 255] is mapped to [0 0.996], not [0 1]
% so the uint12 image will be [0 4078], not [0 4095]
% this should just be replaced with im2double()
I = double(I)/256; % this is off by one
% JPG doesn't do anything other than damage the image.
% I does actually need to be unit-scale float here,
% otherwise the result will be wildly mis-scaled or full of
% banding artifacts from some sort of integer overflow.
% i'm not sure if that's a bug, but it doesn't seem to be documented.
imwrite(I, 'test.jpg', 'BitDepth', 12); % JPEG supports 12 bits
I2 = imread('test.jpg');
% this will not preserve the contrast of the image
% not merely because we're using the extrema instead of the domain limits
% but because the extrema have been grossly shifted by imwrite()/imread()
% as a consequence, we don't even get remotely close to the contrast
% of either the original image or the low-contrast image copy
% we just get something random in-between
I2 = rescale(I2); % stretch global extrema to [0 1]
% original image
% low-contrast copy
% some degraded copy with random wrong contrast
imshow([im2double(I0) I I2])
If you want to rescale the data, rescale the data.
% images don't always span the domain implied by their class
I0 = imread("peppers.png"); % uint8
I = imadjust(I0,[0 1],[0.25 0.75]); % reduce the contrast
% rescale it and shove it into a class that can hold it
% Y = X/((2^8 - 1)/(2^12 - 1)), not X/2^(8-12)
ir = getrangefromclass(I); % input scale
or = [0 2^12-1]; % output scale for 12b
scalefactor = diff(or)/diff(ir);
I2 = cast((double(I) - ir(1))*scalefactor,'uint16');
% original image
% low-contrast copy
% correct contrast, but uint12-scale in uint16
imshow([im2double(I0) im2double(I) double(I2)/4095])
That said, if you want to work with uint12-scale image data, you're going to constantly be working around the fact that it's improperly-scaled for its class, no matter what class (e.g. 'uint16','double') you cram it into. No scale-dependent tools will handle it properly without extra effort, including imshow() and imwrite().
If you want to store technical working data in a native 12-bit image format, then as far as I recall, JPG is the only thing imwrite says it supports. As far as I'm concerned, that's only an option if you don't mind ruining your data.
You can always write non-native uint12-scale uint16 in anything that supports uint16 though (e.g. PNG). It'll be lossless, but now you're just exporting the problem of improper scale outside of MATLAB.
Alternatively, you could do something like this with PNG. In this usage, any native-scale image is written to a 16-bit PNG, ostensibly keeping the 4 least significant bits. The data returned by imread() will not be uint12-scale. It will be uint16-scale. The size of the last argument to imwrite() must be tailored to match the depth of the image.
% a uint8 image
inpict = imread('peppers.png');
% write it as bitshifted uint12-scale data in uint16
imwrite(inpict,'testme.png','bitdepth',16,'SignificantBits',[12 12 12]);
% imread() won't shift the data back
recovered = imread('testme.png'); % uint16-scale
% so shift it back
recovered = bitshift(recovered,-4); % uint12-scale
Because of the way the data is represented in the file, it should remain readable by other apps. Likewise, there may be similar roundabout things you can do with PNM.

Iniciar sesión para comentar.

Más respuestas (1)

DGM
DGM el 6 de Jul. de 2024
Editada: DGM el 6 de Jul. de 2024
MIMT imcast() does this sort of rescaling without needing to jump through hoops.
% a properly-scaled image of any class
inpict = imread('peppers.png'); % uint8 RGB
% any native-scale image --> uint12-scale uint16
outpict = imcast(inpict,class(inpict),'uint12');

Categorías

Más información sobre Matrix Indexing en Help Center y File Exchange.

Community Treasure Hunt

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

Start Hunting!

Translated by