Algorithm 连接组件标签-实现

Algorithm 连接组件标签-实现,algorithm,image-processing,multidimensional-array,area,neighbours,Algorithm,Image Processing,Multidimensional Array,Area,Neighbours,几天前我问了一个类似的问题,但我还没有找到一个有效的方法来解决我的问题。 我正在开发一个简单的控制台游戏,我有一个如下的2D阵列: 1,0,0,0,1 1,1,0,1,1 0,1,0,0,1 1,1,1,1,0 0,0,0,1,0 我正在尝试查找由相邻1(4路连接)组成的所有区域。因此,在本例中,两个区域如下所示: 1 1,1 1 1,1,1,1 1 以及: 我一直在研究的算法,可以找到一个单元的所有邻居,并且可以很好地处理这类矩阵。然而,当我使用更大的数组(如90*90)时

几天前我问了一个类似的问题,但我还没有找到一个有效的方法来解决我的问题。 我正在开发一个简单的控制台游戏,我有一个如下的2D阵列:

1,0,0,0,1
1,1,0,1,1
0,1,0,0,1
1,1,1,1,0
0,0,0,1,0
我正在尝试查找由相邻1(4路连接)组成的所有区域。因此,在本例中,两个区域如下所示:

1
1,1
  1
1,1,1,1
      1
以及:

我一直在研究的算法,可以找到一个单元的所有邻居,并且可以很好地处理这类矩阵。然而,当我使用更大的数组(如90*90)时,程序非常慢,有时使用的巨大数组会导致堆栈溢出

另一个问题上的一个人告诉我,连接组件标签是解决我问题的有效方法

有人能告诉我使用这个算法的任何C++代码,因为我对它如何与不相交的集合数据结构事物一起工作有点困惑……/P>
非常感谢您的帮助和时间。

我将首先向您介绍代码,然后再解释一下:

//方向向量
常量int dx[]={+1,0,-1,0};
常量int dy[]={0,+1,0,-1};
//矩阵维数
int行计数;
国际货币基金组织计数;
//输入矩阵
int m[MAX][MAX];
//标签,0表示未标记
整数标签[MAX][MAX];
无效dfs(整数x、整数y、整数当前_标签){
如果(x<0 | | x==行数)返回;//超出范围
如果(y<0 | | y==col_count)返回;//超出范围
if(label[x][y]| | |!m[x][y])return;//在m中已标记或未标记1
//标记当前单元格
标签[x][y]=当前_标签;
//递归地标记邻居
用于(整数方向=0;方向<4;++方向)
dfs(x+dx[方向],y+dy[方向],当前_标签);
}
void find_components(){
int分量=0;
对于(int i=0;i
这是解决这个问题的常用方法

方向向量只是找到相邻单元(在四个方向中的每一个方向)的好方法

dfs函数对网格执行深度优先搜索。这仅仅意味着它将访问从起始单元可以访问的所有单元。每个单元格将标有当前\u标签

find_components函数遍历网格的所有单元格,如果找到未标记的单元格(标记为1),则启动组件标记

这也可以使用堆栈进行迭代。 如果将堆栈替换为队列,则获得bfs或广度优先搜索。

这可以通过使用解决(尽管如另一个答案所示,DFS可能更简单一些)

此数据结构背后的基本思想是重复合并同一组件中的元素。这是通过将每个组件表示为一棵树来实现的(节点跟踪自己的父节点,而不是相反),您可以通过遍历根节点来检查两个元素是否位于同一组件中,并且您可以通过简单地使一个根成为另一个根的父节点来合并节点

一个简短的代码示例演示了这一点:

const int w=5,h=5;
int输入[w][h]={{1,0,0,1},
{1,1,0,1,1},
{0,1,0,0,1},
{1,1,1,1,0},
{0,0,0,1,0}};
int分量[w*h];
无效双宁(内部a,内部b)
{
//获取a和b的根组件,并将其中一个的父组件设置为另一个
while(组件[a]!=a)
a=成分[a];
while(组件[b]!=b)
b=成分[b];
组分[b]=a;
}
无效联合坐标(整数x,整数y,整数x2,整数y2)
{
如果(y2cout您也可以尝试这种传递闭包方法,但是当图像中有许多分离的对象时,传递闭包的三重循环会减慢速度,建议更改代码

干杯

戴夫

void CC(无符号字符*pBinImage,无符号字符*pOutImage,int-width,int-height,int-CON8)
{
int i,j,x,y,k,maxIndX,maxIndY,sum,ct,newLabel=1,count,maxVal=0,sumVal=0,maxEQ=10000;
int*eq=NULL,列表[4];
int bAdd;
memcpy(pOutImage,pBinImage,width*height*sizeof(unsigned char));
无符号字符*等效=(无符号字符*)calloc(sizeof(无符号字符),maxEQ*maxEQ);
//修改标签这应该通过迭代器来修改元素
//当前列
对于(j=0;j0)
{
如果((i>0))
{
如果((pOutImage[(i-1)+(j-1)*宽度]>0)和(CON8>0))
列表[计数++]=pOutImage[(i-1)+(j-1)*宽度];
}
如果(pOutImage[i+(j-1)*宽度]>0)
{
对于(x=0,bAdd=true;x 0))
{
对于(x=0,bAdd=true;x0)
{
如果(pOutImage[(i-1)+j*宽度]>0)
{
对于(x=0,bAdd=true;x1)
{
//将等价项存储在表中
对于(x=0;x非常有用的文档=>

java应用程序-开源-从图像中提取对象-连接组件标签=>

import java.util.ArrayList;
公共类标签
{
数组列表温度;
ArrayList cc=新的ArrayList();
公共int[]cclabel(布尔值[]主,int w){
/*此方法返回每个数组包含的数组“xycc”的数组
一个连接组件的像素的x,y坐标
       1
     1,1
       1
void CC(unsigned char* pBinImage, unsigned char* pOutImage, int width, int height, int     CON8)
{
int i, j, x, y, k, maxIndX, maxIndY,  sum, ct, newLabel=1, count, maxVal=0, sumVal=0, maxEQ=10000;
int *eq=NULL, list[4];
int bAdd;

memcpy(pOutImage, pBinImage, width*height*sizeof(unsigned char));

unsigned char* equivalences=(unsigned char*) calloc(sizeof(unsigned char), maxEQ*maxEQ);

// modify labels this should be done with iterators to modify elements
// current column
for(j=0; j<height; j++)
{
    // current row
    for(i=0; i<width; i++)
    {
        if(pOutImage[i+j*width]>0)
        {
            count=0;

            // go through blocks
            list[0]=0;
            list[1]=0;
            list[2]=0;
            list[3]=0;

            if(j>0)
            {
                if((i>0))
                {
                    if((pOutImage[(i-1)+(j-1)*width]>0) && (CON8 > 0))
                        list[count++]=pOutImage[(i-1)+(j-1)*width];
                }

                if(pOutImage[i+(j-1)*width]>0)
                {
                    for(x=0, bAdd=true; x<count; x++)
                    {
                        if(pOutImage[i+(j-1)*width]==list[x])
                            bAdd=false;
                    }

                    if(bAdd)
                        list[count++]=pOutImage[i+(j-1)*width];
                }

                if(i<width-1)
                {
                    if((pOutImage[(i+1)+(j-1)*width]>0) && (CON8 > 0))
                    {
                        for(x=0, bAdd=true; x<count; x++)
                        {
                            if(pOutImage[(i+1)+(j-1)*width]==list[x])
                                bAdd=false;
                        }

                        if(bAdd)
                            list[count++]=pOutImage[(i+1)+(j-1)*width];
                    }
                }
            }

            if(i>0)
            {
                if(pOutImage[(i-1)+j*width]>0)
                {
                    for(x=0, bAdd=true; x<count; x++)
                    {
                        if(pOutImage[(i-1)+j*width]==list[x])
                            bAdd=false;
                    }

                    if(bAdd)
                        list[count++]=pOutImage[(i-1)+j*width];
                }
            }

            // has a neighbour label
            if(count==0)
                pOutImage[i+j*width]=newLabel++;
            else
            {
                pOutImage[i+j*width]=list[0];

                if(count>1)
                {
                    // store equivalences in table
                    for(x=0; x<count; x++)
                        for(y=0; y<count; y++)
                            equivalences[list[x]+list[y]*maxEQ]=1;
                }

            }
        }
    }
}

 // floyd-Warshall algorithm - transitive closure - slow though :-(
 for(i=0; i<newLabel; i++)
    for(j=0; j<newLabel; j++)
    {
        if(equivalences[i+j*maxEQ]>0)
        {
            for(k=0; k<newLabel; k++)
            {
                equivalences[k+j*maxEQ]= equivalences[k+j*maxEQ] || equivalences[k+i*maxEQ];
            }
        }
    }


eq=(int*) calloc(sizeof(int), newLabel);

for(i=0; i<newLabel; i++)
    for(j=0; j<newLabel; j++)
    {
        if(equivalences[i+j*maxEQ]>0)
        {
            eq[i]=j;
            break;
        }
    }


free(equivalences);

// label image with equivalents
for(i=0; i<width*height; i++)
{
    if(pOutImage[i]>0&&eq[pOutImage[i]]>0)
        pOutImage[i]=eq[pOutImage[i]];
}

free(eq);
}
    import java.util.ArrayList;

public class cclabeling

{

 int neighbourindex;ArrayList<Integer> Temp;

 ArrayList<ArrayList<Integer>> cc=new ArrayList<>();

 public int[][][] cclabel(boolean[] Main,int w){

 /* this method return array of arrays "xycc" each array contains 

 the x,y coordinates of pixels of one connected component 

 – Main => binary array of image 

 – w => width of image */

long start=System.nanoTime();

int len=Main.length;int id=0;

int[] dir={-w-1,-w,-w+1,-1,+1,+w-1,+w,+w+1};

for(int i=0;i<len;i+=1){

if(Main[i]){

Temp=new ArrayList<>();

Temp.add(i);

for(int x=0;x<Temp.size();x+=1){

id=Temp.get(x);

for(int u=0;u<8;u+=1){

neighbourindex=id+dir[u];

 if(Main[neighbourindex]){ 

 Temp.add(neighbourindex);

 Main[neighbourindex]=false;

 }

 }

Main[id]=false;

}

cc.add(Temp);

    }

}

int[][][] xycc=new int[cc.size()][][];

int x;int y;

for(int i=0;i<cc.size();i+=1){

 xycc[i]=new int[cc.get(i).size()][2];



 for(int v=0;v<cc.get(i).size();v+=1){

 y=Math.round(cc.get(i).get(v)/w);

 x=cc.get(i).get(v)-y*w;

 xycc[i][v][0]=x;

 xycc[i][v][1]=y;

 }



}

long end=System.nanoTime();

long time=end-start;

System.out.println("Connected Component Labeling Time =>"+time/1000000+" milliseconds");

System.out.println("Number Of Shapes => "+xycc.length);

 return xycc;



 }

}
package addressextraction;

public class ConnectedComponentLabelling {

    int[] dx={+1, 0, -1, 0};
    int[] dy={0, +1, 0, -1};
    int row_count=0;
    int col_count=0;
    int[][] m;
    int[][] label;

    public ConnectedComponentLabelling(int row_count,int col_count) {
        this.row_count=row_count;
        this.col_count=col_count;
        m=new int[row_count][col_count];
        label=new int[row_count][col_count];
    }

    void dfs(int x, int y, int current_label) {
          if (x < 0 || x == row_count) return; // out of bounds
          if (y < 0 || y == col_count) return; // out of bounds
          if (label[x][y]!=0 || m[x][y]!=1) return; // already labeled or not marked with 1 in m

          // mark the current cell
          label[x][y] = current_label;
         // System.out.println("****************************");

          // recursively mark the neighbors
          int direction = 0;
          for (direction = 0; direction < 4; ++direction)
            dfs(x + dx[direction], y + dy[direction], current_label);
        }

    void find_components() {
          int component = 0;
          for (int i = 0; i < row_count; ++i) 
            for (int j = 0; j < col_count; ++j) 
              if (label[i][j]==0 && m[i][j]==1) dfs(i, j, ++component);
        }


    public static void main(String[] args) {
        ConnectedComponentLabelling l=new ConnectedComponentLabelling(4,4);
        l.m[0][0]=0;
        l.m[0][1]=0;
        l.m[0][2]=0;
        l.m[0][3]=0;

        l.m[1][0]=0;
        l.m[1][1]=1;
        l.m[1][2]=0;
        l.m[1][3]=0;

        l.m[2][0]=0;
        l.m[2][1]=0;
        l.m[2][2]=0;
        l.m[2][3]=0;

        l.m[3][0]=0;
        l.m[3][1]=1;
        l.m[3][2]=0;
        l.m[3][3]=0;

        l.find_components();

        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 4; j++) {
                System.out.print(l.label[i][j]);
            }
            System.out.println("");

        }


    }

}