/*******************************************************************************
* Copyright 2014 Analog Devices, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
********************************************************************************/
package com.analog.lyric.dimple.benchmarks.imageDenoising;
import static com.analog.lyric.benchmarking.utils.doublespace.IndexerFactory.*;
import java.io.IOException;
import java.net.URL;
import com.analog.lyric.benchmarking.Benchmark;
import com.analog.lyric.benchmarking.utils.doublespace.DoubleSpace;
import com.analog.lyric.benchmarking.utils.doublespace.DoubleSpaceFactory;
import com.analog.lyric.benchmarking.utils.functional.Functions;
import com.analog.lyric.benchmarking.utils.functional.NoiseGenerator;
import com.analog.lyric.benchmarking.utils.functional.Threshold;
import com.analog.lyric.benchmarking.utils.functional.TransformFunction;
import com.analog.lyric.dimple.benchmarks.utils.Image;
import com.analog.lyric.dimple.model.core.FactorGraph;
import com.analog.lyric.dimple.options.BPOptions;
import com.analog.lyric.dimple.solvers.gibbs.GibbsSolver;
import com.analog.lyric.dimple.solvers.optimizedupdate.UpdateApproach;
@SuppressWarnings({"null", "deprecation"})
public class ImageDenoisingBenchmark
{
private final boolean saveResult = false;
@Benchmark(warmupIterations = 0, iterations = 1)
public boolean imageDenoisingGibbs()
{
FactorGraph fg = new FactorGraph();
fg.setSolverFactory(new GibbsSolver());
fg.setOption(BPOptions.iterations, 1600);
int imageDimension = 100;
int xImageOffset = 800;
int yImageOffset = 1925;
int xImageSize = imageDimension;
int yImageSize = imageDimension;
double noiseSigma = 1.0;
imageDenoisingInference(fg, "images/1202.4002.3.png", "gibbs", imageDimension, xImageOffset, yImageOffset, xImageSize,
yImageSize, noiseSigma);
return false;
}
@Benchmark(warmupIterations = 0, iterations = 1)
public boolean imageDenoisingSumProduct()
{
FactorGraph fg = new FactorGraph();
fg.setSolverFactory(new com.analog.lyric.dimple.solvers.sumproduct.Solver());
fg.setOption(BPOptions.iterations, 1);
// This is the automatic setting, but making it explicit ensures that the benchmark will not change
fg.setOption(BPOptions.updateApproach, UpdateApproach.OPTIMIZED);
int imageDimension = 100;
int xImageOffset = 800;
int yImageOffset = 1925;
int xImageSize = imageDimension;
int yImageSize = imageDimension;
double noiseSigma = 1.0;
imageDenoisingInference(fg, "images/1202.4002.3.png", "sumproduct", imageDimension, xImageOffset, yImageOffset, xImageSize,
yImageSize, noiseSigma);
return false;
}
@Benchmark(warmupIterations = 0, iterations = 1)
public boolean imageDenoisingMinSum()
{
FactorGraph fg = new FactorGraph();
fg.setSolverFactory(new com.analog.lyric.dimple.solvers.minsum.Solver());
fg.setOption(BPOptions.iterations, 2);
// This is the automatic setting, but making it explicit ensures that the benchmark will not change
fg.setOption(BPOptions.updateApproach, UpdateApproach.OPTIMIZED);
int imageDimension = 100;
int xImageOffset = 800;
int yImageOffset = 1925;
int xImageSize = imageDimension;
int yImageSize = imageDimension;
double noiseSigma = 1.0;
imageDenoisingInference(fg, "images/1202.4002.3.png", "minsum", imageDimension, xImageOffset, yImageOffset, xImageSize,
yImageSize, noiseSigma);
return false;
}
@SuppressWarnings("unused")
public void imageDenoisingInference(FactorGraph fg, String imageFileName, String saveLabel, int imageDimension,
int xImageOffset, int yImageOffset, int xImageSize, int yImageSize, double noiseSigma)
{
try
{
final String factorFileName = "imageStats/factorTableValues300dpi.csv";
final int xBlockSize = 4;
final int yBlockSize = 4;
URL urlImage = this.getClass().getResource(imageFileName);
DoubleSpace likelihoods = noisyImageInput(urlImage, noiseSigma, xImageOffset, yImageOffset, xImageSize, yImageSize);
ImageDenoisingGraph imageDenoisingGraph = new ImageDenoisingGraph(fg, factorFileName, xImageSize, yImageSize, xBlockSize,
yBlockSize);
imageDenoisingGraph.setInput(likelihoods);
fg.solve();
if (saveResult && saveLabel != null)
{
DoubleSpace output = imageDenoisingGraph.getValue();
Functions.normalize(output).transform(Image.contrastCurve);
String resultPath = String.format("denoise_%s.png", saveLabel);
Image.save(resultPath, output);
}
double score = fg.getScore();
}
catch (IOException ex)
{
throw new RuntimeException(ex);
}
}
private DoubleSpace noisyImageInput(URL urlImage, double noiseSigma, int xImageOffset, int yImageOffset, int xImageSize,
int yImageSize) throws IOException
{
DoubleSpace image = Image.loadImage(urlImage);
image = image.view(range(yImageOffset, yImageOffset + yImageSize - 1), range(xImageOffset, xImageOffset + xImageSize - 1));
image.transform(new Threshold(128));
image.transform(new TransformFunction()
{
@Override
public double apply(double v)
{
return v * 2.0 - 1.0;
}
});
DoubleSpace noiseImage = DoubleSpaceFactory.generate(new NoiseGenerator(0.0, noiseSigma), yImageSize, xImageSize);
image.add(noiseImage);
final double noiseVariance = Math.pow(noiseSigma, 2.0);
image.transform(new TransformFunction()
{
// LLR
@Override
public double apply(double v)
{
return -2.0 * v / noiseVariance;
}
});
image.transform(new TransformFunction()
{
// likelihood
@Override
public double apply(double v)
{
return 1.0 / (1.0 + Math.exp(v));
}
});
return image;
}
}