Search in sources :

Example 56 with Shape

use of com.joliciel.jochre.graphics.Shape in project jochre by urieli.

the class ShapeMerger method merge.

/**
 * Merge two sequential shapes into a single shape.
 */
public Shape merge(Shape shape1, Shape shape2) {
    ShapePair pair = new ShapePair(shape1, shape2);
    Shape mergedShape = shape1.getJochreImage().getShape(pair.getLeft(), pair.getTop(), pair.getRight(), pair.getBottom());
    return mergedShape;
}
Also used : Shape(com.joliciel.jochre.graphics.Shape)

Example 57 with Shape

use of com.joliciel.jochre.graphics.Shape in project jochre by urieli.

the class BeamSearchImageAnalyser method analyseInternal.

public void analyseInternal(JochreImage image) {
    LOG.debug("Analysing image " + image.getId());
    if (currentMonitor != null) {
        currentMonitor.setCurrentAction("imageMonitor.analysingImage", new Object[] { image.getPage().getIndex() });
    }
    for (LetterGuessObserver observer : observers) {
        observer.onImageStart(image);
    }
    if (totalShapeCount < 0)
        totalShapeCount = image.getShapeCount();
    for (Paragraph paragraph : image.getParagraphs()) {
        LOG.debug("Analysing paragraph " + paragraph.getIndex() + " (id=" + paragraph.getId() + ")");
        List<LetterSequence> holdoverSequences = null;
        GroupOfShapes holdoverGroup = null;
        for (RowOfShapes row : paragraph.getRows()) {
            LOG.debug("Analysing row " + row.getIndex() + " (id=" + row.getId() + ")");
            for (GroupOfShapes group : row.getGroups()) {
                if (group.isSkip()) {
                    LOG.debug("Skipping group " + group.getIndex() + " (id=" + group.getId() + ")");
                    continue;
                }
                LOG.debug("Analysing group " + group.getIndex() + " (id=" + group.getId() + ")");
                int width = group.getRight() - group.getLeft() + 1;
                List<ShapeSequence> shapeSequences = null;
                if (boundaryDetector != null) {
                    shapeSequences = boundaryDetector.findBoundaries(group);
                } else {
                    // simply add this groups shape's
                    shapeSequences = new ArrayList<>();
                    ShapeSequence shapeSequence = new ShapeSequence();
                    for (Shape shape : group.getShapes()) shapeSequence.addShape(shape);
                    shapeSequences.add(shapeSequence);
                }
                // Perform a beam search to guess the most likely sequence
                // for this
                // word
                TreeMap<Integer, PriorityQueue<LetterSequence>> heaps = new TreeMap<>();
                // prime a starter heap with the n best shape boundary
                // analyses for
                // this group
                PriorityQueue<LetterSequence> starterHeap = new PriorityQueue<>(1);
                for (ShapeSequence shapeSequence : shapeSequences) {
                    LetterSequence emptySequence = new LetterSequence(shapeSequence, jochreSession);
                    starterHeap.add(emptySequence);
                }
                heaps.put(0, starterHeap);
                PriorityQueue<LetterSequence> finalHeap = null;
                while (heaps.size() > 0) {
                    Entry<Integer, PriorityQueue<LetterSequence>> heapEntry = heaps.pollFirstEntry();
                    if (LOG.isTraceEnabled())
                        LOG.trace("heap for index: " + heapEntry.getKey().intValue() + ", width: " + width);
                    if (heapEntry.getKey().intValue() == width) {
                        finalHeap = heapEntry.getValue();
                        break;
                    }
                    PriorityQueue<LetterSequence> previousHeap = heapEntry.getValue();
                    // limit the breadth to K
                    int maxSequences = previousHeap.size() > this.beamWidth ? this.beamWidth : previousHeap.size();
                    for (int j = 0; j < maxSequences; j++) {
                        LetterSequence history = previousHeap.poll();
                        ShapeInSequence shapeInSequence = history.getNextShape();
                        Shape shape = shapeInSequence.getShape();
                        if (LOG.isTraceEnabled()) {
                            LOG.trace("Sequence " + history + ", shape: " + shape);
                        }
                        LogUtils.logMemory(LOG);
                        int position = 0;
                        if (jochreSession.getLinguistics().isLeftToRight()) {
                            position = shape.getRight() - group.getLeft() + 1;
                        } else {
                            position = group.getRight() - shape.getLeft() + 1;
                        }
                        PriorityQueue<LetterSequence> heap = heaps.get(position);
                        if (heap == null) {
                            heap = new PriorityQueue<>();
                            heaps.put(position, heap);
                        }
                        letterGuesser.guessLetter(shapeInSequence, history);
                        // heap sort
                        for (Decision letterGuess : shape.getLetterGuesses()) {
                            // leave out very low probability outcomes
                            if (letterGuess.getProbability() > this.minOutcomeWeight) {
                                LetterSequence sequence = new LetterSequence(history);
                                sequence.getLetters().add(letterGuess.getOutcome());
                                sequence.addDecision(letterGuess);
                                heap.add(sequence);
                            }
                        // weight big enough to include
                        }
                    // next letter guess for this shape
                    }
                // next history in heap
                }
                // any more heaps?
                // find best sequence
                LetterSequence bestSequence = null;
                boolean isHoldover = false;
                List<LetterSequence> finalSequences = new ArrayList<>();
                for (int i = 0; i < this.beamWidth; i++) {
                    if (finalHeap.isEmpty())
                        break;
                    finalSequences.add(finalHeap.poll());
                }
                if (this.mostLikelyWordChooser == null) {
                    // most likely sequence is on top of the last heap
                    bestSequence = finalSequences.get(0);
                } else {
                    // get most likely sequence using lexicon
                    if (holdoverSequences != null) {
                        // we have a holdover from the previous row
                        // ending with a dash
                        bestSequence = this.mostLikelyWordChooser.chooseMostLikelyWord(finalSequences, holdoverSequences, this.beamWidth);
                    } else {
                        // check if this is the last group on the row
                        // and could end with
                        // a dash
                        boolean shouldBeHeldOver = false;
                        if (group.getIndex() == row.getGroups().size() - 1 && row.getIndex() < paragraph.getRows().size() - 1) {
                            for (LetterSequence letterSequence : finalSequences) {
                                if (letterSequence.toString().endsWith("-")) {
                                    shouldBeHeldOver = true;
                                    break;
                                }
                            }
                        }
                        if (shouldBeHeldOver) {
                            holdoverSequences = finalSequences;
                            holdoverGroup = group;
                            isHoldover = true;
                        } else {
                            // simplest case: no holdover
                            bestSequence = this.mostLikelyWordChooser.chooseMostLikelyWord(finalSequences, this.beamWidth);
                        }
                    }
                // have we holdover sequences?
                }
                if (!isHoldover) {
                    for (LetterGuessObserver observer : observers) {
                        observer.onBeamSearchEnd(bestSequence, finalSequences, holdoverSequences);
                    }
                }
                // assign letter
                if (!isHoldover) {
                    for (LetterGuessObserver observer : observers) {
                        observer.onStartSequence(bestSequence);
                    }
                    if (holdoverGroup == null) {
                        group.setBestLetterSequence(bestSequence);
                    } else {
                        // split bestSequence by group
                        List<LetterSequence> sequencesByGroup = bestSequence.splitByGroup();
                        for (LetterSequence sequenceByGroup : sequencesByGroup) {
                            if (sequenceByGroup.getGroups().get(0).equals(holdoverGroup))
                                holdoverGroup.setBestLetterSequence(sequenceByGroup);
                            else if (sequenceByGroup.getGroups().get(0).equals(group))
                                group.setBestLetterSequence(sequenceByGroup);
                        }
                        holdoverSequences = null;
                        holdoverGroup = null;
                    }
                    int i = 0;
                    for (ShapeInSequence shapeInSequence : bestSequence.getUnderlyingShapeSequence()) {
                        String bestOutcome = bestSequence.getLetters().get(i);
                        this.assignLetter(shapeInSequence, bestOutcome);
                        i++;
                    }
                    for (LetterGuessObserver observer : observers) {
                        observer.onGuessSequence(bestSequence);
                    }
                }
                this.shapeCount += group.getShapes().size();
                if (this.currentMonitor != null) {
                    double progress = (double) shapeCount / (double) totalShapeCount;
                    LOG.debug("progress: " + progress);
                    currentMonitor.setPercentComplete(progress);
                }
            }
        // next group
        }
    // next row
    }
    for (LetterGuessObserver observer : observers) {
        observer.onImageEnd();
    }
}
Also used : LetterSequence(com.joliciel.jochre.letterGuesser.LetterSequence) Shape(com.joliciel.jochre.graphics.Shape) ArrayList(java.util.ArrayList) RowOfShapes(com.joliciel.jochre.graphics.RowOfShapes) PriorityQueue(java.util.PriorityQueue) TreeMap(java.util.TreeMap) Decision(com.joliciel.talismane.machineLearning.Decision) Paragraph(com.joliciel.jochre.graphics.Paragraph) GroupOfShapes(com.joliciel.jochre.graphics.GroupOfShapes) ShapeSequence(com.joliciel.jochre.boundaries.ShapeSequence) ShapeInSequence(com.joliciel.jochre.boundaries.ShapeInSequence)

Example 58 with Shape

use of com.joliciel.jochre.graphics.Shape in project jochre by urieli.

the class LetterAssigner method onGuessSequence.

@Override
public void onGuessSequence(LetterSequence letterSequence) {
    if (save) {
        ShapeSequence shapeSequence = letterSequence.getUnderlyingShapeSequence();
        for (ShapeInSequence shapeInSequence : shapeSequence) {
            Shape shape = shapeInSequence.getShape();
            shape.save();
        }
    }
}
Also used : Shape(com.joliciel.jochre.graphics.Shape) ShapeSequence(com.joliciel.jochre.boundaries.ShapeSequence) ShapeInSequence(com.joliciel.jochre.boundaries.ShapeInSequence)

Example 59 with Shape

use of com.joliciel.jochre.graphics.Shape in project jochre by urieli.

the class LetterAssigner method onGuessLetter.

@Override
public void onGuessLetter(ShapeInSequence shapeInSequence, String bestGuess) {
    Shape shape = shapeInSequence.getShape();
    if (jochreImage.getImageStatus().equals(ImageStatus.AUTO_NEW)) {
        // if the image is brand new, we assign both the letter and the original guess
        // for all other images, we assign only the original guess
        // so as not to override the letter selected by the user
        shape.setLetter(bestGuess);
    }
    shape.setOriginalGuess(bestGuess);
}
Also used : Shape(com.joliciel.jochre.graphics.Shape)

Example 60 with Shape

use of com.joliciel.jochre.graphics.Shape in project jochre by urieli.

the class OriginalShapeLetterAssigner method onGuessLetter.

@Override
public void onGuessLetter(ShapeInSequence shapeInSequence, String bestGuess) {
    Shape shape = shapeInSequence.getShape();
    shape.setOriginalGuess(bestGuess);
}
Also used : Shape(com.joliciel.jochre.graphics.Shape)

Aggregations

Shape (com.joliciel.jochre.graphics.Shape)74 ArrayList (java.util.ArrayList)22 GroupOfShapes (com.joliciel.jochre.graphics.GroupOfShapes)14 JochreImage (com.joliciel.jochre.graphics.JochreImage)13 Paragraph (com.joliciel.jochre.graphics.Paragraph)9 RowOfShapes (com.joliciel.jochre.graphics.RowOfShapes)9 Decision (com.joliciel.talismane.machineLearning.Decision)8 Test (org.junit.Test)8 JochreSession (com.joliciel.jochre.JochreSession)7 JochrePage (com.joliciel.jochre.doc.JochrePage)7 Config (com.typesafe.config.Config)7 TreeSet (java.util.TreeSet)7 JochreDocument (com.joliciel.jochre.doc.JochreDocument)6 BufferedImage (java.awt.image.BufferedImage)6 ShapeInSequence (com.joliciel.jochre.boundaries.ShapeInSequence)5 ShapeSequence (com.joliciel.jochre.boundaries.ShapeSequence)5 GraphicsDao (com.joliciel.jochre.graphics.GraphicsDao)5 RuntimeEnvironment (com.joliciel.talismane.machineLearning.features.RuntimeEnvironment)5 SplitFeature (com.joliciel.jochre.boundaries.features.SplitFeature)4 JochreException (com.joliciel.jochre.utils.JochreException)4