package edu.berkeley.cs.nlp.ocular.preprocessing;
import java.io.File;
import java.io.FilenameFilter;
import java.util.ArrayList;
import java.util.List;
import edu.berkeley.cs.nlp.ocular.image.ImageUtils;
import edu.berkeley.cs.nlp.ocular.image.ImageUtils.ConnectedComponentProcessor;
import edu.berkeley.cs.nlp.ocular.preprocessing.VerticalProfile.VerticalSegmentation;
import tberg.murphy.fileio.f;
import tberg.murphy.tuple.Pair;
/**
* @author Taylor Berg-Kirkpatrick (tberg@eecs.berkeley.edu)
*/
public class LineExtractor {
public static List<double[][]> extractLines(double[][] levels) {
VerticalProfile verticalProfile = new VerticalProfile(levels);
VerticalModel trainedModel = verticalProfile.runEM(5, 100);
// trainedModel.freezeSizeParams(1);
VerticalSegmentation viterbiSegments = verticalProfile.decode(trainedModel);
// ImageUtils.display(Visualizer.renderLineExtraction(levels, viterbiSegments));
List<double[][]> result = new ArrayList<double[][]>();
int topDist = 29;
int botDist = 11;
List<Pair<Integer,Integer>> segments = viterbiSegments.retrieveLineBoundaries();
List<Integer> baselines = viterbiSegments.retrieveBaselines();
for (int s=0; s<baselines.size(); ++s) {
int base = baselines.get(s);
int upper = segments.get(s).getFirst();
int lower = segments.get(s).getSecond();
double[][] line = new double[levels.length][topDist+botDist];
for (int t=0; t<topDist; ++t) {
for (int x = 0; x < levels.length; x++) {
int pos = base+(t-topDist);
if (pos < 0 || pos >= levels[0].length){
// if (pos < 0 || pos >= levels[0].length || pos < upper-5 || pos >= lower+5){
line[x][t] = ImageUtils.MAX_LEVEL;
} else {
line[x][t] = levels[x][pos];
}
}
}
for (int b=0; b<botDist; ++b) {
for (int x = 0; x < levels.length; x++) {
int pos = base+b;
if (pos < 0 || pos >= levels[0].length){
// if (pos < 0 || pos >= levels[0].length || pos < upper-5 || pos >= lower+5){
line[x][topDist+b] = ImageUtils.MAX_LEVEL;
} else {
line[x][topDist+b] = levels[x][pos];
}
}
}
result.add(line);
}
// List<Pair<Integer,Integer>> lineBoundaries = viterbiSegments.retrieveLineBoundaries();
// for (Pair<Integer,Integer> boundary : lineBoundaries) {
// double[][] line = new double[levels.length][boundary.getSecond().intValue() - boundary.getFirst().intValue()];
// for (int y = boundary.getFirst().intValue(); y < boundary.getSecond().intValue(); y++) {
// for (int x = 0; x < levels.length; x++) {
// line[x][y-boundary.getFirst()] = levels[x][y];
// }
// }
// result.add(line);
// }
System.out.println("Extractor returned " + result.size() + " line images");
return result;
}
public static void main(String[] args) {
String path = "/Users/tberg/Desktop/F-tem/seg_extraction/";
File dir = new File(path);
for (String name : dir.list(new FilenameFilter() {
public boolean accept(File dir, String name) {
return name.endsWith(".png") || name.endsWith(".jpg");
}
})) {
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(0.13, levels);
ConnectedComponentProcessor ccprocSmall = new ConnectedComponentProcessor() {
public void process(double[][] levels, List<int[]> connectedComponent) {
if (connectedComponent.size() < 20 || connectedComponent.size() > 1000) {
for (int[] pixel : connectedComponent) {
levels[pixel[0]][pixel[1]] = 255.0;
}
}
}
};
ImageUtils.processConnectedComponents(levels, 127.0, ccprocSmall);
List<double[][]> lines = extractLines(levels);
for (double[][] line : lines) {
ImageUtils.display(ImageUtils.makeImage(line));
}
}
}
}