i trying find perimeter of binary object.
consider following picture
[ 0 0 0 0 1 1 0 ] [ 0 0 1 0 0 0 0 ] [ 0 1 1 0 1 1 0 ] [ 0 1 1 0 0 1 0 ] [ 0 1 1 1 0 0 0 ] [ 0 1 0 0 1 1 0 ] [ 0 0 0 0 1 1 0 ]
labeled image this
[ 0 0 0 0 1 1 0 ] [ 0 0 2 0 0 0 0 ] [ 0 2 2 0 3 3 0 ] [ 0 2 2 0 0 3 0 ] [ 0 2 2 0 0 0 0 ] [ 0 2 0 0 4 4 0 ] [ 0 0 0 0 4 4 0 ]
also collected each object pixels in array list
so example 4 marked object list
{ (5,4), (5,5) , (6,4), (6,5) }
area size of each object pixel array, how can find perimeter, should again iterate on whole image finding neighbors of cell check if corner pixel of object or there easier way basing on coordinates.
please suggest easier way find perimeter, code example highly appreciated
try doing a breadth-first search of image, (or alternatively iterate through list of points), , tag every pixel neighbors pixel isn't of same group.
it's not clear me if perimeter want every pixel on outside edge of requested object, or every pixel borders object. i'll assume former now.
set image:
here's how you'd go doing this. first, set image 2-d array, each pixel labeled group number:
[ 0 0 0 0 1 1 0 ] [ 0 0 2 0 0 0 0 ] [ 0 2 2 0 3 3 0 ] [ 0 2 2 0 0 3 0 ] [ 0 2 2 0 0 0 0 ] [ 0 2 0 0 4 4 0 ] [ 0 0 0 0 4 4 0 ]
a way load use scanner
object each point, 1 one:
list<point> points = new arraylist<>(); scanner scanner = new scanner( /* whatever input source */ ); string pointregex = "\\(\\d,\\d\\)"; //looks "(#,#)" while(!scanner.hasnext(pointregex)){ string pointtext = scanner.next(pointregex); //for example, "(5,4)" point point = getpointfromtext(pointtext); //turns string point points.add(point); }
notice use of scanner.next(string pattern)
. method return next string
looks pattern. (read on regular expressions if want learn more how works.)
now on populating grid:
boolean[][] binaryimage = new boolean[width][height]; for(point p : points){ //iterate through each point inside our list of point objects binaryimage[p.getx()][p.gety()] = true; }
this puts object, represented our collection of point
objects "points
", grid of boolean
s. need worry 1 object, don't need load of others. finding out points on perimeter.
recursive method:
boolean[][] visitedbefore = new boolean[width][height]; boolean[][] isonperimeter = new boolean[width][height]; int[] deltax = {-1, 0, 1, -1, 1, -1, 0, 1}, deltay = {-1, -1, -1, 0, 0, 1, 1, 1}; queue<point> searchnext = new linkedlist<>(); searchnext.add(points.get(0)); //just need 1 point going while(!searchnext.isempty()){ point p = searchnext.remove(); //take what's waiting @ front of queue if(visitedbefore[p.getx()][p.gety()]){ continue; //already check spot! } //mark we've been here visited[p.getx()][p.gety()] = true; //look @ of point's neighbors for(int = 0 ; < deltax.length ; i++){ int newx = p.getx() + deltax[i]; int newy = p.gety() + deltay[i]; //make sure isn't out of bounds if(newx < 0 || newx >= width || newy<0 || newy>=height){ isonperimeter[p.getx()][p.gety()] = true; //if decide bordering edge of image counts being on perimeter continue; } //check if new point we're considering isn't part of image if( binaryimage[p.getx()][p.gety()] != binaryimage[newx][newy] ){ //if isn't, point p must on perimeter isonperimeter[p.getx()][p.gety()] = true; } else { /* otherwise, new point we're considering part of * same object, , part of perimeter. */ searchnext.add(new point(newx, newy)); } } }
now have grid each point on perimeter marked true
. if need these list, picking out points easy:
list<point> perimeter = new arraylist<point>(); for(int x = 0 ; x < isonperimeter.length ; x++) for(int y = 0 ; y < isonperimeter[x].length ; y++) perimeter.add( new point(x,y) );
iterative method:
this pretty similar above, jumps straight putting perimeter points list.
int[] deltax = {-1, 0, 1, -1, 1, -1, 0, 1}, deltay = {-1, -1, -1, 0, 0, 1, 1, 1}; outer: for(point p : points){ inner: for(int = 0 ; < deltax.length ; i++){ int newx = p.getx() + deltax[i]; int newy = p.gety() + deltay[i]; //check if new point we're considering outside image if(newx < 0 || newx >= width || newy<0 || newy>=height){ perimeter.add(p); //if decide bordering edge of image counts being on perimeter continue outer; } //check if new point we're considering isn't part of image if( binaryimage[p.getx()][p.gety()] != binaryimage[newx][newy] ){ //if isn't, point p must on perimeter perimeter.add(p); continue outer; } } }
notice labels outer:
, inner:
. lets choose loop skip along when continue outer;
.
there go! should perimeter of object either binary image or list.
Comments
Post a Comment