Saturday, February 23, 2013

Image Quantization

The quantization is the idea of minimizing the color of an image to simplify the appearance.
A simplified image permit some compression or some futur works as the image identification.
For begin I propose the image loading that is particular to JPEG and pure RGB format , other aspect could have more or less than 3 colors(transparence, gray,...).


public class FakeJpicture {
    public byte[] pixels;
    public int width;
    public int height;
    public FakeJpicture(File file) throws IOException {
        BufferedImage img;
        img = ImageIO.read(file);
        width=img.getWidth();
        height=img.getHeight();
        pixels = ((DataBufferByte)img.getRaster().getDataBuffer()).getData();
    }

This lines permit to obtain an image names pixels with the size width*height*3 . 3 for RGB.

First work, how to obtain the color:

private int calculateIndex(int x, int y){
        return x+y*width*3;
    }
 
Second work , how to calculate a gray level on this pixel:

public int getGray(int x, int y) {
        int index=calculateIndex(x, y);
        return (int) (0.299*(128+pixels[index])+0.587*(128+pixels[index+1])+0.114*(128+pixels[index+2]));
    }

It s the time to talk about bins. It s easy to calculate some gray level with 256 level.
But our target is to decrease the number of gray level. Exemple 256 -> 8
The most we can do is to cut our level. For exemple the compressed gray level 0 could contain the original gray level from 0 to 7.

I propose an algorithm to calculate the histogram that uses a bins parameter :
public float [] ComputeGrayLevelHistogram(int bins){
        float []Npg=new float[bins];
        for (int i=0;i<bins;i++)
            Npg[i]=0.0f;
        float MN=(float)width*height;
        float NpgSURMN=1.0f/MN; //<- count each time we sea the gray level
        for (int x=0;x<width;x++)
            for (int y=0;y<height;y++){
                int gray=getGray(x,y); // <- get the gray level
                int binsIndex=(int)((gray/256.0)*bins); // <- calculate the compressed level
                Npg[binsIndex]+=NpgSURMN; // <- increment the histo on this value
            }
        return Npg;
    }


Now the colors. To manage RGB colors we need to do the same things coded for the gray value. The difference is to manage 3 colors and not just one value.

For simplify this, I calculate an index managing each bins colors for each colors:
private int calculateRGBIndex(int R, int G,int B,int Rb,int Gb,int Bb){
        return R+G*Rb+B*Rb*Gb;
   }

My algorithm for RGB colors is :

public float [] ComputeRGBHistogram(int binsR,int binsG,int binsB){
        int totalmaxbins=binsR*binsG*binsB;
        float []Npg=new float[totalmaxbins];
        for (int i=0;i<totalmaxbins;i++)
            Npg[i]=0.0f;
        float MN=(float)width*height;
        float NpgSURMN=1.0f/MN;
        for (int x=0;x<width;x++)
            for (int y=0;y<height;y++){
                int index=calculateIndex(x, y);
                int binsRIndex=(int)(((128+pixels[index])/256.0)*binsR);
                int binsGIndex=(int)(((128+pixels[index+1])/256.0)*binsG);
                int binsBIndex=(int)(((128+pixels[index+2])/256.0)*binsB);
                int binsIndex=calculateRGBIndex(binsRIndex, binsGIndex,binsBIndex,binsR,binsG,binsB);
                Npg[binsIndex]+=NpgSURMN;
            }
        return Npg;
    }

The conclusion is that this code can be reused to generate a compressed image.

Result exemple


   Gray histogram on 64 bins

Color 6x6x6 bins



No comments:

Post a Comment