Algorithm 连接组件标签-实现
几天前我问了一个类似的问题,但我还没有找到一个有效的方法来解决我的问题。 我正在开发一个简单的控制台游戏,我有一个如下的2D阵列: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)时
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)
{
如果(y2 cout您也可以尝试这种传递闭包方法,但是当图像中有许多分离的对象时,传递闭包的三重循环会减慢速度,建议更改代码
干杯
戴夫
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("");
}
}
}