Skip to content
Snippets Groups Projects
Commit baeb1853 authored by Vojtech Moravec's avatar Vojtech Moravec
Browse files

Remove CodebookEntry class, instead use raw vector.

This simplify the future work, where we need to access raw codebook
vector.
parent 5c1ebdcb
No related branches found
No related tags found
No related merge requests found
Showing with 63 additions and 131 deletions
package azgracompress.cache;
import azgracompress.quantization.vector.CodebookEntry;
import azgracompress.quantization.vector.VQCodebook;
import java.io.DataInputStream;
......@@ -23,9 +22,9 @@ public class VQCacheFile implements ICacheFile {
public void writeToStream(DataOutputStream outputStream) throws IOException {
header.writeToStream(outputStream);
final CodebookEntry[] entries = codebook.getVectors();
for (final CodebookEntry entry : entries) {
for (final int vectorValue : entry.getVector()) {
final int[][] entries = codebook.getVectors();
for (final int[] entry : entries) {
for (final int vectorValue : entry) {
outputStream.writeShort(vectorValue);
}
}
......@@ -45,16 +44,16 @@ public class VQCacheFile implements ICacheFile {
@Override
public void readFromStream(DataInputStream inputStream, CacheFileHeader header) throws IOException {
final int codebookSize = header.getCodebookSize();
final CodebookEntry[] vectors = new CodebookEntry[codebookSize];
final long[] frequencies = new long[codebookSize];
final int entrySize = header.getVectorSizeX() * header.getVectorSizeY() * header.getVectorSizeZ();
final int[][] vectors = new int[codebookSize][entrySize];
final long[] frequencies = new long[codebookSize];
for (int i = 0; i < codebookSize; i++) {
int[] vector = new int[entrySize];
//int[] vector = new int[entrySize];
for (int j = 0; j < entrySize; j++) {
vector[j] = inputStream.readUnsignedShort();
vectors[i][j] = inputStream.readUnsignedShort();
}
vectors[i] = new CodebookEntry(vector);
}
for (int i = 0; i < codebookSize; i++) {
......@@ -73,10 +72,12 @@ public class VQCacheFile implements ICacheFile {
@Override
public void report(StringBuilder builder) {
final CodebookEntry[] vectors = codebook.getVectors();
for (int i = 0; i < vectors.length; i++) {
final int[][] vectors = codebook.getVectors();
for (int[] vector : vectors) {
builder.append("- - - - - - - - - - - - - - - - - - - - - - - - -\n");
vectors[i].getVectorString(builder);
for (final int x : vector) {
builder.append(x).append(';');
}
}
}
}
......@@ -47,11 +47,10 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm
*/
private void writeQuantizerToCompressStream(final VectorQuantizer quantizer,
DataOutputStream compressStream) throws ImageCompressionException {
final CodebookEntry[] codebook = quantizer.getCodebookVectors();
final int[][] codebook = quantizer.getCodebookVectors();
try {
for (final CodebookEntry entry : codebook) {
final int[] entryVector = entry.getVector();
for (final int vecVal : entryVector) {
for (final int[] entry : codebook) {
for (final int vecVal : entry) {
compressStream.writeShort(vecVal);
}
}
......@@ -160,7 +159,7 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm
assert (quantizer != null);
// Use BestBinFirst KDTree for codebook lookup.
// final int[] indices = quantizer.quantizeIntoIndicesUsingKDTree(planeVectors, options.getWorkerCount());
// final int[] indices = quantizer.quantizeIntoIndicesUsingKDTree(planeVectors, options.getWorkerCount());
// Use BruteForce for codebook lookup.
final int[] indices = quantizer.quantizeIntoIndices(planeVectors, options.getWorkerCount());
......
......@@ -7,7 +7,6 @@ import azgracompress.fileformat.QuantizationType;
import azgracompress.huffman.Huffman;
import azgracompress.huffman.HuffmanNode;
import azgracompress.io.InBitStream;
import azgracompress.quantization.vector.CodebookEntry;
import azgracompress.quantization.vector.VQCodebook;
import azgracompress.utilities.Stopwatch;
import azgracompress.utilities.TypeConverter;
......@@ -48,15 +47,14 @@ public class VQImageDecompressor extends CompressorDecompressorBase implements I
final int codebookSize,
final int vectorSize) throws ImageDecompressionException {
final CodebookEntry[] codebookVectors = new CodebookEntry[codebookSize];
final int[][] codebookVectors = new int[codebookSize][vectorSize];
final long[] frequencies = new long[codebookSize];
try {
for (int codebookIndex = 0; codebookIndex < codebookSize; codebookIndex++) {
final int[] vector = new int[vectorSize];
// final int[] vector = new int[vectorSize];
for (int vecIndex = 0; vecIndex < vectorSize; vecIndex++) {
vector[vecIndex] = compressedStream.readUnsignedShort();
codebookVectors[codebookIndex][vecIndex] = compressedStream.readUnsignedShort();
}
codebookVectors[codebookIndex] = new CodebookEntry(vector);
}
for (int codebookIndex = 0; codebookIndex < codebookSize; codebookIndex++) {
frequencies[codebookIndex] = compressedStream.readLong();
......@@ -166,7 +164,7 @@ public class VQImageDecompressor extends CompressorDecompressorBase implements I
bit = inBitStream.readBit();
currentHuffmanNode = currentHuffmanNode.traverse(bit);
}
System.arraycopy(codebook.getVectors()[currentHuffmanNode.getSymbol()].getVector(),
System.arraycopy(codebook.getVectors()[currentHuffmanNode.getSymbol()],
0, decompressedVectors[vecIndex], 0, vectorSize);
}
......@@ -239,7 +237,7 @@ public class VQImageDecompressor extends CompressorDecompressorBase implements I
for (int voxelIndex = 0; voxelIndex < voxelLayerVoxelCount; voxelIndex++) {
final int huffmanSymbol = decodeHuffmanSymbol(huffman, inBitStream);
System.arraycopy(codebook.getVectors()[huffmanSymbol].getVector(), 0, decompressedVoxels[voxelIndex], 0, vectorSize);
System.arraycopy(codebook.getVectors()[huffmanSymbol], 0, decompressedVoxels[voxelIndex], 0, vectorSize);
}
} catch (Exception e) {
......
package azgracompress.quantization.vector;
public class CodebookEntry {
final int[] vector;
final int width;
final int height;
public CodebookEntry(final int[] codebook) {
this.vector = codebook;
this.width = codebook.length;
this.height = 1;
}
@Override
public boolean equals(final Object obj) {
if (obj instanceof CodebookEntry) {
final CodebookEntry ceObj = (CodebookEntry) obj;
if (vector.length != ceObj.vector.length) {
return false;
}
for (int i = 0; i < vector.length; i++) {
if (vector[i] != ceObj.vector[i]) {
return false;
}
}
return true;
}
return super.equals(obj);
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public int[] getVector() {
return vector;
}
public String getVectorString(StringBuilder sb) {
for (int i = 0; i < vector.length; i++) {
sb.append(vector[i]);
if (i != (vector.length - 1))
sb.append(';');
}
sb.append('\n');
return sb.toString();
}
public String getVectorString() {
return getVectorString(new StringBuilder());
}
}
......@@ -4,14 +4,14 @@ import azgracompress.data.V3i;
public class LBGResult {
private final CodebookEntry[] codebookVectors;
private final int[][] codebookVectors;
private final long[] frequencies;
private final double averageMse;
private final double psnr;
private final V3i vectorDims;
public LBGResult(final V3i vectorDims,
final CodebookEntry[] codebook,
final int[][] codebook,
final long[] frequencies,
final double averageMse,
final double psnr) {
......
......@@ -92,13 +92,12 @@ public class LBGVectorQuantizer {
assert (uniqueTrainingVectors != null) : "uniqueTrainingVectors aren't initialized.";
reportStatus("There is only %d unique vectors. Creating codebook from unique vectors...",
uniqueTrainingVectors.size());
CodebookEntry[] codebook = new CodebookEntry[codebookSize];
int[] zeros = new int[vectorSize];
Arrays.fill(zeros, 0);
CodebookEntry zeroEntry = new CodebookEntry(zeros);
final int[][] codebook = new int[codebookSize][vectorSize];
int[] zeroEntry = new int[vectorSize];
Arrays.fill(zeroEntry, 0);
for (int i = 0; i < codebookSize; i++) {
if (i < uniqueVectorCount) {
codebook[i] = new CodebookEntry(uniqueTrainingVectors.get(i).getVector());
codebook[i] = uniqueTrainingVectors.get(i).getVector();
} else {
codebook[i] = zeroEntry;
}
......@@ -141,10 +140,10 @@ public class LBGVectorQuantizer {
* @param learningCodebook Source array of LearningCodebookEntry.
* @return Array of CodebookEntries.
*/
private CodebookEntry[] learningCodebookToCodebook(final LearningCodebookEntry[] learningCodebook) {
CodebookEntry[] codebook = new CodebookEntry[learningCodebook.length];
private int[][] learningCodebookToCodebook(final LearningCodebookEntry[] learningCodebook) {
final int[][] codebook = new int[learningCodebook.length][vectorSize];
for (int i = 0; i < codebook.length; i++) {
codebook[i] = new CodebookEntry(learningCodebook[i].getVector());
codebook[i] = learningCodebook[i].getVector();
}
return codebook;
}
......@@ -168,14 +167,17 @@ public class LBGVectorQuantizer {
}
}
private double averageMse(final LearningCodebookEntry[] codebook) {
return averageMse(learningCodebookToCodebook(codebook));
}
/**
* Calculate the average mean square error of the codebook.
*
* @param codebook Codebook of vectors.
* @return Mean square error.
*/
private double averageMse(final CodebookEntry[] codebook) {
Stopwatch s = Stopwatch.startNew("averageMse");
private double averageMse(final int[][] codebook) {
double mse = 0.0;
resetFrequencies();
if (workerCount > 1) {
......@@ -202,7 +204,8 @@ public class LBGVectorQuantizer {
qIndex = quantizer.quantizeToIndex(vector);
++workerFrequencies[qIndex];
qVector = quantizer.getCodebookVectors()[qIndex].getVector();
qVector = quantizer.getCodebookVectors()[qIndex];
for (int vI = 0; vI < vectorSize; vI++) {
threadMse += Math.pow(((double) vector[vI] - (double) qVector[vI]), 2);
}
......@@ -233,7 +236,7 @@ public class LBGVectorQuantizer {
int[] qVector;
for (final TrainingVector trV : trainingVectors) {
qIndex = quantizer.quantizeToIndex(trV.getVector());
qVector = quantizer.getCodebookVectors()[qIndex].getVector();
qVector = quantizer.getCodebookVectors()[qIndex];
++frequencies[qIndex];
for (int i = 0; i < vectorSize; i++) {
mse += Math.pow(((double) trV.getVector()[i] - (double) qVector[i]), 2);
......@@ -241,10 +244,6 @@ public class LBGVectorQuantizer {
}
mse /= (double) trainingVectors.length;
}
s.stop();
// if (this.verbose) {
//// System.out.println(s);
// }
return mse;
}
......
package azgracompress.quantization.vector;
public class LearningCodebookEntry extends CodebookEntry {
public class LearningCodebookEntry {
private final int[] codebookVector;
private int vectorCount = -1;
private double averageDistortion = -1.0f;
private double[] perturbationVector;
public LearningCodebookEntry(int[] codebook) {
super(codebook);
public LearningCodebookEntry(int[] codebookVector) {
this.codebookVector = codebookVector;
}
/**
* Set codebook entry properties from helper object.
*
* @param info Helper object with property informations.
* @param info Helper object with property information.
*/
public void setInfo(final EntryInfo info) {
this.vectorCount = info.vectorCount;
this.averageDistortion = info.calculateAverageDistortion();
final int[] newCentroid = info.calculateCentroid();
assert (newCentroid.length == vector.length);
System.arraycopy(newCentroid, 0, this.vector, 0, newCentroid.length);
assert (newCentroid.length == codebookVector.length);
System.arraycopy(newCentroid, 0, this.codebookVector, 0, newCentroid.length);
this.perturbationVector = info.calculatePRTVector();
}
public int[] getVector() {
return codebookVector;
}
/**
* Get perturbation vector for splitting this entry.
*
......
......@@ -9,7 +9,7 @@ public class VQCodebook {
/**
* Quantization vectors.
*/
private final CodebookEntry[] vectors;
private final int[][] vectors;
/**
* Absolute frequencies of quantization vectors.
......@@ -26,7 +26,7 @@ public class VQCodebook {
*/
private final V3i vectorDims;
public VQCodebook(final V3i vectorDims, final CodebookEntry[] vectors, final long[] vectorFrequencies) {
public VQCodebook(final V3i vectorDims, final int[][] vectors, final long[] vectorFrequencies) {
//assert (vectors.length == vectorFrequencies.length);
this.vectorDims = vectorDims;
this.vectors = vectors;
......@@ -39,20 +39,10 @@ public class VQCodebook {
*
* @return Quantization vectors.
*/
public CodebookEntry[] getVectors() {
public int[][] getVectors() {
return vectors;
}
public int[][] getRawVectors() {
assert (codebookSize == vectors.length);
assert (vectors[0].getVector().length == (int) vectorDims.multiplyTogether());
final int[][] rawCodebook = new int[vectors.length][(int) vectorDims.multiplyTogether()];
for (int i = 0; i < codebookSize; i++) {
rawCodebook[i] = vectors[i].getVector();
}
return rawCodebook;
}
/**
* Get frequencies of codebook vectors at indices.
*
......
......@@ -11,7 +11,7 @@ public class VectorQuantizer {
}
private final VectorDistanceMetric metric = VectorDistanceMetric.Euclidean;
private final CodebookEntry[] codebookVectors;
private final int[][] codebookVectors;
private final int vectorSize;
private final long[] frequencies;
......@@ -19,16 +19,15 @@ public class VectorQuantizer {
public VectorQuantizer(final VQCodebook codebook) {
this.codebookVectors = codebook.getVectors();
this.vectorSize = codebookVectors[0].getVector().length;
this.vectorSize = codebook.getVectors()[0].length;
this.frequencies = codebook.getVectorFrequencies();
kdTree = new KDTreeBuilder(this.vectorSize, 8).buildTree(codebook.getRawVectors());
kdTree = new KDTreeBuilder(this.vectorSize, 8).buildTree(codebook.getVectors());
}
public int[] quantize(final int[] dataVector) {
assert (dataVector.length > 0 && dataVector.length % vectorSize == 0) : "Wrong vector size";
final CodebookEntry closestEntry = findClosestCodebookEntry(dataVector, metric);
return closestEntry.getVector();
return findClosestCodebookEntry(dataVector, metric);
}
public int quantizeToIndex(final int[] dataVector) {
......@@ -42,13 +41,12 @@ public class VectorQuantizer {
if (workerCount == 1) {
for (int vectorIndex = 0; vectorIndex < dataVectors.length; vectorIndex++) {
final CodebookEntry closestEntry = findClosestCodebookEntry(dataVectors[vectorIndex], metric);
result[vectorIndex] = closestEntry.getVector();
result[vectorIndex] = findClosestCodebookEntry(dataVectors[vectorIndex], metric);
}
} else {
final int[] indices = quantizeIntoIndices(dataVectors, workerCount);
for (int i = 0; i < dataVectors.length; i++) {
result[i] = codebookVectors[indices[i]].getVector();
result[i] = codebookVectors[indices[i]];
}
}
......@@ -142,11 +140,11 @@ public class VectorQuantizer {
return 0.0;
}
private CodebookEntry findClosestCodebookEntry(final int[] dataVector) {
private int[] findClosestCodebookEntry(final int[] dataVector) {
return findClosestCodebookEntry(dataVector, metric);
}
private CodebookEntry findClosestCodebookEntry(final int[] dataVector, final VectorDistanceMetric metric) {
private int[] findClosestCodebookEntry(final int[] dataVector, final VectorDistanceMetric metric) {
return codebookVectors[findClosestCodebookEntryIndex(dataVector, metric)];
}
......@@ -156,7 +154,7 @@ public class VectorQuantizer {
for (int entryIndex = 0; entryIndex < codebookVectors.length; entryIndex++) {
final double dist = distanceBetweenVectors(dataVector, codebookVectors[entryIndex].getVector(), metric);
final double dist = distanceBetweenVectors(dataVector, codebookVectors[entryIndex], metric);
if (dist < minDist) {
minDist = dist;
closestEntryIndex = entryIndex;
......@@ -166,7 +164,7 @@ public class VectorQuantizer {
return closestEntryIndex;
}
public CodebookEntry[] getCodebookVectors() {
public int[][] getCodebookVectors() {
return codebookVectors;
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment