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