use of com.joliciel.jochre.graphics.Shape in project jochre by urieli.
the class ShapeSequence method getRectangleInGroup.
/**
* Return the rectangle enclosing this shape sequence in a particular group.
*/
public Rectangle getRectangleInGroup(GroupOfShapes group) {
boolean haveShapes = false;
RectangleImpl rectangle = new RectangleImpl(Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MIN_VALUE, Integer.MIN_VALUE);
for (ShapeInSequence shapeInSequence : this) {
Shape shape = shapeInSequence.getShape();
if (shape.getGroup().equals(group)) {
haveShapes = true;
if (shape.getLeft() < rectangle.getLeft())
rectangle.setLeft(shape.getLeft());
if (shape.getTop() < rectangle.getTop())
rectangle.setTop(shape.getTop());
if (shape.getRight() > rectangle.getRight())
rectangle.setRight(shape.getRight());
if (shape.getBottom() > rectangle.getBottom())
rectangle.setBottom(shape.getBottom());
}
}
if (!haveShapes)
rectangle = null;
return rectangle;
}
use of com.joliciel.jochre.graphics.Shape in project jochre by urieli.
the class TrainingCorpusShapeSplitter method split.
@Override
public List<ShapeSequence> split(Shape shape) {
List<ShapeSequence> shapeSequences = new ArrayList<ShapeSequence>();
ShapeSequence shapeSequence = new ShapeSequence();
shapeSequences.add(shapeSequence);
Set<String> nonSplittableLetters = jochreSession.getLinguistics().getDualCharacterLetters();
String testLetter = shape.getLetter().replace("|", "");
if (testLetter.length() == 1 || nonSplittableLetters.contains(testLetter)) {
shapeSequence.addShape(shape);
} else {
int lastLeft = 0;
Comparator<Shape> shapeComparator = null;
if (jochreSession.getLinguistics().isLeftToRight())
shapeComparator = new ShapeLeftToRightComparator();
else
shapeComparator = new ShapeRightToLeftComparator();
TreeSet<Shape> splitShapes = new TreeSet<Shape>(shapeComparator);
for (Split split : shape.getSplits()) {
Shape newShape = shape.getJochreImage().getShape(shape.getLeft() + lastLeft, shape.getTop(), shape.getLeft() + split.getPosition(), shape.getBottom());
lastLeft = split.getPosition() + 1;
splitShapes.add(newShape);
}
Shape lastShape = shape.getJochreImage().getShape(shape.getLeft() + lastLeft, shape.getTop(), shape.getRight(), shape.getBottom());
splitShapes.add(lastShape);
List<String> splitLetters = new ArrayList<String>();
char lastChar = 0;
boolean haveSplitLetter = false;
for (int i = 0; i < shape.getLetter().length(); i++) {
char c = shape.getLetter().charAt(i);
if (c == '|')
haveSplitLetter = true;
if (lastChar != 0) {
String doubleChar = "" + lastChar + c;
if (nonSplittableLetters.contains(doubleChar)) {
splitLetters.add(doubleChar);
lastChar = 0;
} else {
splitLetters.add("" + lastChar);
lastChar = c;
}
} else {
lastChar = c;
}
}
if (lastChar != 0)
splitLetters.add("" + lastChar);
if (splitLetters.size() == 0)
splitLetters.add("");
// mean end a split a or start a split b
if (haveSplitLetter) {
int i = 0;
List<String> newSplitLetters = new ArrayList<String>();
boolean inSplit = false;
for (String letter : splitLetters) {
if (letter.equals("|")) {
if (i == 1 && i == splitLetters.size() - 2) {
// smack in the middle - ambiguous split mark
Shape previousShape = null;
Shape nextShape = null;
String previousLetter = splitLetters.get(0);
String nextLetter = splitLetters.get(2);
if (shape.getIndex() > 0) {
previousShape = shape.getGroup().getShapes().get(shape.getIndex() - 1);
}
if (shape.getIndex() < shape.getGroup().getShapes().size() - 1) {
nextShape = shape.getGroup().getShapes().get(shape.getIndex() + 1);
}
boolean backwardsSplit = true;
if (previousShape != null && previousShape.getLetter().equals("|" + previousLetter)) {
backwardsSplit = true;
} else if (nextShape != null && nextShape.getLetter().equals(nextLetter + "|")) {
backwardsSplit = false;
} else if (previousShape != null && previousShape.getLetter().length() == 0) {
backwardsSplit = true;
} else if (nextShape != null && nextShape.getLetter().length() == 0) {
backwardsSplit = false;
} else {
throw new JochreException("Impossible split for shape " + shape.getId() + ": " + previousLetter + "|" + nextLetter);
}
if (backwardsSplit) {
// start split
String letterWithSplit = newSplitLetters.get(0) + "|";
newSplitLetters.remove(0);
newSplitLetters.add(letterWithSplit);
} else {
inSplit = true;
}
} else if (i == 1) {
// start split
String letterWithSplit = newSplitLetters.get(0) + "|";
newSplitLetters.remove(0);
newSplitLetters.add(letterWithSplit);
} else if (i == splitLetters.size() - 2) {
// end split
inSplit = true;
} else {
throw new JochreException("Impossible split location for shape " + shape.getId() + ": " + shape.getLetter());
}
} else if (inSplit) {
newSplitLetters.add("|" + letter);
inSplit = false;
} else {
newSplitLetters.add(letter);
}
i++;
}
splitLetters = newSplitLetters;
}
if (splitLetters.size() != splitShapes.size()) {
throw new JochreException("Cannot have more shapes than letters in shape " + shape.getId() + ": " + shape.getLetter() + ", " + splitLetters);
}
int i = 0;
for (Shape splitShape : splitShapes) {
shapeSequence.addShape(splitShape, shape);
splitShape.setLetter(splitLetters.get(i++));
}
}
return shapeSequences;
}
use of com.joliciel.jochre.graphics.Shape in project jochre by urieli.
the class SplitShapeWidthRatioFeature method checkInternal.
@Override
public FeatureResult<Double> checkInternal(Split split, RuntimeEnvironment env) {
FeatureResult<Double> result = null;
Shape shape = split.getShape();
int rightWidth = (shape.getWidth() - 1) - (split.getPosition() + 1);
int leftWidth = split.getPosition() - 1;
double ratio = (double) leftWidth / (double) rightWidth;
if (ratio > 1)
ratio = 1 / ratio;
result = this.generateResult(ratio);
return result;
}
use of com.joliciel.jochre.graphics.Shape in project jochre by urieli.
the class TrueContourSlopeDifferenceFeature method checkInternal.
@Override
public FeatureResult<Double> checkInternal(Split split, RuntimeEnvironment env) {
FeatureResult<Double> result = null;
FeatureResult<Integer> contourDistanceResult = contourDistanceFeature.check(split, env);
if (contourDistanceResult != null) {
int contourDistance = contourDistanceResult.getOutcome();
int[][] verticalContour = split.getShape().getVerticalContour();
int startX = split.getPosition();
Shape shape = split.getShape();
int topStart = verticalContour[startX][0];
int bottomStart = verticalContour[startX][1];
SimpleRegression topRightRegression = new SimpleRegression();
SimpleRegression bottomRightRegression = new SimpleRegression();
SimpleRegression topLeftRegression = new SimpleRegression();
SimpleRegression bottomLeftRegression = new SimpleRegression();
topRightRegression.addData(startX, topStart);
topLeftRegression.addData(startX, topStart);
bottomRightRegression.addData(startX, bottomStart);
bottomLeftRegression.addData(startX, bottomStart);
int lastTopRight = topStart;
int lastTopLeft = topStart;
int lastBottomRight = bottomStart;
int lastBottomLeft = bottomStart;
for (int i = 1; i <= contourDistance; i++) {
int x = startX + i;
if (x < shape.getWidth()) {
if (shape.isPixelBlack(x, lastTopRight)) {
for (int y = lastTopRight - 1; y >= -1; y--) {
if (y < 0 || !shape.isPixelBlack(x, y)) {
lastTopRight = y + 1;
topRightRegression.addData(x, lastTopRight);
break;
}
}
} else {
for (int y = lastTopRight + 1; y <= shape.getHeight(); y++) {
if (y == shape.getHeight() || shape.isPixelBlack(x, y)) {
lastTopRight = y;
topRightRegression.addData(x, lastTopRight);
break;
}
}
}
if (shape.isPixelBlack(x, lastBottomRight)) {
for (int y = lastBottomRight + 1; y <= shape.getHeight(); y++) {
if (y == shape.getHeight() || !shape.isPixelBlack(x, y)) {
lastBottomRight = y - 1;
bottomRightRegression.addData(x, lastBottomRight);
break;
}
}
} else {
for (int y = lastBottomRight - 1; y >= -1; y--) {
if (y < 0 || shape.isPixelBlack(x, y)) {
lastBottomRight = y;
bottomRightRegression.addData(x, lastBottomRight);
break;
}
}
}
}
x = startX - i;
if (x >= 0) {
if (shape.isPixelBlack(x, lastTopLeft)) {
for (int y = lastTopLeft - 1; y >= -1; y--) {
if (y < 0 || !shape.isPixelBlack(x, y)) {
lastTopLeft = y + 1;
topLeftRegression.addData(x, lastTopLeft);
break;
}
}
} else {
for (int y = lastTopLeft + 1; y <= shape.getHeight(); y++) {
if (y == shape.getHeight() || shape.isPixelBlack(x, y)) {
lastTopLeft = y;
topLeftRegression.addData(x, lastTopLeft);
break;
}
}
}
if (shape.isPixelBlack(x, lastBottomLeft)) {
for (int y = lastBottomLeft + 1; y <= shape.getHeight(); y++) {
if (y == shape.getHeight() || !shape.isPixelBlack(x, y)) {
lastBottomLeft = y - 1;
bottomLeftRegression.addData(x, lastBottomLeft);
break;
}
}
} else {
for (int y = lastBottomLeft - 1; y >= -1; y--) {
if (y < 0 || shape.isPixelBlack(x, y)) {
lastBottomLeft = y;
bottomLeftRegression.addData(x, lastBottomLeft);
break;
}
}
}
}
}
// get the slopes
double topRightSlope = topRightRegression.getSlope();
double bottomRightSlope = bottomRightRegression.getSlope();
double topLeftSlope = topLeftRegression.getSlope();
double bottomLeftSlope = bottomLeftRegression.getSlope();
// convert slopes to angles
double topRightAngle = Math.atan(topRightSlope);
double bottomRightAngle = Math.atan(bottomRightSlope);
double topLeftAngle = Math.atan(topLeftSlope);
double bottomLeftAngle = Math.atan(bottomLeftSlope);
// calculate the right & left-hand differences
double rightDiff = Math.abs(topRightAngle - bottomRightAngle);
double leftDiff = Math.abs(topLeftAngle - bottomLeftAngle);
// normalise the differences from 0 to 1
rightDiff = rightDiff / Math.PI;
leftDiff = leftDiff / Math.PI;
double product = rightDiff * leftDiff;
if (LOG.isTraceEnabled()) {
LOG.trace("topRightAngle: " + topRightAngle);
LOG.trace("bottomRightAngle: " + bottomRightAngle);
LOG.trace("topLeftAngle: " + topLeftAngle);
LOG.trace("bottomLeftAngle: " + bottomLeftAngle);
LOG.trace("rightDiff: " + rightDiff);
LOG.trace("leftDiff: " + leftDiff);
LOG.trace("product: " + product);
}
result = this.generateResult(product);
}
return result;
}
use of com.joliciel.jochre.graphics.Shape in project jochre by urieli.
the class TwoPointSlopeDifferenceFeature method checkInternal.
@Override
public FeatureResult<Double> checkInternal(Split split, RuntimeEnvironment env) {
FeatureResult<Double> result = null;
FeatureResult<Integer> contourDistanceResult = contourDistanceFeature.check(split, env);
if (contourDistanceResult != null) {
int contourDistance = contourDistanceResult.getOutcome();
int[][] verticalContour = split.getShape().getVerticalContour();
int x = split.getPosition();
Shape shape = split.getShape();
int topStart = verticalContour[x][0];
int bottomStart = verticalContour[x][1];
SimpleRegression topRightRegression = new SimpleRegression();
SimpleRegression bottomRightRegression = new SimpleRegression();
SimpleRegression topLeftRegression = new SimpleRegression();
SimpleRegression bottomLeftRegression = new SimpleRegression();
topRightRegression.addData(x, topStart);
topLeftRegression.addData(x, topStart);
bottomRightRegression.addData(x, bottomStart);
bottomLeftRegression.addData(x, bottomStart);
int[] minTopRight = new int[] { x, topStart };
int[] minTopLeft = new int[] { x, topStart };
int[] maxTopRight = new int[] { x, topStart };
int[] maxTopLeft = new int[] { x, topStart };
int[] minBottomRight = new int[] { x, bottomStart };
int[] minBottomLeft = new int[] { x, bottomStart };
int[] maxBottomRight = new int[] { x, bottomStart };
int[] maxBottomLeft = new int[] { x, bottomStart };
for (int i = 1; i <= contourDistance; i++) {
if (x + i < shape.getWidth()) {
if (verticalContour[x + i][0] < minTopRight[1])
minTopRight = new int[] { x + i, verticalContour[x + i][0] };
if (verticalContour[x + i][0] > maxTopRight[1])
maxTopRight = new int[] { x + i, verticalContour[x + i][0] };
if (verticalContour[x + i][1] < minBottomRight[1])
minBottomRight = new int[] { x + i, verticalContour[x + i][1] };
if (verticalContour[x + i][1] > maxBottomRight[1])
maxBottomRight = new int[] { x + i, verticalContour[x + i][1] };
}
if (x - i >= 0) {
if (verticalContour[x - i][0] < minTopLeft[1])
minTopLeft = new int[] { x - i, verticalContour[x - i][0] };
if (verticalContour[x - i][0] > maxTopLeft[1])
maxTopLeft = new int[] { x - i, verticalContour[x - i][0] };
if (verticalContour[x - i][1] < minBottomLeft[1])
minBottomLeft = new int[] { x - i, verticalContour[x - i][1] };
if (verticalContour[x - i][1] > maxBottomLeft[1])
maxBottomLeft = new int[] { x - i, verticalContour[x - i][1] };
}
}
if (minTopRight[0] == x)
topRightRegression.addData(maxTopRight[0], maxTopRight[1]);
else
topRightRegression.addData(minTopRight[0], minTopRight[1]);
if (minTopLeft[0] == x)
topLeftRegression.addData(maxTopLeft[0], maxTopLeft[1]);
else
topLeftRegression.addData(minTopLeft[0], minTopLeft[1]);
if (maxBottomRight[0] == x)
bottomRightRegression.addData(minBottomRight[0], minBottomRight[1]);
else
bottomRightRegression.addData(maxBottomRight[0], maxBottomRight[1]);
if (maxBottomLeft[0] == x)
bottomLeftRegression.addData(minBottomLeft[0], minBottomLeft[1]);
else
bottomLeftRegression.addData(maxBottomLeft[0], maxBottomLeft[1]);
// get the slopes
double topRightSlope = topRightRegression.getSlope();
double bottomRightSlope = bottomRightRegression.getSlope();
double topLeftSlope = topLeftRegression.getSlope();
double bottomLeftSlope = bottomLeftRegression.getSlope();
// convert slopes to angles
double topRightAngle = Math.atan(topRightSlope);
double bottomRightAngle = Math.atan(bottomRightSlope);
double topLeftAngle = Math.atan(topLeftSlope);
double bottomLeftAngle = Math.atan(bottomLeftSlope);
// calculate the right & left-hand differences
double rightDiff = Math.abs(topRightAngle - bottomRightAngle);
double leftDiff = Math.abs(topLeftAngle - bottomLeftAngle);
// normalise the differences from 0 to 1
rightDiff = rightDiff / Math.PI;
leftDiff = leftDiff / Math.PI;
double product = rightDiff * leftDiff;
if (LOG.isTraceEnabled()) {
LOG.trace("topRightAngle: " + topRightAngle);
LOG.trace("bottomRightAngle: " + bottomRightAngle);
LOG.trace("topLeftAngle: " + topLeftAngle);
LOG.trace("bottomLeftAngle: " + bottomLeftAngle);
LOG.trace("rightDiff: " + rightDiff);
LOG.trace("leftDiff: " + leftDiff);
LOG.trace("product: " + product);
}
result = this.generateResult(product);
}
return result;
}
Aggregations