# Quantization Image using MATLAB

I'm trying to quantize an image 8 bits to 4 or 2-bits uniformly. I searched internet, interestingly I could not find what I want exactly. Then I wrote an simple code for it myself. I'm curious about whether there is a build-in function in MATLAB which convert 8-bit image to 4-bits uniformly . My results using the methods from internet is not good. Am I doing something wrong when I use these methods? Thank you in advance.

1. Method from internet giving strange results
reducedImage = uint8((single(monalisa)/256)*2^4);


1. Method writen by me. I'm putting code to clarify what I want to do.
monalisa_2= monalisa;
figure
monalisa_2(monalisa<=63)               = 32  ; %% 00
monalisa_2(monalisa<=127&monalisa>63)  = 85  ; %% 01
monalisa_2(monalisa<=191&monalisa>127) = 159 ; %% 10
monalisa_2(monalisa<=255&monalisa>191) = 223 ; %% 11
imshow(monalisa_2)


• your method not so good .. it's not depending on actulally cretiria i already did this , Quantization on image ,, by using histogram distribution and get details to building your resulted matrix .. – Osama Almiahi Mar 26 '15 at 12:09

I point you to this https://stackoverflow.com/questions/12723699/changing-image-bit-depth-using-matlab it can be done. This particular post is only for png, but if I'm not mistaken all image types have the depth parameter so they can likely all be changed in a similar manner

EDIT

%change this as needed
desired_bit_depth = 2;

my_pixel_depth = 2 ^ desired_bit_depth;
%converts grayscale to an indexed image at the appropriate depth
[ind_im, reduced_colormap ] = gray2ind(my_gray_image, my_pixel_depth)

figure()
subplot(1,2,1);imshow(my_gray_image); title('original')
subplot(1,2,2);imshow(ind_im,reduced_colormap); title(sprintf('reduced to %d bits',desired_bit_depth))

% save indexed png
imwrite(ind_im, reduced_colormap, 'test.png', 'bitdepth', desired_bit_depth);


EDIT #2: While reducing the "bits" to display the image, the "colormap" is made by taking the average of each range I kept the original answer because it still works and may suit someone elses needs in the future.

For this solution, rather than using evenly spaced values for our "colormap' we actually use the gray value that is the average over the specified range

ex

to convert to 1 bit image we have two ranges 0,128 and 128,256

replace all values between 0,128 with the average value between 0,128

replace all values between 128,256 with the average value between 128,256

function result_im = ChangeBitDepthGrayImage(gray_im, desired_bit_depth)
if (desired_bit_depth < 1)
disp('converting to binary(1 bit) image');
desired_bit_depth = 1;
end

if (desired_bit_depth > 8)
disp('converting to 8 bit image');
desired_bit_depth = 8;
end

num_levels = 2 ^ desired_bit_depth;

%figures out how big each range should be, we use +1 because if we
%divide the data into N levels, there should be N+1 boundaries
limits = linspace(0,256,num_levels + 1);

result_im = uint8(zeros(size(gray_im)));

for i = 1:num_levels
lower_lim = limits(i);
upper_lim = limits(i+1);

%creates a binary mask of values between the limits, the output is
%0 or 1, but we need to make it uint8 for the next step
temp_mask = uint8((gray_im >= lower_lim) & (gray_im < upper_lim));

%multiplies image by mask, this isolates only pixels in the given
%range

%finds the mean of that small part of the image. this weird notation is
%taking the average of nonzero elements
avg_val_for_range = round(mean(image_only_in_range(image_only_in_range~=0)));

%replaces all pixels in that range with the average val
result_im = result_im +(avg_val_for_range * temp_mask);
end

%i just picked some random figure
figure(32)
subplot(1,2,1);imshow(gray_im);title('original image');
subplot(1,2,2);imshow(result_im);title(sprintf('modified to %dbit image',desired_bit_depth));
end

• My image is already grayscale and png. What will parameter 'map' be? – toygan kılıç Mar 2 '15 at 22:11
• 'map' is not a parameter, but an output. It tells matlab what color each value in your image should be displayed as (just like using matlabs built-in colormap mathworks.com/help/matlab/ref/colormap.html). Since you reduced the depth of your images matlab has to know how to display these images so it uses the map. Notice in my example, the imshow command is passed the image, AND the new colormap – andrew Mar 2 '15 at 23:44
• Firstly, thank you for your interest. When I tried your code with 1 bit depth, I obtain 0s and 1s. However what I want is uniform quantization. For example: range of 0 to 127 => mean(0,127) range of 128 to 255 => mean(128,255) – toygan kılıç Mar 3 '15 at 0:13
• Ok now I understand the problem. As far as I know there is no built in function to do this, but I came up with a method. It uses lots of binary masking. I'm not sure if there is a better way to do it, but this works and is relatively quick. – andrew Mar 3 '15 at 1:06