Search in sources :

Example 1 with WritableImageGrid

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

the class InnerEmptyChupchikLowerLeftFeature method checkInternal.

@Override
public FeatureResult<Boolean> checkInternal(ShapeWrapper shapeWrapper, RuntimeEnvironment env) {
    Shape shape = shapeWrapper.getShape();
    BitSet bitset = shape.getBlackAndWhiteBitSet(shape.getJochreImage().getBlackThreshold());
    boolean[][] grid = new boolean[shape.getWidth()][shape.getHeight()];
    for (int i = 0; i < shape.getWidth(); i++) {
        for (int j = 0; j < shape.getHeight(); j++) {
            if (bitset.get(j * shape.getWidth() + i))
                grid[i][j] = true;
        }
    }
    int startX = shape.getWidth() / 2;
    int startY = shape.getHeight() / 2;
    while (startY < shape.getHeight() && grid[startX][startY]) {
        startY += 1;
    }
    WritableImageGrid mirror = new ImageMirror(shape);
    boolean foundChupchikOrOpening = false;
    if (startY < shape.getHeight()) {
        Stack<HorizontalLineSegment> whiteLineStack = new Stack<HorizontalLineSegment>();
        Set<HorizontalLineSegment> whiteLineSet = new TreeSet<HorizontalLineSegment>();
        HorizontalLineSegment startLine = new HorizontalLineSegment(startX, startY);
        whiteLineStack.push(startLine);
        while (!whiteLineStack.empty()) {
            HorizontalLineSegment line = whiteLineStack.pop();
            if (line.y == shape.getHeight() - 1) {
                // found opening to the outside world
                if (LOG.isTraceEnabled())
                    LOG.trace("Reached edge: found opening");
                foundChupchikOrOpening = true;
                break;
            }
            if (mirror.getPixel(line.xLeft, line.y) == 1)
                continue;
            // extend this line to the right and left
            for (int i = line.xLeft; i >= 0; i--) {
                if (!grid[i][line.y])
                    line.xLeft = i;
                else
                    break;
            }
            for (int i = line.xRight; i <= startX; i++) {
                if (!grid[i][line.y])
                    line.xRight = i;
                else
                    break;
            }
            if (LOG.isTraceEnabled())
                LOG.trace(line.toString());
            whiteLineSet.add(line);
            for (int i = line.xLeft; i <= line.xRight; i++) {
                mirror.setPixel(i, line.y, 1);
            }
            // find lines below and to the left
            if (line.y < shape.getHeight() - 1) {
                boolean inLine = false;
                int row = line.y + 1;
                int xLeft = 0;
                for (int i = line.xLeft; i <= line.xRight; i++) {
                    if (!inLine && !grid[i][row]) {
                        inLine = true;
                        xLeft = i;
                    } else if (inLine && grid[i][row]) {
                        HorizontalLineSegment newLine = new HorizontalLineSegment(xLeft, row);
                        newLine.xRight = i - 1;
                        whiteLineStack.push(newLine);
                        inLine = false;
                    }
                }
                if (inLine) {
                    HorizontalLineSegment newLine = new HorizontalLineSegment(xLeft, row);
                    newLine.xRight = line.xRight;
                    whiteLineStack.push(newLine);
                }
            }
        }
        if (!foundChupchikOrOpening) {
            // if (LOG.isDebugEnabled()) {
            // LOG.trace("List of lines");
            // for (HorizontalLineSegment line : whiteLineSet) {
            // LOG.trace(line.toString());
            // }
            // }
            Iterator<HorizontalLineSegment> iLines = whiteLineSet.iterator();
            HorizontalLineSegment bottomLeftLine = iLines.next();
            double threshold = shape.getWidth() / 8;
            if (LOG.isTraceEnabled())
                LOG.trace("Length threshold: " + threshold);
            HorizontalLineSegment nextLine = null;
            List<HorizontalLineSegment> firstFewLines = new ArrayList<HorizontalLineSegment>();
            firstFewLines.add(bottomLeftLine);
            HorizontalLineSegment currentLine = bottomLeftLine;
            while (iLines.hasNext() && firstFewLines.size() < 3) {
                nextLine = iLines.next();
                if (nextLine.y != currentLine.y) {
                    firstFewLines.add(nextLine);
                    currentLine = nextLine;
                }
            }
            boolean mightHaveChupchik = true;
            HorizontalLineSegment prevLine = null;
            for (HorizontalLineSegment line : firstFewLines) {
                if (LOG.isTraceEnabled())
                    LOG.trace("Next line left, " + bottomLeftLine.xLeft + ", length: " + bottomLeftLine.length() + ", threshold: " + threshold);
                if (line.length() > threshold) {
                    mightHaveChupchik = false;
                    break;
                }
                if (prevLine != null) {
                    if (line.xLeft + 2 < prevLine.xLeft) {
                        mightHaveChupchik = false;
                        break;
                    }
                    if (line.length() + 1 < prevLine.length()) {
                        mightHaveChupchik = false;
                        break;
                    }
                }
                prevLine = line;
                threshold = threshold * 1.2;
            }
            if (mightHaveChupchik)
                foundChupchikOrOpening = true;
        }
    }
    FeatureResult<Boolean> outcome = this.generateResult(foundChupchikOrOpening);
    return outcome;
}
Also used : ImageMirror(com.joliciel.jochre.graphics.ImageMirror) Shape(com.joliciel.jochre.graphics.Shape) BitSet(java.util.BitSet) ArrayList(java.util.ArrayList) Stack(java.util.Stack) TreeSet(java.util.TreeSet) WritableImageGrid(com.joliciel.jochre.graphics.WritableImageGrid)

Aggregations

ImageMirror (com.joliciel.jochre.graphics.ImageMirror)1 Shape (com.joliciel.jochre.graphics.Shape)1 WritableImageGrid (com.joliciel.jochre.graphics.WritableImageGrid)1 ArrayList (java.util.ArrayList)1 BitSet (java.util.BitSet)1 Stack (java.util.Stack)1 TreeSet (java.util.TreeSet)1