Une petite classe java pour calculer la carte des distances par la méthode des masques de Chamfer.

La methode compute() prend en entré un tableau binaire et retourne un tableau de flotant. Chaque case [x][y] du tableau contient la distance entre le pixel [x][y] et le "1" le plus proche dans l'image binaire.


A gauche: l'image binaire en entrée
A droite: la carte des distances (l'intensité représente la distance)

Code java : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
 
/**
 * Chamfer distance
 * 
 * @author Code by Xavier Philippeau <br> Kernels by Verwer, Borgefors and Thiel 
 */
public class ChamferDistance  {
 
	public final static int[][] cheessboard = new int[][] {
		new int[] {1,0,1},
		new int[] {1,1,1}
	};
 
	public final static int[][] chamfer3 = new int[][] {
		new int[] {1,0,3},
		new int[] {1,1,4}
	};
 
	public final static int[][] chamfer5 = new int[][] {
		new int[] {1,0,5},
		new int[] {1,1,7},
		new int[] {2,1,11}
	};
 
	public final static int[][] chamfer7 = new int[][] {
		new int[] {1,0,14},
		new int[] {1,1,20},
		new int[] {2,1,31},
		new int[] {3,1,44}
	};
 
	public final static int[][] chamfer13 = new int[][] {
		new int[] { 1,  0,  68},
		new int[] { 1,  1,  96},
		new int[] { 2,  1, 152},
		new int[] { 3,  1, 215},
		new int[] { 3,  2, 245},
		new int[] { 4,  1, 280},
		new int[] { 4,  3, 340},
		new int[] { 5,  1, 346},
		new int[] { 6,  1, 413}
	};
 
	private int[][] chamfer = null; 
	private int normalizer = 0; 
 
	private int width=0,height=0;
 
	public ChamferDistance() {
		this(ChamferDistance.chamfer3);
	}
 
	public ChamferDistance(int[][] chamfermask) {
		this.chamfer = chamfermask;
		this.normalizer = this.chamfer[0][2];
	}
 
	private void testAndSet(double[][] output, int x, int y, double newvalue) {
		if(x<0 || x>=this.width) return;
		if(y<0 || y>=this.height) return;
		double v = output[x][y];
		if (v>=0 && v<newvalue) return;
		output[x][y] = newvalue;
	}
 
	public double[][] compute(boolean[][] input, int width, int height) {
 
		this.width = width;
		this.height = height;
		double[][] output = new double[width][height]; 
 
		// initialize distance
		for (int y=0; y<height; y++)
			for (int x=0; x<width; x++)
				if (  input[x][y] )
					output[x][y]=0; // inside the object -> distance=0
				else
					output[x][y]=-1; // outside the object -> to be computed
 
		// forward
		for (int y=0; y<=height-1; y++) {
			for (int x=0; x<=width-1; x++) {
				double v = output[x][y];
				if (v<0) continue;
				for(int k=0;k<chamfer.length;k++) {
					int dx = chamfer[k][0];
					int dy = chamfer[k][1];
					int dt = chamfer[k][2];
 
					testAndSet(output, x+dx, y+dy, v+dt);
					if (dy!=0) testAndSet(output, x-dx, y+dy, v+dt);
					if (dx!=dy) {
						testAndSet(output, x+dy, y+dx, v+dt);
						if (dy!=0) testAndSet(output, x-dy, y+dx, v+dt);
					}
				}
			}
		}
 
		// backward
		for (int y=height-1; y>=0; y--) {
			for (int x=width-1; x>=0; x--) {
				double v = output[x][y];
				if (v<0) continue;
				for(int k=0;k<chamfer.length;k++) {
					int dx = chamfer[k][0];
					int dy = chamfer[k][1];
					int dt = chamfer[k][2];
 
					testAndSet(output, x-dx, y-dy, v+dt);
					if (dy!=0) testAndSet(output, x+dx, y-dy, v+dt);
					if (dx!=dy) {
						testAndSet(output, x-dy, y-dx, v+dt);
						if (dy!=0) testAndSet(output, x+dy, y-dx, v+dt);
					}
				}
			}
		}
 
		// normalize
		for (int y=0; y<height; y++)
			for (int x=0; x<width; x++)
				output[x][y] = output[x][y]/normalizer;
 
		return output;
	}
}

exemple d'utilisation:
Code java : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
 
double[][] distancemap = new ChamferDistance(ChamferDistance.chamfer5).compute(binaryarray, 300, 200);