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
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