How to find the corner pixels of a rectangle?

Given a simple monochrome bitmap that contains a single, randomly rotated rectangle. How can I find the left / top, left / bottom, right / bottom, and right / top angular positions of a rectangle inside a bitmap?

For example, a bitmap looks like this, where X marks the pixels in question:

......... ......... ......... .........
.X11111X. ....X.... ..X11.... ....11X..
.1111111. ...111... ..11111X. X111111..
.1111111. ..X111X.. ..111111. .111111..
.X11111X. ...111... .1111111. .1111111.
......... ....X.... .111111.. ..111111.
......... ......... .X11111.. ..11111X.
......... ......... ....11X.. ..X11....
......... ......... ......... .........

I apologize for the bad art of ascii. For the second example, the corner pixel at the top can be either a left / top rectangle or a right / top corner. Curious.

What steps are needed to determine the angular pixels / positions in the above examples?

+4
source share
4

- , . . .

( , ).

. . - , .

Y, x. - , (x0-x1) , x0 , x1 .

.

, , , - . , , , , if. - x ys , , if.

+3

. , : " ". :

......... ......... .......... ...XX.... ....X.... ....XX.... ..X11X... ...111... ...1111... ..X11X... ..X111X.. ..X1111X.. ...XX.... ...111... ..X1111X.. ......... ....X.... ...X11X... ......... ......... ....XX.... ......... ......... ..........

, +1 -1, . . .

+1
  • .
  • .

    public class Test {
    
        String[][] squares = {
            {
                ".........",
                ".X11111X.",
                ".1111111.",
                ".1111111.",
                ".X11111X.",
                ".........",
                ".........",
                ".........",
                ".........",},
            {
                ".........",
                "....X....",
                "...111...",
                "..X111X..",
                "...111...",
                "....X....",
                ".........",
                ".........",
                ".........",},
            {
                ".........",
                "..X11....",
                "..11111X.",
                "..111111.",
                ".1111111.",
                ".111111..",
                ".X11111..",
                "....11X..",
                ".........",},
            {
                ".........",
                "....11X..",
                "X111111..",
                ".111111..",
                ".1111111.",
                "..111111.",
                "..11111X.",
                "..X11....",
                ".........",}};
    
        private static final int WHITE = 0;
        private static final int BLACK = 1;
    
        class Point {
    
            private final int x;
            private final int y;
    
            public Point(Point p) {
                this.x = p.x;
                this.y = p.y;
            }
    
            public Point(int x, int y) {
                this.x = x;
                this.y = y;
            }
    
            @Override
            public String toString() {
                return "{" + x + "," + y + '}';
            }
    
            // What colour is there?
            public int colour(int[][] bmp) {
                // Make everything off-bmp black.
                if (x < 0 || y < 0 || y >= bmp.length || x >= bmp[y].length) {
                    return BLACK;
                }
                return bmp[y][x];
            }
    
            private Point step(Point d) {
                return new Point(x + d.x, y + d.y);
            }
    
        }
    
        class Rectangle {
    
            private final Point[] corners = new Point[4];
    
            public Rectangle(Point[] corners) {
                // Points are immutable but corners are not.
                System.arraycopy(corners, 0, this.corners, 0, corners.length);
            }
    
            public Rectangle(Rectangle r) {
                this(r.corners());
            }
    
            public Rectangle(Point a, Point b, Point c, Point d) {
                corners[0] = a;
                corners[1] = b;
                corners[2] = c;
                corners[3] = d;
            }
    
            private Rectangle(Point tl, Point br) {
                this(tl, new Point(br.x, tl.y), br, new Point(tl.x, br.y));
            }
    
            public Point[] corners() {
                return Arrays.copyOf(corners, corners.length);
            }
    
            @Override
            public String toString() {
                return Arrays.toString(corners);
            }
    
        }
    
        private Rectangle getBoundingBox(int[][] bmp) {
            int minX = Integer.MAX_VALUE, minY = Integer.MAX_VALUE, maxX = 0, maxY = 0;
            for (int r = 0; r < bmp.length; r++) {
                for (int c = 0; c < bmp[r].length; c++) {
                    if (bmp[r][c] != WHITE) {
                        if (minX > c) {
                            minX = c;
                        }
                        if (minY > r) {
                            minY = r;
                        }
                        if (maxX < c) {
                            maxX = c;
                        }
                        if (maxY < r) {
                            maxY = r;
                        }
                    }
                }
            }
            return new Rectangle(new Point(minX, minY), new Point(maxX, maxY));
        }
    
        Point[] clockwise = new Point[]{
            new Point(1, 0),
            new Point(0, 1),
            new Point(-1, 0),
            new Point(0, -1)};
    
        private void test(int[][] bmp) {
            // Find the bounding box.
            Rectangle bBox = getBoundingBox(bmp);
            System.out.println("bbox = " + bBox);
            Point[] corners = bBox.corners();
            // Move each corner clockwise until it is black.
            for (int p = 0; p < corners.length; p++) {
                while (corners[p].colour(bmp) == WHITE) {
                    corners[p] = corners[p].step(clockwise[p]);
                }
            }
            System.out.println("rect = " + new Rectangle(corners));
        }
    
        private void test(String[] square) {
            // Build the int[][].
            // . -> White
            // X/1 -> Black
            int[][] bmp = new int[square.length][];
            for (int r = 0; r < square.length; r++) {
                bmp[r] = new int[square[r].length()];
                for (int c = 0; c < bmp[r].length; c++) {
                    switch (square[r].charAt(c)) {
                        case '.':
                            bmp[r][c] = WHITE;
                            break;
                        case 'X':
                        case '1':
                            bmp[r][c] = BLACK;
                            break;
                    }
                }
            }
            test(bmp);
        }
    
        public void test() {
            for (String[] square : squares) {
                test(square);
            }
        }
    
        public static void main(String args[]) {
            try {
                new Test().test();
            } catch (Throwable t) {
                t.printStackTrace(System.err);
            }
        }
    
    }
    

    bbox = [{1,1}, {7,1}, {7,4}, {1,4}]
    rect = [{1,1}, {7,1}, {7,4}, {1,4}]
    bbox = [{2,1}, {6,1}, {6,5}, {2,5}]
    rect = [{4,1}, {6,3}, {4,5}, {2,3}]
    bbox = [{1,1}, {7,1}, {7,7}, {1,7}]
    rect = [{2,1}, {7,2}, {6,7}, {1,6}]
    bbox = [{0,1}, {7,1}, {7,7}, {0,7}]
    rect = [{4,1}, {7,4}, {4,7}, {0,2}]

.

0

, , .

: , , , .

, . , .

0

Source: https://habr.com/ru/post/1620551/


All Articles