Search in sources :

Example 16 with RowOfShapes

use of com.joliciel.jochre.graphics.RowOfShapes 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 17 with RowOfShapes

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

the class JochreDocument method getXml.

/**
 * Returns an xml representation of this document as it currently stands, to
 * be used for correcting the text associated with this document.
 */
public void getXml(OutputStream outputStream) {
    try {
        XMLOutputFactory xmlOutputFactory = XMLOutputFactory.newFactory();
        XMLStreamWriter writer = xmlOutputFactory.createXMLStreamWriter(outputStream);
        writer.writeStartDocument("UTF-8", "1.0");
        writer.writeStartElement("doc");
        writer.writeAttribute("name", this.getName());
        writer.writeAttribute("fileName", this.getFileName());
        writer.writeAttribute("locale", this.getLocale().getLanguage());
        for (JochrePage page : this.getPages()) {
            writer.writeStartElement("page");
            writer.writeAttribute("index", "" + page.getIndex());
            for (JochreImage image : page.getImages()) {
                writer.writeStartElement("image");
                writer.writeAttribute("name", image.getName());
                writer.writeAttribute("index", "" + image.getIndex());
                for (Paragraph paragraph : image.getParagraphs()) {
                    writer.writeStartElement("paragraph");
                    writer.writeAttribute("index", "" + paragraph.getIndex());
                    StringBuffer sb = new StringBuffer();
                    for (RowOfShapes row : paragraph.getRows()) {
                        for (GroupOfShapes group : row.getGroups()) {
                            for (Shape shape : group.getShapes()) {
                                if (shape.getLetter() != null)
                                    sb.append(shape.getLetter());
                            }
                            sb.append(" ");
                        }
                        sb.append("\r\n");
                    }
                    writer.writeCData(sb.toString());
                    // paragraph
                    writer.writeEndElement();
                }
                // image
                writer.writeEndElement();
            }
            // page
            writer.writeEndElement();
        }
        // doc
        writer.writeEndElement();
        writer.writeEndDocument();
        writer.flush();
    } catch (XMLStreamException e) {
        throw new JochreException(e);
    }
}
Also used : XMLOutputFactory(javax.xml.stream.XMLOutputFactory) JochreImage(com.joliciel.jochre.graphics.JochreImage) Shape(com.joliciel.jochre.graphics.Shape) JochreException(com.joliciel.jochre.utils.JochreException) XMLStreamException(javax.xml.stream.XMLStreamException) XMLStreamWriter(javax.xml.stream.XMLStreamWriter) GroupOfShapes(com.joliciel.jochre.graphics.GroupOfShapes) RowOfShapes(com.joliciel.jochre.graphics.RowOfShapes) Paragraph(com.joliciel.jochre.graphics.Paragraph)

Aggregations

Paragraph (com.joliciel.jochre.graphics.Paragraph)17 RowOfShapes (com.joliciel.jochre.graphics.RowOfShapes)17 ArrayList (java.util.ArrayList)12 GroupOfShapes (com.joliciel.jochre.graphics.GroupOfShapes)10 Test (org.junit.Test)10 Shape (com.joliciel.jochre.graphics.Shape)9 JochreSession (com.joliciel.jochre.JochreSession)8 Config (com.typesafe.config.Config)8 Segmenter (com.joliciel.jochre.graphics.Segmenter)7 SourceImage (com.joliciel.jochre.graphics.SourceImage)7 BufferedImage (java.awt.image.BufferedImage)7 InputStream (java.io.InputStream)7 JochreImage (com.joliciel.jochre.graphics.JochreImage)6 Rectangle (java.awt.Rectangle)6 HashMap (java.util.HashMap)6 JochreDocument (com.joliciel.jochre.doc.JochreDocument)4 JochrePage (com.joliciel.jochre.doc.JochrePage)4 StringWriter (java.io.StringWriter)3 Expectations (mockit.Expectations)3 LetterSequence (com.joliciel.jochre.letterGuesser.LetterSequence)2