Search in sources :

Example 1 with JochreSession

use of com.joliciel.jochre.JochreSession in project jochre by urieli.

the class SegmentationTest method testSegmentation.

@Test
public void testSegmentation() throws Exception {
    // TODO: Note currently this requires high thresholds to work
    // Need to decide if this is valid in general, or only for these samples
    System.setProperty("config.file", "src/test/resources/testHighThresholds.conf");
    ConfigFactory.invalidateCaches();
    Config config = ConfigFactory.load();
    JochreSession jochreSession = new JochreSession(config);
    boolean writePixelsToLog = true;
    for (int imageNumber = 1; imageNumber <= 4; imageNumber++) {
        if (imageNumber != 1)
            continue;
        String imageName = "";
        String suffix = "";
        String text = "";
        String fileName = "";
        String userFileName;
        int rowCount = 2;
        int shapeCountRow1;
        int shapeCountRow2;
        int groupCountRow1;
        int groupCountRow2;
        int groupCountRow3 = 0;
        int shapeCountRow1Group1;
        int shapeCountRow2Group1;
        if (imageNumber == 1) {
            imageName = "MotlPeysiDemKhazns2RowsShort2";
            suffix = "jpg";
            text = "איך געה מיט אייך קיינער אין דער וועלט";
            fileName = "MotlPeysiDemKhazns2RowsShort2.pdf";
            userFileName = "Motl Peysi Dem Khazns";
            shapeCountRow1 = 13;
            shapeCountRow2 = 17;
            groupCountRow1 = 4;
            groupCountRow2 = 4;
            shapeCountRow1Group1 = 3;
            shapeCountRow2Group1 = 6;
        } else if (imageNumber == 2) {
            imageName = "MegileLiderZeresh";
            suffix = "png";
            text = "זרש, די מכשפה, װאָס שעלט ווי אַ מגפה";
            fileName = "MegileLiderManger.pdf";
            userFileName = "Megile Lider";
            shapeCountRow1 = 12;
            shapeCountRow2 = 17;
            groupCountRow1 = 3;
            groupCountRow2 = 5;
            shapeCountRow1Group1 = 4;
            shapeCountRow2Group1 = 4;
        } else if (imageNumber == 3) {
            imageName = "MendeleMoykherSforimVol1_41_0Excerpt";
            suffix = "png";
            text = "ער הייסט יאַנקיל, בעריל,";
            fileName = "MendeleMoykherSforimVol1_41_0.png";
            userFileName = "MendeleMoykherSforimVol1_41_0";
            shapeCountRow1 = 20;
            shapeCountRow2 = 0;
            groupCountRow1 = 4;
            groupCountRow2 = 0;
            shapeCountRow1Group1 = 2;
            shapeCountRow2Group1 = 0;
        } else {
            imageName = "JoinedLetterTest";
            suffix = "png";
            text = "Joined Letter Test";
            fileName = "JoinedLetterTest.png";
            userFileName = "JoinedLetterTest";
            rowCount = 2;
            shapeCountRow1 = 23;
            shapeCountRow2 = 23;
            groupCountRow1 = 4;
            groupCountRow2 = 4;
            groupCountRow3 = 5;
            shapeCountRow1Group1 = 6;
            shapeCountRow2Group1 = 5;
        }
        LOG.debug("######### imageName: " + imageName);
        // String fileName = "data/Zelmenyaners3Words.gif";
        InputStream imageFileStream = getClass().getResourceAsStream("/com/joliciel/jochre/test/resources/" + imageName + "." + suffix);
        assertNotNull(imageFileStream);
        BufferedImage image = ImageIO.read(imageFileStream);
        JochreDocument doc = new JochreDocument(jochreSession);
        doc.setFileName(fileName);
        doc.setName(userFileName);
        JochrePage page = doc.newPage();
        SourceImage sourceImage = page.newJochreImage(image, imageName);
        sourceImage.setWhiteGapFillFactor(5);
        sourceImage.setImageStatus(ImageStatus.AUTO_NEW);
        if (writePixelsToLog) {
            LOG.debug("i012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789");
            for (int y = 0; y < sourceImage.getHeight(); y++) {
                String line = "" + y;
                for (int x = 0; x < sourceImage.getWidth(); x++) {
                    if (sourceImage.isPixelBlack(x, y, sourceImage.getBlackThreshold()))
                        line += "x";
                    else
                        line += "o";
                }
                LOG.debug(line);
            }
        }
        Segmenter segmenter = new Segmenter(sourceImage, jochreSession);
        segmenter.segment();
        if (segmenter.isDrawSegmentation()) {
            BufferedImage segmentedImage = segmenter.getSegmentedImage();
            File tempDir = new File(System.getProperty("java.io.tmpdir"));
            ImageIO.write(segmentedImage, "PNG", new File(tempDir, imageName + "_seg.png"));
        }
        JochreImage jochreImage = sourceImage;
        int i = 0;
        boolean firstShape = true;
        int midPixelFirstShape = 0;
        int midPixelFirstShapeRaw = 0;
        for (Paragraph paragraph : jochreImage.getParagraphs()) {
            for (RowOfShapes row : paragraph.getRows()) {
                int j = 0;
                LOG.debug("============= Row " + i + " ================");
                for (Shape shape : row.getShapes()) {
                    LOG.debug("Shape (" + i + "," + j + "). Left = " + shape.getLeft() + ". Top = " + shape.getTop() + ". Right = " + shape.getRight() + ". Bottom = " + shape.getBottom() + ". Group: " + shape.getGroup().getIndex());
                    if (firstShape) {
                        midPixelFirstShape = shape.getPixel(3, 3);
                        midPixelFirstShapeRaw = shape.getRawPixel(3, 3);
                        firstShape = false;
                    }
                    if (writePixelsToLog) {
                        for (int y = 0; y < shape.getHeight(); y++) {
                            String line = "";
                            if (y == shape.getMeanLine())
                                line += "M";
                            else if (y == shape.getBaseLine())
                                line += "B";
                            else
                                line += y;
                            for (int x = 0; x < shape.getWidth(); x++) {
                                if (shape.isPixelBlack(x, y, sourceImage.getBlackThreshold()))
                                    line += "x";
                                else
                                    line += "o";
                            }
                            LOG.debug(line);
                        }
                    }
                    j++;
                }
                // next shape
                i++;
            }
        // next row
        }
        // next paragraph
        i = 0;
        for (Paragraph paragraph : jochreImage.getParagraphs()) {
            for (RowOfShapes row : paragraph.getRows()) {
                for (GroupOfShapes group : row.getGroups()) {
                    for (Shape shape : group.getShapes()) {
                        if (i < text.length()) {
                            String letter = text.substring(i, i + 1);
                            String nextLetter = "";
                            if (i + 1 < text.length())
                                nextLetter = text.substring(i + 1, i + 2);
                            if (nextLetter.equals("ָֹ") || nextLetter.equals("ַ")) {
                                letter += nextLetter;
                                i++;
                            }
                            LOG.debug("Letter: " + letter);
                            shape.setLetter(letter);
                        }
                        i++;
                    }
                    // to skip the space
                    i++;
                    LOG.debug("Space");
                }
            // next group
            }
        // next row
        }
        // next paragraph
        List<ShapeFeature<?>> features = new ArrayList<ShapeFeature<?>>();
        features.add(new VerticalElongationFeature());
        features.add(new VerticalSizeFeature());
        features.add(new TouchesBaseLineFeature());
        features.add(new TouchesMeanLineFeature());
        features.add(new EmptyCentreFeature());
        i = 0;
        DecimalFormat df = new DecimalFormat("0.00");
        firstShape = true;
        int totalRowCount = 0;
        for (Paragraph paragraph : jochreImage.getParagraphs()) {
            for (RowOfShapes row : paragraph.getRows()) {
                totalRowCount++;
                LOG.debug("============= Row " + i + " ================");
                int j = 0;
                for (GroupOfShapes group : row.getGroups()) {
                    for (Shape shape : group.getShapes()) {
                        LOG.debug("============= Shape (" + i + "," + j + ") ================");
                        LOG.debug("Left = " + shape.getLeft() + ". Top = " + shape.getTop() + ". Right = " + shape.getRight() + ". Bottom = " + shape.getBottom());
                        LOG.debug("Letter " + shape.getLetter());
                        if (firstShape) {
                            LOG.debug("mid pixel: " + midPixelFirstShape);
                            assertEquals(midPixelFirstShape, shape.getPixel(3, 3));
                            LOG.debug("mid pixel raw: " + midPixelFirstShapeRaw);
                            assertEquals(midPixelFirstShapeRaw, shape.getRawPixel(3, 3));
                            firstShape = false;
                        }
                        if (writePixelsToLog) {
                            for (int y = 0; y < shape.getHeight(); y++) {
                                String line = "";
                                if (y == shape.getMeanLine())
                                    line += "M";
                                else if (y == shape.getBaseLine())
                                    line += "B";
                                else
                                    line += y;
                                for (int x = 0; x < shape.getWidth(); x++) {
                                    if (shape.isPixelBlack(x, y, sourceImage.getBlackThreshold()))
                                        line += "x";
                                    else
                                        line += "o";
                                }
                                LOG.debug(line);
                            }
                        }
                        double[][] totals = shape.getBrightnessBySection(5, 5, 1, SectionBrightnessMeasurementMethod.RAW);
                        LOG.debug("Brightness counts");
                        for (int y = 0; y < totals[0].length; y++) {
                            String line = "";
                            for (int x = 0; x < totals.length; x++) {
                                line += df.format(totals[x][y]) + "\t";
                            }
                            LOG.debug(line);
                        }
                        for (ShapeFeature<?> feature : features) {
                            RuntimeEnvironment env = new RuntimeEnvironment();
                            FeatureResult<?> outcome = feature.check(shape, env);
                            LOG.debug(outcome.toString());
                        }
                    }
                    if (i == 0) {
                        if (j == 0)
                            assertEquals(shapeCountRow1Group1, group.getShapes().size());
                    } else if (i == 1) {
                        if (j == 0)
                            assertEquals(shapeCountRow2Group1, group.getShapes().size());
                    }
                    j++;
                }
                if (i == 0)
                    assertEquals(groupCountRow1, row.getGroups().size());
                else if (i == 1)
                    assertEquals(groupCountRow2, row.getGroups().size());
                else if (i == 2)
                    assertEquals(groupCountRow3, row.getGroups().size());
                if (i == 0)
                    assertEquals(shapeCountRow1, row.getShapes().size());
                else if (i == 1)
                    assertEquals(shapeCountRow2, row.getShapes().size());
                i++;
            }
        // next row
        }
        // next paragraph
        assertEquals(rowCount, totalRowCount);
    }
    // next test image
    LOG.debug("************** Finished ***********");
}
Also used : ShapeFeature(com.joliciel.jochre.graphics.features.ShapeFeature) Shape(com.joliciel.jochre.graphics.Shape) SourceImage(com.joliciel.jochre.graphics.SourceImage) Config(com.typesafe.config.Config) DecimalFormat(java.text.DecimalFormat) ArrayList(java.util.ArrayList) VerticalSizeFeature(com.joliciel.jochre.graphics.features.VerticalSizeFeature) JochreDocument(com.joliciel.jochre.doc.JochreDocument) TouchesBaseLineFeature(com.joliciel.jochre.graphics.features.TouchesBaseLineFeature) BufferedImage(java.awt.image.BufferedImage) JochreSession(com.joliciel.jochre.JochreSession) EmptyCentreFeature(com.joliciel.jochre.graphics.features.EmptyCentreFeature) JochreImage(com.joliciel.jochre.graphics.JochreImage) RuntimeEnvironment(com.joliciel.talismane.machineLearning.features.RuntimeEnvironment) TouchesMeanLineFeature(com.joliciel.jochre.graphics.features.TouchesMeanLineFeature) InputStream(java.io.InputStream) RowOfShapes(com.joliciel.jochre.graphics.RowOfShapes) VerticalElongationFeature(com.joliciel.jochre.graphics.features.VerticalElongationFeature) Segmenter(com.joliciel.jochre.graphics.Segmenter) JochrePage(com.joliciel.jochre.doc.JochrePage) Paragraph(com.joliciel.jochre.graphics.Paragraph) GroupOfShapes(com.joliciel.jochre.graphics.GroupOfShapes) File(java.io.File) Test(org.junit.Test)

Example 2 with JochreSession

use of com.joliciel.jochre.JochreSession in project jochre by urieli.

the class SegmenterImplTest method testSplitShape.

@Test
public void testSplitShape() throws Exception {
    System.setProperty("config.file", "src/test/resources/test.conf");
    ConfigFactory.invalidateCaches();
    Config config = ConfigFactory.load();
    JochreSession jochreSession = new JochreSession(config);
    final int threshold = 100;
    final int width = 12;
    final int height = 9;
    final int maxBridgeWidth = 2;
    final int minLetterWeight = 12;
    final int maxOverlap = 2;
    final int left = 10;
    final int top = 10;
    int[] pixels = { // row 0
    1, // row 0
    1, // row 0
    0, // row 0
    0, // row 0
    0, // row 0
    1, // row 0
    0, // row 0
    1, // row 0
    0, // row 0
    1, // row 0
    1, // row 0
    1, // row 1
    0, // row 1
    1, // row 1
    0, // row 1
    0, // row 1
    1, // row 1
    1, // row 1
    1, // row 1
    1, // row 1
    0, // row 1
    0, // row 1
    1, // row 1
    1, // row 2
    0, // row 2
    1, // row 2
    1, // row 2
    1, // row 2
    1, // row 2
    1, // row 2
    0, // row 2
    0, // row 2
    1, // row 2
    0, // row 2
    1, // row 2
    1, // row 3
    0, // row 3
    1, // row 3
    1, // row 3
    0, // row 3
    1, // row 3
    1, // row 3
    0, // row 3
    0, // row 3
    1, // row 3
    0, // row 3
    1, // row 3
    1, // row 4
    0, // row 4
    0, // row 4
    1, // row 4
    1, // row 4
    1, // row 4
    0, // row 4
    0, // row 4
    0, // row 4
    1, // row 4
    1, // row 4
    1, // row 4
    0, // row 5
    0, // row 5
    0, // row 5
    1, // row 5
    1, // row 5
    0, // row 5
    0, // row 5
    0, // row 5
    0, // row 5
    1, // row 5
    1, // row 5
    0, // row 5
    0, // row 6
    0, // row 6
    1, // row 6
    1, // row 6
    0, // row 6
    0, // row 6
    0, // row 6
    0, // row 6
    1, // row 6
    1, // row 6
    0, // row 6
    0, // row 6
    0, // row 7
    1, // row 7
    1, // row 7
    0, // row 7
    0, // row 7
    0, // row 7
    0, // row 7
    1, // row 7
    1, // row 7
    0, // row 7
    0, // row 7
    0, // row 7
    0, // row 8
    0, // row 8
    0, // row 8
    0, // row 8
    0, // row 8
    0, // row 8
    0, // row 8
    1, // row 8
    0, // row 8
    0, // row 8
    0, // row 8
    0, // row 8
    0 };
    SourceImage sourceImage = new SourceImageMock(pixels, 9, 12, jochreSession);
    sourceImage.setSeparationThreshold(threshold);
    Shape shape = new ShapeMock(pixels, left, top, width, height, jochreSession);
    shape.setJochreImage(sourceImage);
    Segmenter segmenter = new Segmenter(sourceImage, jochreSession);
    List<Shape> shapes = segmenter.splitShape(shape, sourceImage, maxBridgeWidth, minLetterWeight, maxOverlap);
    for (Shape splitShape : shapes) {
        LOG.debug("Split shape:  " + splitShape);
    }
    assertEquals(2, shapes.size());
    Shape leftShape = shapes.get(0);
    assertEquals(left, leftShape.getLeft());
    assertEquals(left + 5, leftShape.getRight());
    assertEquals(top, leftShape.getTop());
    assertEquals(top + 7, leftShape.getBottom());
    Shape rightShape = shapes.get(1);
    assertEquals(left + 6, rightShape.getLeft());
    assertEquals(top + 11, rightShape.getRight());
    assertEquals(top, rightShape.getTop());
    assertEquals(top + 8, rightShape.getBottom());
}
Also used : Config(com.typesafe.config.Config) JochreSession(com.joliciel.jochre.JochreSession) Test(org.junit.Test)

Example 3 with JochreSession

use of com.joliciel.jochre.JochreSession in project jochre by urieli.

the class SegmenterImplTest method testGetShape.

@Test
public void testGetShape() throws Exception {
    System.setProperty("config.file", "src/test/resources/test.conf");
    ConfigFactory.invalidateCaches();
    Config config = ConfigFactory.load();
    JochreSession jochreSession = new JochreSession(config);
    final int startX = 3;
    final int startY = 2;
    int[] pixels = { // row 0
    0, // row 0
    0, // row 0
    0, // row 0
    0, // row 0
    0, // row 0
    0, // row 0
    0, // row 0
    0, // row 1
    0, // row 1
    1, // row 1
    0, // row 1
    0, // row 1
    0, // row 1
    0, // row 1
    0, // row 1
    0, // row 2
    0, // row 2
    0, // row 2
    0, // row 2
    1, // row 2
    0, // row 2
    0, // row 2
    1, // row 2
    1, // row 3
    0, // row 3
    0, // row 3
    1, // row 3
    1, // row 3
    1, // row 3
    0, // row 3
    0, // row 3
    1, // row 4
    0, // row 4
    0, // row 4
    0, // row 4
    1, // row 4
    1, // row 4
    1, // row 4
    1, // row 4
    1, // row 5
    0, // row 5
    1, // row 5
    0, // row 5
    0, // row 5
    0, // row 5
    0, // row 5
    0, // row 5
    0, // row 6
    0, // row 6
    1, // row 6
    1, // row 6
    0, // row 6
    0, // row 6
    0, // row 6
    0, // row 6
    0, // row 7
    0, // row 7
    0, // row 7
    1, // row 7
    1, // row 7
    0, // row 7
    0, // row 7
    0, // row 7
    0 };
    SourceImage sourceImage = new SourceImageMock(pixels, 8, 8, jochreSession);
    Segmenter segmenter = new Segmenter(sourceImage, jochreSession);
    final WritableImageGrid imageMirror = new ImageMirror(sourceImage);
    Shape shape = segmenter.getShape(sourceImage, imageMirror, startX, startY);
    assertEquals(2, shape.getTop());
    assertEquals(2, shape.getLeft());
    assertEquals(4, shape.getBottom());
    assertEquals(7, shape.getRight());
}
Also used : Config(com.typesafe.config.Config) JochreSession(com.joliciel.jochre.JochreSession) Test(org.junit.Test)

Example 4 with JochreSession

use of com.joliciel.jochre.JochreSession in project jochre by urieli.

the class ShapeFillerImplTest method testFillBitSet.

@Test
public void testFillBitSet() throws Exception {
    System.setProperty("config.file", "src/test/resources/test.conf");
    ConfigFactory.invalidateCaches();
    Config config = ConfigFactory.load();
    JochreSession jochreSession = new JochreSession(config);
    final int threshold = 100;
    final int width = 8;
    final int height = 8;
    int[] pixels = { // row 0
    0, // row 0
    1, // row 0
    1, // row 0
    0, // row 0
    0, // row 0
    1, // row 0
    1, // row 0
    1, // row 1
    0, // row 1
    1, // row 1
    0, // row 1
    1, // row 1
    0, // row 1
    1, // row 1
    0, // row 1
    1, // row 2
    0, // row 2
    0, // row 2
    1, // row 2
    1, // row 2
    0, // row 2
    0, // row 2
    1, // row 2
    1, // row 3
    0, // row 3
    0, // row 3
    1, // row 3
    1, // row 3
    0, // row 3
    1, // row 3
    1, // row 3
    0, // row 4
    0, // row 4
    0, // row 4
    0, // row 4
    1, // row 4
    0, // row 4
    1, // row 4
    1, // row 4
    0, // row 5
    0, // row 5
    0, // row 5
    0, // row 5
    1, // row 5
    1, // row 5
    1, // row 5
    0, // row 5
    0, // row 6
    0, // row 6
    0, // row 6
    1, // row 6
    0, // row 6
    1, // row 6
    0, // row 6
    0, // row 6
    0, // row 7
    1, // row 7
    1, // row 7
    0, // row 7
    1, // row 7
    1, // row 7
    0, // row 7
    0, // row 7
    0 };
    ShapeMock shape = new ShapeMock(pixels, width, height, jochreSession);
    ShapeFiller shapeFiller = new ShapeFiller();
    BitSet filledBitSet = shapeFiller.fillBitSet(shape, shape.getBlackAndWhiteBitSet(threshold), 5);
    for (int y = 0; y < height; y++) {
        StringBuilder line = new StringBuilder();
        for (int x = 0; x < width; x++) {
            if (filledBitSet.get(y * width + x))
                line.append("x");
            else
                line.append("o");
        }
        LOG.debug(line.toString());
    }
}
Also used : Config(com.typesafe.config.Config) BitSet(java.util.BitSet) JochreSession(com.joliciel.jochre.JochreSession) Test(org.junit.Test)

Example 5 with JochreSession

use of com.joliciel.jochre.JochreSession in project jochre by urieli.

the class ShapeImplTest method testIsPixelBlackFromContainer.

@Test
public void testIsPixelBlackFromContainer() throws Exception {
    System.setProperty("config.file", "src/test/resources/test.conf");
    ConfigFactory.invalidateCaches();
    Config config = ConfigFactory.load();
    JochreSession jochreSession = new JochreSession(config);
    final int threshold = 100;
    final int width = 8;
    final int height = 8;
    int[] pixels = { // row 0
    0, // row 0
    0, // row 0
    0, // row 0
    0, // row 0
    0, // row 0
    0, // row 0
    0, // row 0
    0, // row 1
    0, // row 1
    1, // row 1
    0, // row 1
    0, // row 1
    0, // row 1
    0, // row 1
    0, // row 1
    0, // row 2
    0, // row 2
    0, // row 2
    0, // row 2
    1, // row 2
    0, // row 2
    0, // row 2
    1, // row 2
    1, // row 3
    0, // row 3
    0, // row 3
    1, // row 3
    1, // row 3
    1, // row 3
    0, // row 3
    0, // row 3
    1, // row 4
    0, // row 4
    0, // row 4
    0, // row 4
    1, // row 4
    1, // row 4
    1, // row 4
    1, // row 4
    1, // row 5
    0, // row 5
    1, // row 5
    0, // row 5
    0, // row 5
    0, // row 5
    0, // row 5
    0, // row 5
    0, // row 6
    0, // row 6
    1, // row 6
    1, // row 6
    0, // row 6
    0, // row 6
    0, // row 6
    0, // row 6
    0, // row 7
    0, // row 7
    0, // row 7
    1, // row 7
    1, // row 7
    0, // row 7
    0, // row 7
    0, // row 7
    0 };
    SourceImage sourceImage = new SourceImageMock(pixels, height, width, jochreSession);
    sourceImage.setWhiteGapFillFactor(0);
    sourceImage.setBlackThreshold(threshold);
    Shape shape = new Shape(sourceImage, jochreSession);
    shape.setTop(2);
    shape.setLeft(2);
    shape.setBottom(4);
    shape.setRight(7);
    for (int i = 0; i < shape.getHeight(); i++) {
        String line = "";
        for (int j = 0; j < shape.getWidth(); j++) {
            boolean expectedBlack = sourceImage.getAbsolutePixel(j + shape.getLeft(), i + shape.getTop()) == 0;
            boolean actualBlack = shape.isPixelBlack(j, i, threshold);
            if (actualBlack)
                line += "x";
            else
                line += "o";
            assertEquals("Wrong value at (" + j + "," + i + ")", expectedBlack, actualBlack);
        }
        LOG.debug(line);
    }
}
Also used : Config(com.typesafe.config.Config) JochreSession(com.joliciel.jochre.JochreSession) Test(org.junit.Test)

Aggregations

JochreSession (com.joliciel.jochre.JochreSession)40 Config (com.typesafe.config.Config)34 Test (org.junit.Test)34 BufferedImage (java.awt.image.BufferedImage)20 ArrayList (java.util.ArrayList)13 InputStream (java.io.InputStream)10 Paragraph (com.joliciel.jochre.graphics.Paragraph)8 RowOfShapes (com.joliciel.jochre.graphics.RowOfShapes)8 SourceImage (com.joliciel.jochre.graphics.SourceImage)8 Segmenter (com.joliciel.jochre.graphics.Segmenter)7 Shape (com.joliciel.jochre.graphics.Shape)7 ImagePixelGrabber (com.joliciel.jochre.utils.graphics.ImagePixelGrabber)7 JochreImage (com.joliciel.jochre.graphics.JochreImage)6 Rectangle (java.awt.Rectangle)6 HashMap (java.util.HashMap)6 Session (org.zkoss.zk.ui.Session)6 BitSet (java.util.BitSet)5 JochrePage (com.joliciel.jochre.doc.JochrePage)4 SplitFeature (com.joliciel.jochre.boundaries.features.SplitFeature)3 JochreDocument (com.joliciel.jochre.doc.JochreDocument)3