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

As in LloydMax change logging logic to listener.

Also cleaned the log messages.
parent ba983b54
No related branches found
No related tags found
No related merge requests found
......@@ -67,7 +67,7 @@ public class CompressionOptions {
this.workerCount = (cores / 2);
}
protected void setVerbose(boolean verbose) {
public void setVerbose(boolean verbose) {
this.verbose = verbose;
}
......
......@@ -32,7 +32,7 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm
getCodebookSize(),
options.getWorkerCount(),
options.getVectorDimension().toV3i());
LBGResult vqResult = vqInitializer.findOptimalCodebook(false);
LBGResult vqResult = vqInitializer.findOptimalCodebook();
return new VectorQuantizer(vqResult.getCodebook());
}
......@@ -255,7 +255,8 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm
options.getWorkerCount(),
options.getVectorDimension().toV3i());
reportStatusToListeners("Starting LBG optimization.");
LBGResult lbgResult = vqInitializer.findOptimalCodebook(options.isVerbose());
vqInitializer.setStatusListener(this::reportStatusToListeners);
LBGResult lbgResult = vqInitializer.findOptimalCodebook();
reportStatusToListeners("Learned the optimal codebook.");
......
package azgracompress.quantization.vector;
import azgracompress.U16;
import azgracompress.compression.listeners.IStatusListener;
import azgracompress.data.V3i;
import azgracompress.utilities.Stopwatch;
import azgracompress.utilities.Utils;
......@@ -24,7 +25,7 @@ public class LBGVectorQuantizer {
private long[] frequencies;
boolean verbose = false;
private IStatusListener statusListener = null;
private double _mse = 0.0;
public LBGVectorQuantizer(final int[][] vectors,
......@@ -49,6 +50,19 @@ public class LBGVectorQuantizer {
findUniqueVectors();
}
public void setStatusListener(final IStatusListener statusListener) {
this.statusListener = statusListener;
}
private void reportStatus(final String message) {
if (statusListener != null)
statusListener.sendMessage(message);
}
private void reportStatus(final String format, final Object... arg) {
reportStatus(String.format(format, arg));
}
private void findUniqueVectors() {
uniqueVectorCount = 0;
uniqueTrainingVectors = new ArrayList<>(codebookSize);
......@@ -74,10 +88,10 @@ public class LBGVectorQuantizer {
}
private LBGResult createCodebookFromUniqueVectors() {
assert (uniqueTrainingVectors != null) : "uniqueTrainingVectors aren't initialized.";
if (verbose) {
System.out.println("Creating codebook from unique vectors.");
}
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);
......@@ -91,9 +105,7 @@ public class LBGVectorQuantizer {
}
final double mse = averageMse(codebook);
final double psnr = Utils.calculatePsnr(mse, U16.Max);
if (verbose) {
System.out.println(String.format("Final MSE: %.4f\nFinal PSNR: %.4f (dB)", mse, psnr));
}
reportStatus("Unique vector codebook, MSE: %f PSNR: %f(dB)", mse, psnr);
return new LBGResult(vectorDimensions, codebook, frequencies, mse, psnr);
}
......@@ -103,40 +115,23 @@ public class LBGVectorQuantizer {
* @return Result of the search.
*/
public LBGResult findOptimalCodebook() {
return findOptimalCodebook(false);
}
/**
* Find the optimal codebook of vectors, used for vector quantization.
*
* @param isVerbose True if program algorithm should be verbose.
* @return Result of the search.
*/
public LBGResult findOptimalCodebook(boolean isVerbose) {
Stopwatch stopwatch = Stopwatch.startNew("findOptimalCodebook");
this.verbose = isVerbose;
Stopwatch stopwatch = Stopwatch.startNew("LBG::findOptimalCodebook()");
if (uniqueVectorCount < codebookSize) {
return createCodebookFromUniqueVectors();
}
LearningCodebookEntry[] codebook = initializeCodebook();
if (verbose) {
System.out.println("Got initial codebook. Improving codebook...");
}
reportStatus("LBG::findOptimalCodebook() - Got initial codebook. Improving it...");
LBG(codebook, EPSILON * 0.1);
final double finalMse = averageMse(codebook);
final double psnr = Utils.calculatePsnr(finalMse, U16.Max);
if (verbose) {
System.out.println(String.format("Improved codebook, final average MSE: %.4f PSNR: %.4f (dB)",
reportStatus("LBG::findOptimalCodebook() - Improved the codebook. Final MSE: %f PSNR: %f (dB)",
finalMse,
psnr));
}
psnr);
stopwatch.stop();
if (verbose) {
System.out.println(stopwatch);
}
reportStatus(stopwatch.toString());
return new LBGResult(vectorDimensions, learningCodebookToCodebook(codebook), frequencies, finalMse, psnr);
}
......@@ -384,22 +379,17 @@ public class LBGVectorQuantizer {
}
codebook = newCodebook;
assert (codebook.length == (currentCodebookSize * 2));
if (verbose) {
System.out.println(String.format("Split from %d -> %d", currentCodebookSize, currentCodebookSize * 2));
}
reportStatus("LBG::initializeCodebook() - Dividing codebook from %d --> %d",
currentCodebookSize,
2 * currentCodebookSize);
currentCodebookSize *= 2;
// Execute LBG Algorithm on current codebook to improve it.
if (verbose) {
System.out.println("Improving current codebook...");
}
LBG(codebook);
final double avgMse = averageMse(codebook);
if (verbose) {
System.out.println(String.format("Average MSE: %.4f", avgMse));
}
reportStatus("MSE of improved divided codebook: %f", avgMse);
}
return codebook;
}
......@@ -463,32 +453,26 @@ public class LBGVectorQuantizer {
avgDistortion /= codebook.length;
// Calculate distortion
double dist = (previousDistortion - avgDistortion) / avgDistortion;
if (verbose) {
System.out.println(String.format("---- It: %d Distortion: %.5f", iteration++, dist));
System.out.println(String.format("Last Dist: %.5f Current dist: %.5f", lastDist, dist));
}
double distortion = (previousDistortion - avgDistortion) / avgDistortion;
reportStatus("LBG::LBG() - Iteration: %d Distortion: %.5f", iteration++, distortion);
if (Double.isNaN(dist)) {
if (verbose) {
System.out.println("Distortion is NaN.");
}
if (Double.isNaN(distortion)) {
reportStatus("Distortion is NaN. Stopping LBG::LBG().");
break;
}
if (dist > lastDist) {
if (verbose) {
System.out.println("Previous distortion was better. Ending LBG...");
}
if (distortion > lastDist) {
reportStatus("Previous distortion was better. Stopping LBG::LBG().");
break;
}
// Check distortion against epsilon
if (dist < epsilon) {
if (distortion < epsilon) {
break;
} else {
previousDistortion = avgDistortion;
lastDist = dist;
lastDist = distortion;
}
}
}
......@@ -665,7 +649,6 @@ public class LBGVectorQuantizer {
*/
private void calculateEntryProperties(LearningCodebookEntry[] codebook) {
Stopwatch stopwatch = Stopwatch.startNew("calculateEntryProperties");
int value;
EntryInfo[] entryInfos = new EntryInfo[codebook.length];
for (int i = 0; i < entryInfos.length; i++) {
......@@ -695,10 +678,6 @@ public class LBGVectorQuantizer {
for (int i = 0; i < codebook.length; i++) {
codebook[i].setInfo(entryInfos[i]);
}
stopwatch.stop();
if (this.verbose) {
System.out.println(stopwatch);
}
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment