Today I’ll explain a little about scalar quantization. The goal of scalar quantization is to try to display an image using less quantization levels or less bit to represent each color level.

This method is very simple and very intuitive but the results aren’t that good. So, what’s the idea of scalar quantization? Imagine that we have an RGB image with color quantization from 0 to 255 (8 bits) and we want to represent the colors level only with 2 bits for each color. So instead of using 24 bits we’ll use only 6.

Ok, but how do we do it? It’s pretty simple, imagine that we divide our range from 0 to 255 in 4 groups for each color: 0 to 63, 64 to 127, 128 to 191, 192 to 255. For each group the average value is 32, 96, 160, 224. So we’ll have in total 64 colors.

So for every pixel, we check every color and find in which group the color fits and replace its value for the average value of that group. For example, for a pixel whose values are (R, G, B) = (25, 78, 230), we’ll convert it to (32, 96, 224). And we do this for every pixel of the image. This is that simple!

One disadvantage of this algorithm is that it process each color in separate way and so we’ll have more color distortion as we can see in the background. We can also see lots of artifacts due lost of resolution. We can compare the result image against the original one below.

Is there any way to improve quality using scalar quantization technique? Yes, we can improve it by using kmeans which aims minimize the mean squared error. We can use the 64 colors define in scalar quantization as centroid to the kmeans function in matlab. The results we can check in the image below. We can easily note an improvement in quality but at cost of more processing.

Next post I’ll show you another algorithm called Vector Quantization. We’ll see that we’ll have much better results

Here the source code for octave/matlab for only scalar quantization

clear all pkg load image %Don't need if matlab fruits = imread('fruits.tiff'); fruits = imresize(fruits, 0.5); img_size = size(fruits); x_max = img_size(1); y_max = img_size(2); fruits_scalar = fruits; for i = 1 : x_max for j = 1 : y_max for color = 1:3 if fruits(i,j,color) < 64 fruits_scalar(i, j, color) = 32; elseif fruits(i,j,color) < 128 fruits_scalar(i, j, color) = 96; elseif fruits(i,j,color) < 192 fruits_scalar(i, j, color) = 160; else fruits_scalar(i, j, color) = 224; end end end end figure(1); imshow(fruits); figure(2); imshow(fruits_scalar); imwrite(fruits_scalar, 'fruits_scalar.png', 'png');

Here the source code for octave/matlab for scalar quantization + kmeans. For Octave we need to adapt kmeans function. Remember, we need statistics package for kmeans in octave.

clear all pkg load image %Don't need if matlab pkg load statistics %Don't need if matlab fruits = imread('fruits.tiff'); fruits = imresize(fruits, 0.5); fruits = reshape(fruits,320*240,3); centroid = ones(64, 3); a = 1; for i = 1 : 4 for j = 1 : 4 for k = 1:4 centroid(a, 1) = i * 64 - 32; centroid(a, 2) = j * 64 - 32; centroid(a, 3) = k * 64 - 32; a = a + 1; end end end fruits = double(fruits); [idx,ctrs,SUMD] = kmeans(fruits, 64, 'start', centroid(1:64,:), 'EmptyAction', 'singleton', 'Display','iter','MaxIter', 5); new_img_vec = ctrs(idx, :); fruits_kmeans = reshape(new_img_vec,240, 320, 3); figure(1); fruits_kmeans = uint8(fruits_kmeans); imshow(fruits_kmeans); imwrite(fruits_kmeans, 'fruits_kmeans5.png', 'png');

That’s all!

Marcelo

Thank you for the post sir. It is very informative.

Just to add something useful… i used Maxim 9526 to decode video from my PAL / NTSC signal from TV cable, that IC is great, then the output was procesed by a Xilinx spartan 3E to detect a color pattern and detect start/end of some spots in public tv. The whole process works great, spartan 3E works good to detect color patterns, substitute them if neccesary and the you can use an Analog Devices IC to get the video signal back in PAL/NTSC… May be that hard + this article can work together as a real time video compressor.

Great info, thanks!