Search in sources :

Example 41 with Shape

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

the class RecursiveShapeSplitterTest method testSplitShapeSplitMoreLikely.

/**
 * If a split is always more likely (e.g. 60% likelihood), ensure the shape
 * sequences are ordered correctly.
 */
@SuppressWarnings("unchecked")
@Test
public void testSplitShapeSplitMoreLikely() throws Exception {
    System.setProperty("config.file", "src/test/resources/test.conf");
    ConfigFactory.invalidateCaches();
    Config config = ConfigFactory.load();
    JochreSession jochreSession = new JochreSession(config);
    BufferedImage originalImage = new BufferedImage(256, 256, BufferedImage.TYPE_INT_RGB);
    final JochreImage jochreImage = new JochreImage(originalImage, jochreSession);
    final Shape shape = new Shape(jochreImage, 0, 0, 63, 15, jochreSession);
    shape.setBaseLine(12);
    shape.setMeanLine(4);
    final Shape shape1 = new Shape(jochreImage, 0, 0, 31, 15, jochreSession);
    shape1.setBaseLine(12);
    shape1.setMeanLine(4);
    final Shape shape2 = new Shape(jochreImage, 32, 0, 63, 15, jochreSession);
    shape2.setBaseLine(12);
    shape2.setMeanLine(4);
    final SplitCandidateFinder splitCandidateFinder = mock(SplitCandidateFinder.class);
    final DecisionMaker decisionMaker = mock(DecisionMaker.class);
    Split split = new Split(shape, jochreSession);
    split.setPosition(31);
    List<Split> splits = new ArrayList<>();
    splits.add(split);
    when(splitCandidateFinder.findSplitCandidates(shape)).thenReturn(splits);
    Decision yesDecision = new Decision(SplitOutcome.DO_SPLIT.name(), 0.6);
    Decision noDecision = new Decision(SplitOutcome.DO_NOT_SPLIT.name(), 0.4);
    List<Decision> decisions = new ArrayList<>();
    decisions.add(yesDecision);
    decisions.add(noDecision);
    when(decisionMaker.decide(anyList())).thenReturn(decisions);
    Split split1 = new Split(shape1, jochreSession);
    split1.setPosition(15);
    List<Split> splits1 = new ArrayList<>();
    splits1.add(split1);
    when(splitCandidateFinder.findSplitCandidates(shape1)).thenReturn(splits1);
    Split split2 = new Split(shape2, jochreSession);
    split2.setPosition(15);
    List<Split> splits2 = new ArrayList<>();
    splits2.add(split2);
    when(splitCandidateFinder.findSplitCandidates(shape2)).thenReturn(splits2);
    Set<SplitFeature<?>> splitFeatures = new TreeSet<>();
    RecursiveShapeSplitter splitter = new RecursiveShapeSplitter(splitCandidateFinder, splitFeatures, decisionMaker, jochreSession);
    splitter.setBeamWidth(10);
    splitter.setMaxDepth(2);
    splitter.setMinWidthRatio(1.0);
    List<ShapeSequence> shapeSequences = splitter.split(shape);
    assertEquals(5, shapeSequences.size());
    int i = 0;
    for (ShapeSequence shapeSequence : shapeSequences) {
        LOG.debug("sequence " + i + " shapes:");
        for (ShapeInSequence shapeInSequence : shapeSequence) {
            Shape oneShape = shapeInSequence.getShape();
            LOG.debug("Shape: " + oneShape.getLeft() + "," + oneShape.getRight());
        }
        LOG.debug("" + shapeSequence.getScore());
        i++;
    }
    i = 0;
    double prob = 1.0;
    double twoThirds = 0.4 / 0.6;
    LOG.debug("twoThirds: " + twoThirds);
    for (ShapeSequence shapeSequence : shapeSequences) {
        LOG.debug("sequence " + i + " decisions:");
        for (Decision decision : shapeSequence.getDecisions()) LOG.debug("" + decision.getProbability());
        if (i == 0) {
            prob = 1.0;
            assertEquals(prob, shapeSequence.getScore(), 0.0001);
            assertEquals(4, shapeSequence.size());
        } else if (i == 1) {
            prob = 1.0 * twoThirds;
            assertEquals(prob, shapeSequence.getScore(), 0.0001);
            assertEquals(3, shapeSequence.size());
        } else if (i == 2) {
            prob = 1.0 * twoThirds;
            assertEquals(prob, shapeSequence.getScore(), 0.0001);
            assertEquals(3, shapeSequence.size());
        } else if (i == 3) {
            prob = 1.0 * twoThirds * twoThirds;
            assertEquals(prob, shapeSequence.getScore(), 0.0001);
            assertEquals(2, shapeSequence.size());
        } else if (i == 4) {
            prob = 1.0 * twoThirds * twoThirds * twoThirds;
            assertEquals(prob, shapeSequence.getScore(), 0.0001);
            assertEquals(1, shapeSequence.size());
        }
        i++;
    }
}
Also used : JochreImage(com.joliciel.jochre.graphics.JochreImage) Shape(com.joliciel.jochre.graphics.Shape) Config(com.typesafe.config.Config) ArrayList(java.util.ArrayList) DecisionMaker(com.joliciel.talismane.machineLearning.DecisionMaker) SplitFeature(com.joliciel.jochre.boundaries.features.SplitFeature) BufferedImage(java.awt.image.BufferedImage) Decision(com.joliciel.talismane.machineLearning.Decision) TreeSet(java.util.TreeSet) JochreSession(com.joliciel.jochre.JochreSession) Test(org.junit.Test)

Example 42 with Shape

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

the class SplitCandidateFinderImplTest method testFindSplitCanidates.

@Test
public void testFindSplitCanidates() throws Exception {
    System.setProperty("config.file", "src/test/resources/test.conf");
    ConfigFactory.invalidateCaches();
    Config config = ConfigFactory.load();
    JochreSession jochreSession = new JochreSession(config);
    InputStream imageFileStream = getClass().getResourceAsStream("shape_370454.png");
    assertNotNull(imageFileStream);
    BufferedImage image = ImageIO.read(imageFileStream);
    final JochrePage page = mock(JochrePage.class);
    JochreImage jochreImage = new SourceImage(page, "name", image, jochreSession);
    Shape shape = jochreImage.getShape(0, 0, jochreImage.getWidth() - 1, jochreImage.getHeight() - 1);
    SplitCandidateFinder splitCandidateFinder = new SplitCandidateFinder(jochreSession);
    List<Split> splits = splitCandidateFinder.findSplitCandidates(shape);
    int[] trueSplitPositions = new int[] { 38, 59, 82 };
    boolean[] foundSplit = new boolean[] { false, false, false };
    for (Split splitCandidate : splits) {
        LOG.debug("Split candidate at " + splitCandidate.getPosition());
        for (int i = 0; i < trueSplitPositions.length; i++) {
            int truePos = trueSplitPositions[i];
            int distance = splitCandidate.getPosition() - truePos;
            if (distance < 0)
                distance = 0 - distance;
            if (distance < splitCandidateFinder.getMinDistanceBetweenSplits()) {
                foundSplit[i] = true;
                LOG.debug("Found split: " + truePos + ", distance " + distance);
            }
        }
    }
    for (int i = 0; i < trueSplitPositions.length; i++) {
        assertTrue("didn't find split " + trueSplitPositions[i], foundSplit[i]);
    }
}
Also used : JochreImage(com.joliciel.jochre.graphics.JochreImage) Shape(com.joliciel.jochre.graphics.Shape) SourceImage(com.joliciel.jochre.graphics.SourceImage) Config(com.typesafe.config.Config) InputStream(java.io.InputStream) JochrePage(com.joliciel.jochre.doc.JochrePage) BufferedImage(java.awt.image.BufferedImage) JochreSession(com.joliciel.jochre.JochreSession) Test(org.junit.Test)

Example 43 with Shape

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

the class JochreLetterEventStream method hasNext.

@Override
public boolean hasNext() {
    this.initialiseStream();
    while (shapeInSequence == null && shapeSequence != null) {
        while (shapeInSequence == null && shapeIndex < shapeSequence.size()) {
            shapeInSequence = shapeSequence.get(shapeIndex);
            shapeIndex++;
            Shape shape = shapeInSequence.getShape();
            String letter = shape.getLetter();
            if (!letterValidator.validate(letter)) {
                // if there's an invalid letter, skip the rest of this
                // group
                // note we allow empty letters (which is how we indicate
                // ink smudges
                // in the text)
                LOG.debug("Invalid letter for shape " + shapeInSequence.getOriginalShapes().get(0).getId() + ": " + letter);
                invalidLetterCount++;
                shapeInSequence = null;
                break;
            }
        }
        if (shapeInSequence == null) {
            this.getNextGroup();
        }
    }
    if (shapeInSequence == null) {
        LOG.debug("invalidLetterCount: " + invalidLetterCount);
    }
    return shapeInSequence != null;
}
Also used : Shape(com.joliciel.jochre.graphics.Shape)

Example 44 with Shape

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

the class JochreLetterEventStream method next.

@Override
public ClassificationEvent next() {
    ClassificationEvent event = null;
    if (this.hasNext()) {
        Shape shape = shapeInSequence.getShape();
        LOG.debug("next event, shape: " + shape);
        LetterGuesserContext context = new LetterGuesserContext(shapeInSequence, history);
        List<FeatureResult<?>> featureResults = new ArrayList<>();
        // analyse features
        for (LetterFeature<?> feature : features) {
            RuntimeEnvironment env = new RuntimeEnvironment();
            FeatureResult<?> featureResult = feature.check(context, env);
            if (featureResult != null) {
                featureResults.add(featureResult);
                if (LOG.isTraceEnabled()) {
                    LOG.trace(featureResult.toString());
                }
            }
        }
        String outcome = shape.getLetter();
        event = new ClassificationEvent(featureResults, outcome);
        history.getLetters().add(outcome);
        // set shape to null so that hasNext can retrieve the next one.
        this.shapeInSequence = null;
    }
    return event;
}
Also used : Shape(com.joliciel.jochre.graphics.Shape) RuntimeEnvironment(com.joliciel.talismane.machineLearning.features.RuntimeEnvironment) ArrayList(java.util.ArrayList) ClassificationEvent(com.joliciel.talismane.machineLearning.ClassificationEvent) FeatureResult(com.joliciel.talismane.machineLearning.features.FeatureResult)

Example 45 with Shape

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

the class LetterGuesser method guessLetter.

/**
 * Analyses this shape, using the context provided for features that are not
 * intrinsic. Updates shape.getWeightedOutcomes to include all outcomes
 * above a certain threshold of probability.
 *
 * @return the best outcome for this shape.
 */
public String guessLetter(ShapeInSequence shapeInSequence, LetterSequence history) {
    Shape shape = shapeInSequence.getShape();
    if (LOG.isTraceEnabled())
        LOG.trace("guessLetter, shape: " + shape);
    List<FeatureResult<?>> featureResults = new ArrayList<FeatureResult<?>>();
    // analyse features
    for (LetterFeature<?> feature : features) {
        LetterGuesserContext context = new LetterGuesserContext(shapeInSequence, history);
        RuntimeEnvironment env = new RuntimeEnvironment();
        FeatureResult<?> featureResult = feature.check(context, env);
        if (featureResult != null) {
            featureResults.add(featureResult);
            if (LOG.isTraceEnabled()) {
                LOG.trace(featureResult.toString());
            }
        }
    }
    List<Decision> letterGuesses = decisionMaker.decide(featureResults);
    // store outcomes
    String bestOutcome = null;
    shape.getLetterGuesses().clear();
    for (Decision letterGuess : letterGuesses) {
        if (letterGuess.getProbability() >= MIN_PROB_TO_STORE) {
            shape.getLetterGuesses().add(letterGuess);
        }
    }
    bestOutcome = shape.getLetterGuesses().iterator().next().getOutcome();
    if (LOG.isTraceEnabled()) {
        LOG.trace("Shape: " + shape);
        LOG.trace("Letter: " + shape.getLetter());
        LOG.trace("Best outcome: " + bestOutcome);
    }
    return bestOutcome;
}
Also used : Shape(com.joliciel.jochre.graphics.Shape) RuntimeEnvironment(com.joliciel.talismane.machineLearning.features.RuntimeEnvironment) ArrayList(java.util.ArrayList) FeatureResult(com.joliciel.talismane.machineLearning.features.FeatureResult) Decision(com.joliciel.talismane.machineLearning.Decision)

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