Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/359.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 查找图像二值对象的周长_Java_Image_Algorithm_Image Processing_Pattern Recognition - Fatal编程技术网

Java 查找图像二值对象的周长

Java 查找图像二值对象的周长,java,image,algorithm,image-processing,pattern-recognition,Java,Image,Algorithm,Image Processing,Pattern Recognition,我试图找到二元物体的周长 考虑下面的图片 [ 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 ] 标记的图像将如下所示 [ 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 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 ]
标记的图像将如下所示

[ 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 ]
我还收集了数组列表中的每个对象像素

例如,对于4个标记的对象,列表将

{ (5,4), (5,5) , (6,4), (6,5) }
面积只是每个对象像素阵列的大小,但我如何才能找到周长,我是否应该再次迭代整个图像,查找单元的邻居,检查它是否是对象的角像素,或者有更简单的方法,仅基于坐标进行此操作


请建议最容易找到周长的方法,任何代码示例都将受到高度赞赏

尝试对您的图像进行广度优先搜索,(或者遍历您的点列表),并标记与不属于同一组的另一个像素相邻的每个像素

我不清楚您想要的周长是请求对象外部边缘上的每个像素,还是对象边界上的每个像素。我现在就假设前者

设置图像: 下面是你将如何着手做这件事。首先,将图像设置为二维阵列,每个像素都标有组号:

[ 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 ]
加载此文件的一个好方法是使用
扫描仪
对象逐个获取每个点:

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);
}
这将对象(由我们的
对象集合“
”表示)放入一个
布尔
的网格中。我们只需要担心这一个对象,所以不需要加载任何其他对象。现在来看看周界上有哪些点

递归方法: 迭代法: 这与上面的非常相似,但直接跳到将周界点放入列表中

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;
        }
    }
}
int[]deltaX={-1,0,1,-1,1,-1,0,1},
deltaY={1,-1,-1,0,0,1,1,1};
外部:用于(点p:点){
内部:for(int i=0;i=宽度| | newY=高度){
add(p);//如果您决定与图像的边缘相邻,则视为在周长上
继续对外开放;
}
//检查我们正在考虑的新点是否不是图像的一部分
if(binaryImage[p.getX()][p.getY()!=binaryImage[newX][newY]){
//如果不是,那么点p必须在周界上
增加(p);
继续对外开放;
}
}
}
注意标签
外部:
内部:
。这让我们可以选择在说
continue outer时跳过哪个for循环

好了!这将帮助您以二进制图像或列表的形式获取任何对象的周长

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));
        }
    }
}
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;
        }
    }
}