📄 colorlayout.java
字号:
/*
* This file is part of Caliph & Emir.
*
* Caliph & Emir is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Caliph & Emir is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Caliph & Emir; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Copyright statement:
* --------------------
* (c) 2002-2004 by Mathias Lux (mathias@juggle.at)
* http://www.juggle.at
*/
/*
*
*
*
* @author Mathias Lux, mathias@juggle.at
* Date: 16.09.2002
* Time: 14:45:06
*/
package at.lux.imageanalysis;
import org.jdom.Element;
import org.jdom.Namespace;
import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;
import java.util.Iterator;
import java.util.StringTokenizer;
import java.util.Vector;
/**
* Class for extrcating & comparing MPEG-7 based CBIR descriptor ColorLayout
* @author Mathias Lux, mathias@juggle.at
*/
public class ColorLayout {
// static final boolean debug = true;
private int[][] shape;
private int imgYSize, imgXSize;
private BufferedImage img;
private static int[] availableCoeffNumbers = {1, 3, 6, 10, 15, 21, 28, 64};
private int[] YCoeff, CbCoeff, CrCoeff;
private int numCCoeff = 3, numYCoeff = 6;
private static int[] arrayZigZag = {
0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5,
12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28,
35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51,
58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63
};
private static double[][] arrayCosin = {
{
3.535534e-01, 3.535534e-01, 3.535534e-01, 3.535534e-01,
3.535534e-01, 3.535534e-01, 3.535534e-01, 3.535534e-01
},
{
4.903926e-01, 4.157348e-01, 2.777851e-01, 9.754516e-02,
-9.754516e-02, -2.777851e-01, -4.157348e-01, -4.903926e-01
},
{
4.619398e-01, 1.913417e-01, -1.913417e-01, -4.619398e-01,
-4.619398e-01, -1.913417e-01, 1.913417e-01, 4.619398e-01
},
{
4.157348e-01, -9.754516e-02, -4.903926e-01, -2.777851e-01,
2.777851e-01, 4.903926e-01, 9.754516e-02, -4.157348e-01
},
{
3.535534e-01, -3.535534e-01, -3.535534e-01, 3.535534e-01,
3.535534e-01, -3.535534e-01, -3.535534e-01, 3.535534e-01
},
{
2.777851e-01, -4.903926e-01, 9.754516e-02, 4.157348e-01,
-4.157348e-01, -9.754516e-02, 4.903926e-01, -2.777851e-01
},
{
1.913417e-01, -4.619398e-01, 4.619398e-01, -1.913417e-01,
-1.913417e-01, 4.619398e-01, -4.619398e-01, 1.913417e-01
},
{
9.754516e-02, -2.777851e-01, 4.157348e-01, -4.903926e-01,
4.903926e-01, -4.157348e-01, 2.777851e-01, -9.754516e-02
}
};
private static int[][] weightMatrix = new int[3][64];
private BufferedImage colorLayoutImage;
/**
* Create a ColorLayout Object from the given BufferedImage. 6 Y and 3 C Coefficients are used,
* if you want to use another number you have to set it with the Setters.
* @param image the input image
*/
public ColorLayout(BufferedImage image) {
this.img = image;
imgYSize = image.getHeight();
imgXSize = image.getWidth();
init();
}
/**
* Create a ColorLayout Object from the given BufferedImage with the desired number of Coefficients
* @param image the input image
* @param numberOfYCoeff desired number of Y Coefficients
* @param numberOfCCoeff desired number of Cr and Cb Coefficients
*/
public ColorLayout(int numberOfYCoeff, int numberOfCCoeff, BufferedImage image) {
this.numCCoeff = getRightCoeffNumber(numberOfCCoeff);
this.numYCoeff = getRightCoeffNumber(numberOfYCoeff);
this.img = image;
imgYSize = image.getHeight();
imgXSize = image.getWidth();
init();
}
/**
* Create a ColorLayout Object from its descriptor
* @param descriptor the descriptor as JDOM Element
*/
public ColorLayout(Element descriptor) {
this.img = null;
YCoeff = new int[64];
CbCoeff = new int[64];
CrCoeff = new int[64];
colorLayoutImage = null;
Vector v = getCoeffs(descriptor);
if (v != null) {
int[] y = (int[]) v.get(0);
int[] cb = (int[]) v.get(1);
int[] cr = (int[]) v.get(2);
for (int i = 0; i < 64; i++) {
if (i < y.length) {
YCoeff[i] = y[i];
} else {
YCoeff[i] = 16;
}
if (i < cb.length) {
CbCoeff[i] = cb[i];
CrCoeff[i] = cr[i];
} else {
CbCoeff[i] = 16;
CrCoeff[i] = 16;
}
}
} else {
// debug("Descriptor not valid!!!");
}
}
/**
* init used by all constructors
*/
private void init() {
shape = new int[3][64];
YCoeff = new int[64];
CbCoeff = new int[64];
CrCoeff = new int[64];
colorLayoutImage = null;
extract();
}
private void createShape() {
int y_axis, x_axis;
int i, k, x, y, j;
long[][] sum = new long[3][64];
int[] cnt = new int[64];
double yy = 0.0;
int R,G,B;
//init of the blocks
for (i = 0; i < 64; i++) {
cnt[i] = 0;
sum[0][i] = 0;
sum[1][i] = 0;
sum[2][i] = 0;
shape[0][i] = 0;
shape[1][i] = 0;
shape[2][i] = 0;
}
WritableRaster raster = img.getRaster();
int[] pixel = {0, 0, 0};
for (y = 0; y < imgYSize; y++) {
for (x = 0; x < imgXSize; x++) {
raster.getPixel(x, y, pixel);
R = pixel[0];
G = pixel[1];
B = pixel[2];
y_axis = (int) (y / (imgYSize / 8.0));
x_axis = (int) (x / (imgXSize / 8.0));
k = y_axis * 8 + x_axis;
//RGB to YCbCr, partition and average-calculation
yy = (0.299 * R + 0.587 * G + 0.114 * B) / 256.0;
sum[0][k] += (int) (219.0 * yy + 16.5); // Y
sum[1][k] += (int) (224.0 * 0.564 * (B / 256.0 * 1.0 - yy) + 128.5); // Cb
sum[2][k] += (int) (224.0 * 0.713 * (R / 256.0 * 1.0 - yy) + 128.5); // Cr
cnt[k]++;
}
}
for (i = 0; i < 8; i++) {
for (j = 0; j < 8; j++) {
for (k = 0; k < 3; k++) {
if (cnt[i * 8 + j] != 0)
shape[k][i * 8 + j] = (int) (sum[k][i * 8 + j] / cnt[i * 8 + j]);
else
shape[k][i * 8 + j] = 0;
}
}
}
}
private void Fdct(int[] shapes) {
int i, j ,k;
double s;
double[] dct = new double[64];
//calculation of the cos-values of the second sum
for (i = 0; i < 8; i++) {
for (j = 0; j < 8; j++) {
s = 0.0;
for (k = 0; k < 8; k++)
s += arrayCosin[j][k] * shapes[8 * i + k];
dct[8 * i + j] = s;
}
}
for (j = 0; j < 8; j++) {
for (i = 0; i < 8; i++) {
s = 0.0;
for (k = 0; k < 8; k++)
s += arrayCosin[i][k] * dct[8 * k + j];
shapes[8 * i + j] = (int) Math.floor(s + 0.499999);
}
}
}
private int quant_ydc(int i) {
int j;
if (i > 192)
j = 112 + (i - 192) / 4;
else if (i > 160)
j = 96 + (i - 160) / 2;
else if (i > 96)
j = 32 + (i - 96);
else if (i > 64)
j = 16 + (i - 64) / 2;
else
j = i / 4;
return j;
}
private int quant_cdc(int i) {
int j;
if (i > 191)
j = 63;
else if (i > 160)
j = 56 + (i - 160) / 4;
else if (i > 144)
j = 48 + (i - 144) / 2;
else if (i > 112)
j = 16 + (i - 112);
else if (i > 96)
j = 8 + (i - 96) / 2;
else if (i > 64)
j = (i - 64) / 4;
else
j = 0;
return j;
}
private int quant_ac(int i) {
int j;
if (i > 255)
i = 255;
//if(i > 239)
//i = 239;
if (i < -256)
i = -256;
if ((Math.abs(i)) > 127)
j = 64 + (Math.abs(i)) / 4;
else if ((Math.abs(i)) > 63)
j = 32 + (Math.abs(i)) / 2;
else
j = Math.abs(i);
j = (i < 0) ? -j :j;
j += 128;
//j+=132;
return j;
}
private int extract() {
createShape();
Fdct(shape[0]);
Fdct(shape[1]);
Fdct(shape[2]);
YCoeff[0] = quant_ydc(shape[0][0] >> 3) >> 1;
CbCoeff[0] = quant_cdc(shape[1][0] >> 3);
CrCoeff[0] = quant_cdc(shape[2][0] >> 3);
//quantization and zig-zagging
for (int i = 1; i < 64; i++) {
YCoeff[i] = quant_ac((shape[0][(arrayZigZag[i])]) >> 1) >> 3;
CbCoeff[i] = quant_ac(shape[1][(arrayZigZag[i])]) >> 3;
CrCoeff[i] = quant_ac(shape[2][(arrayZigZag[i])]) >> 3;
}
setYCoeff(YCoeff);
setCbCoeff(CbCoeff);
setCrCoeff(CrCoeff);
return 0;
}
public Element getDescriptor() {
Namespace mpeg7, xsi;
mpeg7 = Namespace.getNamespace("", "urn:mpeg:mpeg7:schema:2001");
xsi = Namespace.getNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");
Element vdesc = new Element("VisualDescriptor", mpeg7).setAttribute("type", "ColorLayoutType", xsi);
// Ersten Werte:
Element ydc, cbdc, crdc;
ydc = new Element("YDCCoeff", mpeg7).addContent(YCoeff[0] + "");
cbdc = new Element("CbDCCoeff", mpeg7).addContent(CbCoeff[0] + "");
crdc = new Element("CrDCCoeff", mpeg7).addContent(CrCoeff[0] + "");
vdesc.addContent(ydc);
vdesc.addContent(cbdc);
vdesc.addContent(crdc);
if (numYCoeff > 1) {
Element yac = new Element("YACCoeff" + (numYCoeff - 1), mpeg7);
StringBuffer b = new StringBuffer();
for (int i = 1; i < numYCoeff; i++) {
b.append(YCoeff[i] + " ");
}
yac.setText(b.toString().trim());
vdesc.addContent(yac);
}
if (numCCoeff > 1) {
Element cbac = new Element("CbACCoeff" + (numCCoeff - 1), mpeg7);
Element crac = new Element("CrACCoeff" + (numCCoeff - 1), mpeg7);
StringBuffer bcb, bcr;
bcb = new StringBuffer();
bcr = new StringBuffer();
for (int i = 1; i < numCCoeff; i++) {
bcb.append(CbCoeff[i] + " ");
bcr.append(CrCoeff[i] + " ");
}
cbac.setText(bcb.toString().trim());
crac.setText(bcr.toString().trim());
vdesc.addContent(cbac);
vdesc.addContent(crac);
}
return vdesc;
}
private void setYCoeff(int[] YCoeff) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -