贴标签处理:对二值图像中的每个不同的连通域进行不同的编号,来区分不同的连通域。
假定二值图像为f,标签图像为g,贴标签的算法步骤如下:
(1)设标签flag=0,已贴标签数N=0,按照从左到右,从上到下的顺序进行扫描,寻找像素值为1的目标像素点;
(2)对未贴标签的目标点像素f(i,j),根据已经扫描的四个邻接像素(8连通),进行如下判断:
①4连通 ②8连通
如果四个邻接像素的值都为0(表示背景),则flag=flag+1,g(i,j)=flag,已贴标签数N=N+1;
如果其标签值相同,即全部为flag,则g(i,j)=flag;
如果标签值有两种:flag和flag',(0<flag<flag'),令g(i,j)=flag,将所有已经贴标签为flag'的改为flag,同时将标签数进行修正,N=N-1。
(3)将所有像素都进行第(2)步的处理,直到处理完毕;
(4)判断flag是否等于N,如果不相等,则表明标签是不连续的编号,需进行映射编码;如果相等,则完成了贴标签操作。
下面为代码实现部分:
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
import java.util.TreeSet;
public class AttachLabel {
public static final int[] dX = { 0, -1, -1, -1 };
public static final int[] dY = { -1, -1, 0, 1 };
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String[] str = sc.nextLine().split(",");
int m = Integer.parseInt(str[0]);
int n = Integer.parseInt(str[1]);
int[][] map = new int[m][n];
for (int i = 0; i < m; i++) {
String[] strs = sc.nextLine().split(",");
for (int j = 0; j < n; j++)
map[i][j] = Integer.parseInt(strs[j]);
}
sc.close();
//int[] result=searchIce(m,n,map);//方法一
int[] result = connectDomain(m, n, map);//方法二
System.out.println(result[0] + "," + result[1]);
}
public static int[] connectDomain(int m, int n, int[][] map) {
int[] result = new int[2];
int[][] status = new int[m][n];// 标签图像
int flag = 0;//标签
int N = 0;// 标签数
for (int x = 0; x < m; x++) {
for (int y = 0; y < n; y++) {
if (map[x][y] == 1) {
int[] tempX = new int[4];
int[] tempY = new int[4];
for (int i = 0; i < 4; i++) {
tempX[i] = x + dX[i];
tempY[i] = y + dY[i];
}
if (x == 0 && y == 0) {
flag = flag + 1;
status[x][y] = flag;
N = N + 1;
} else if (x == 0 && y > 0) {// 第一行
if (status[tempX[0]][tempY[0]] == 0) {
flag = flag + 1;
status[x][y] = flag;
N = N + 1;
} else if (status[tempX[0]][tempY[0]] == flag) {
status[x][y] = flag;
}
} else if (x > 0 && y == 0) {//第一列
if (status[tempX[2]][tempY[2]] == 0 && status[tempX[3]][tempY[3]] == 0) {
flag = flag + 1;
status[x][y] = flag;
N = N + 1;
} else if (status[tempX[2]][tempY[2]] == flag && status[tempX[3]][tempY[3]] == flag) {
status[x][y] = flag;
} else {
Set<Integer> st=new TreeSet<>();
int flag_p=flag;
for (int k = 2; k < 4; k++) {
if (status[tempX[k]][tempY[k]] != 0) {
st.add(status[tempX[k]][tempY[k]]);
}
}
for(Integer s:st) {
flag_p = s;
break;
}
status[x][y] = flag_p;
if(st.size()==2) {
for (int k = 2; k < 4; k++) {
if (status[tempX[k]][tempY[k]] != 0) {
status[tempX[k]][tempY[k]] = flag_p;
}
}
N = N - 1;
}
}
} else if (x > 0 && y == n - 1) {//最后一列
if (status[tempX[0]][tempY[0]] == 0 && status[tempX[1]][tempY[1]] == 0
&& status[tempX[2]][tempY[2]] == 0) {
flag = flag + 1;
status[x][y] = flag;
N = N + 1;
} else if (status[tempX[0]][tempY[0]] == flag && status[tempX[1]][tempY[1]] == flag
&& status[tempX[2]][tempY[2]] == flag) {
status[x][y] = flag;
} else {
Set<Integer> st=new TreeSet<>();
int flag_p=flag;
for (int k = 0; k < 3; k++) {
if (status[tempX[k]][tempY[k]] != 0) {
st.add(status[tempX[k]][tempY[k]]);
}
}
for(Integer s:st) {
flag_p = s;
break;
}
status[x][y] = flag_p;
if(st.size()==2) {
for (int k = 0; k < 3; k++) {
if (status[tempX[k]][tempY[k]] != 0) {
status[tempX[k]][tempY[k]] = flag_p;
}
}
N = N - 1;
}
}
} else if (x > 0 && y > 0 && y < n - 1) {//其余的行和列
if (status[tempX[0]][tempY[0]] == 0 && status[tempX[1]][tempY[1]] == 0
&& status[tempX[2]][tempY[2]] == 0 && status[tempX[3]][tempY[3]] == 0) {
flag = flag + 1;
status[x][y] = flag;
N = N + 1;
} else if (status[tempX[0]][tempY[0]] == flag && status[tempX[1]][tempY[1]] == flag
&& status[tempX[2]][tempY[2]] == flag && status[tempX[3]][tempY[3]] == flag) {
status[x][y] = flag;
} else {
Set<Integer> st=new TreeSet<>();
int flag_p=flag;
for (int k = 0; k < 4; k++) {
if (status[tempX[k]][tempY[k]] != 0) {
st.add(status[tempX[k]][tempY[k]]);
}
}
for(Integer s:st) {
flag_p = s;
break;
}
status[x][y] = flag_p;
if(st.size()==2) {
for (int k = 0; k < 4; k++) {
if (status[tempX[k]][tempY[k]] != 0) {