嘗試做廣度優先搜索圖像的,(或可替代迭代通過您點的列表)和標記與不屬於同一組的另一個像素相鄰的每個像素。
我不清楚,如果你想要的邊界是所請求的對象的外邊緣上的每個像素,或與該對象的邊界的每個像素。我現在假設前者。
設置圖片:
下面是你如何去做這件事。首先,設置你的圖像作爲2-d陣列,用標記有組號的每個像素:
[ 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 ]
一個好的方式來加載,這將是使用一個Scanner
對象來獲取每個點,一個接一個:
List<Point> points = new ArrayList<>();
Scanner scanner = new Scanner(/* whatever your input source is */);
String pointRegex = "\\(\\d,\\d\\)"; //looks for something like "(#,#)"
while(!scanner.hasNext(pointRegex)){
String pointText = scanner.next(pointRegex); //For example, "(5,4)"
Point point = getPointFromText(pointText); //turns a string into a point
points.add(point);
}
請注意使用Scanner.next(String pattern)
。這是一種方法,將返回看起來像那個模式的下一個String
。在(閱讀上的正則表達式,如果你想了解更多有關如何工作的。)
我們填充網格:
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;
}
這使得對象,通過我們的Point
對象的集合「points
代表「,變成boolean
s的格子。我們只需要擔心這個對象,所以我們不需要加載任何其他對象。現在找出外圍的點。
遞歸方法:
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 one point to get going
while(!searchNext.isEmpty()){
Point p = searchNext.remove(); //take what's waiting at the front of the queue
if(visitedBefore[p.getX()][p.getY()]){
continue; //already check this spot!
}
//mark that we've been here
visited[p.getX()][p.getY()] = true;
//look at all of this Point's neighbors
for(int i = 0 ; i < deltaX.length ; i++){
int newX = p.getX() + deltaX[i];
int newY = p.getY() + deltaY[i];
//make sure this isn't out of bounds
if(newX < 0 || newX >= width || newY<0 || newY>=height){
isOnPerimeter[p.getX()][p.getY()] = true; //if you decide bordering the edge of the image counts as being on the perimeter
continue;
}
//check if this new point we're considering isn't part of the image
if(binaryImage[p.getX()][p.getY()] != binaryImage[newX][newY]){
//if it isn't, then this Point p must be on the perimeter
isOnPerimeter[p.getX()][p.getY()] = true;
} else {
/* otherwise, this new point we're considering is part of the
* same object, and could be part of the perimeter. */
searchNext.add(new Point(newX, newY));
}
}
}
現在你有一個在外線的每個點的網格標記爲true
。如果你需要這些作爲一個列表,挑選出這些點很簡單:
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));
迭代方法:
這是非常類似上面,而是直接跳轉到把周邊點到列表中。
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 i = 0 ; i < deltaX.length ; i++){
int newX = p.getX() + deltaX[i];
int newY = p.getY() + deltaY[i];
//check if this new point we're considering is outside the image
if(newX < 0 || newX >= width || newY<0 || newY>=height){
perimeter.add(p); //if you decide bordering the edge of the image counts as being on the perimeter
continue outer;
}
//check if this new point we're considering isn't part of the image
if(binaryImage[p.getX()][p.getY()] != binaryImage[newX][newY]){
//if it isn't, then this Point p must be on the perimeter
perimeter.add(p);
continue outer;
}
}
}
注意標籤outer:
和inner:
。當我們說continue outer;
時,這讓我們選擇哪個循環跳過。
你走了!這應該可以幫助您將任何對象的邊界視爲二進制圖像或列表。