简体   繁体   中英

Create polygon of non-transparent parts of image

What I am trying to achieve is getting a mask of an image , converting it into an Array with the dimensions (image.getWidth(), image.getHeight()) , then getting all the pixels and seeing if they have an alpha value of 0 .

IF they do, then:

  • add value 1 for the x, y co-ordinate that I am examining at the moment.

ELSE:

  • add value 0 for the x, y co-ordinate that I am examining at the moment.

Up to this point, I know how to program this. If you are interested, this is the code I am using:

private int[] createMask(BufferedImage image) {

    final int[] pixels = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
    final int width = image.getWidth();
    final int height = image.getHeight();
    final boolean hasAlphaChannel = image.getAlphaRaster() != null;

    int[][] result = new int[height][width];
    if (hasAlphaChannel) {
        for (int pixel = 0, row = 0, col = 0; pixel < pixels.length; pixel += 4) {
            int alpha = pixels[pixel];
            if(alpha != 0) {
                result[row][col] = 1;
            } else {
                result[row][col] = 0;
            }

            if (col == width) {
                col = 0;
                row++;
            }
        } 
    }

    return result;
}

After I get this mask, I am attempting to use this Array to draw a Polygon via this code, or an alternation of it (obtained from http://docs.oracle.com/javase/tutorial/2d/geometry/arbitrary.html ) :

    int x1Points[] = {0, 100, 0, 100};
    int y1Points[] = {0, 50, 50, 0};
    GeneralPath polygon = 
    new GeneralPath(GeneralPath.WIND_EVEN_ODD,
                    x1Points.length);
    polygon.moveTo(x1Points[0], y1Points[0]);

    for (int index = 1; index < x1Points.length; index++) {
        polygon.lineTo(x1Points[index], y1Points[index]);
    };

    polygon.closePath();
    g2.draw(polygon);

However, I need to create a method which gives me all the co-ordinates in an Array consisting of Point objects to go around the image to essentially create a "mask".

    public Point[] getCords(int[] mask) {
        ArrayList<Point> points = new ArrayList<Point>(); //you can change this to whatever you want to use

        //get coords to surround the mask
        // >> involving `0` (for transparent) and `1` (non transparent) 
        //  >> these are contained in the `mask` Array...

        return points.toArray(new Points[0]);

So, to conclude:

  • I require to obtain a polygon that outlines an image's visible pixels from an int[] array which contains the values 1 's and 0 's, the former for non-transparent pixel and latter for transparent pixel, respectively.

(link to related java code below)

To create the mask border, do the following: for each pair of coordinates (x,y) check if any one of 8 its neighboring points is outside the mask. However, keep in mind that the resulting mask isn't necessarily 1 pixel wide and vectorizing it might be non-trivial, as in this example (white is the masked area, red is the mask border inside the mask, black is unmasked area):

蒙版边框为红色

Luckily, even if you get a wider-than-1-pixel border in some places in your mask, you can workaround that by rejecting some pixels of the mask from that mask building a submask that is polygonizable. The following image shows the submask's border in blue:

子遮罩边框为蓝色

I implemented such algorithm a while ago. There is the code you can use, but it is quite tightly coupled with my solution, however you could find some insights in it: Thick mask border resolution . Its idea is that from the initial mask you build a submask by flood-filling original mask with a predicate that checks that a cell of submask's border has at most 2 cardinal direction neighbors (ordinal direction neighbors don't matter here).

Once you got the blue submask's border, build a graph where vertices are points of submask's border, and edges are between cardinally neighboring points. Then traverse each component of that graph, and for each component you get a list of points that form your polygons.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM