package edu.berkeley.cs.nlp.ocular.preprocessing;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FilenameFilter;
import java.util.Arrays;
import java.util.List;
import edu.berkeley.cs.nlp.ocular.image.ImageUtils;
import edu.berkeley.cs.nlp.ocular.image.ImageUtils.ConnectedComponentProcessor;
import tberg.murphy.fileio.f;
/**
* @author Taylor Berg-Kirkpatrick (tberg@eecs.berkeley.edu)
*/
public class Straightener {
private static final double MIN_ANGLE_RADIANS = -0.05;
private static final double MAX_ANGLE_RADIANS = 0.05;
private static final int ANGLE_SAMPLE_POINTS = 20;
public static double[][] straighten(double[][] levels) {
BufferedImage image = ImageUtils.makeImage(levels);
double maxTotalVar = Double.NEGATIVE_INFINITY;
double bestAngle = Double.NEGATIVE_INFINITY;
for (int i=0; i<ANGLE_SAMPLE_POINTS; ++i) {
double angle = MIN_ANGLE_RADIANS + ((double) i / (ANGLE_SAMPLE_POINTS-1)) * (MAX_ANGLE_RADIANS - MIN_ANGLE_RADIANS);
double[][] rotLevels = ImageUtils.getLevels(ImageUtils.rotateImage(image, angle));
double totalVar = verticalTotalVariation(rotLevels);
// System.out.println("angle: "+angle+", total var: "+totalVar);
if (totalVar > maxTotalVar) {
maxTotalVar = totalVar;
bestAngle = angle;
}
}
return ImageUtils.getLevels(ImageUtils.rotateImage(ImageUtils.makeImage(levels), bestAngle));
}
private static double verticalTotalVariation(double[][] levels) {
double[] horizontalAvg = new double[levels[0].length];
for (int i=0; i<levels.length; ++i) {
for (int j=0; j<levels[0].length; ++j) {
horizontalAvg[j] += levels[i][j] / levels.length;
}
}
double totalVar = 0;
for (int j=1; j<levels[0].length; ++j) {
totalVar += Math.abs(horizontalAvg[j] - horizontalAvg[j-1]);
}
return totalVar / (levels[0].length-1);
}
public static void main(String[] args) {
String path = args[0];
double binarizeThresh = 0.1;
if (args.length > 1) {
binarizeThresh = Double.parseDouble(args[1]);
}
File dir = new File(path);
String[] names = dir.list(new FilenameFilter() {
public boolean accept(File dir, String name) {
return name.endsWith(".png") || name.endsWith(".jpg");
}
});
Arrays.sort(names);
File straightDir = new File(path + "/straight");
straightDir.mkdirs();
for (String name : names) {
double[][] levels = ImageUtils.getLevels(f.readImage(path+"/"+name));
ConnectedComponentProcessor ccprocBig = new ConnectedComponentProcessor() {
public void process(double[][] levels, List<int[]> connectedComponent) {
if (connectedComponent.size() > 1000) {
for (int[] pixel : connectedComponent) {
levels[pixel[0]][pixel[1]] = 255.0;
}
}
}
};
ImageUtils.processConnectedComponents(levels, 50.0, ccprocBig);
Binarizer.binarizeGlobal(binarizeThresh, levels);
ConnectedComponentProcessor ccprocSmall = new ConnectedComponentProcessor() {
public void process(double[][] levels, List<int[]> connectedComponent) {
if (connectedComponent.size() < 20 || connectedComponent.size() > 500) {
for (int[] pixel : connectedComponent) {
levels[pixel[0]][pixel[1]] = 255.0;
}
}
}
};
ImageUtils.processConnectedComponents(levels, 127.0, ccprocSmall);
double[][] rotLevels = Straightener.straighten(levels);
String baseName = (name.lastIndexOf('.') == -1) ? name : name.substring(0, name.lastIndexOf('.'));
f.writeImage(straightDir.getAbsolutePath() +"/"+ baseName + ".png", ImageUtils.makeImage(rotLevels));
}
}
}