圖像處理中的倒角距離變換(chamfer distance transform)在對象匹配識別中經常用到,算法基本上是基于3x3的窗口來生成每個像素的距離值,分為兩步完成距離變換,第一步從左上角開始,從左向右、從上到下移動窗口掃描每個像素,檢測在中心像素x的周圍0、1、2、3四個像素,保存最小距離與位置作為結果,圖示如下:
第二步從底向上、從右向左,對每個像素,檢測相鄰像素4、5、6、7保存最小距離與位置作為結果,如圖示所:
完成這兩步以后,得到的結果輸出即為倒角距離變換的結果。完整的圖像倒角距離變換代碼實現可以分為如下幾步:
1.對像素數組進行初始化,所有背景顏色像素點初始距離為無窮大,前景像素點距離為0
2.開始倒角距離變換中的第一步,并保存結果
3.基于第一步結果完成倒角距離變換中的第二步
4.根據距離變換結果顯示所有不同灰度值,形成圖像
最終結果顯示如下(左邊表示原圖、右邊表示cdt之后結果)
完整的二值圖像倒角距離變換的源代碼如下:
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
|
package com.gloomyfish.image.transform; import java.awt.color; import java.awt.image.bufferedimage; import java.util.arrays; import com.gloomyfish.filter.study.abstractbufferedimageop; public class cdtfilter extends abstractbufferedimageop { private float [] dis; // nn-distances private int [] pos; // nn-positions, 32 bit index private color bakcgroundcolor; public cdtfilter(color bgcolor) { this .bakcgroundcolor = bgcolor; } @override public bufferedimage filter(bufferedimage src, bufferedimage dest) { int width = src.getwidth(); int height = src.getheight(); if (dest == null ) dest = createcompatibledestimage(src, null ); int [] inpixels = new int [width * height]; pos = new int [width * height]; dis = new float [width * height]; src.getrgb( 0 , 0 , width, height, inpixels, 0 , width); // 隨機生成距離變換點 int index = 0 ; arrays.fill(dis, float .max_value); int numoffc = 0 ; for ( int row = 0 ; row < height; row++) { for ( int col = 0 ; col < width; col++) { index = row * width + col; if (inpixels[index] != bakcgroundcolor.getrgb()) { dis[index] = 0 ; pos[index] = index; numoffc++; } } } final float d1 = 1 ; final float d2 = ( float ) math.sqrt(d1 * d1 + d1 * d1); system.out.println(numoffc); float nd, nd_tmp; int i, in, cols, rows, nearestpixel; // 1 2 3 // 0 i 4 // 7 6 5 // first pass: forward -> l->r, t-b for (rows = 1 ; rows < height - 1 ; rows++) { for (cols = 1 ; cols < width - 1 ; cols++) { i = rows * width + cols; nd = dis[i]; nearestpixel = pos[i]; if (nd != 0 ) { // skip background pixels in = i; in += - 1 ; // 0 if ((nd_tmp = d1 + dis[in]) < nd) { nd = nd_tmp; nearestpixel = pos[in]; } in += -width; // 1 if ((nd_tmp = d2 + dis[in]) < nd) { nd = nd_tmp; nearestpixel = pos[in]; } in += + 1 ; // 2 if ((nd_tmp = d1 + dis[in]) < nd) { nd = nd_tmp; nearestpixel = pos[in]; } in += + 1 ; // 3 if ((nd_tmp = d2 + dis[in]) < nd) { nd = nd_tmp; nearestpixel = pos[in]; } dis[i] = nd; pos[i] = nearestpixel; } } } // second pass: backwards -> r->l, b-t // exactly same as first pass, just in the reverse direction for (rows = height - 2 ; rows >= 1 ; rows--) { for (cols = width - 2 ; cols >= 1 ; cols--) { i = rows * width + cols; nd = dis[i]; nearestpixel = pos[i]; if (nd != 0 ) { in = i; in += + 1 ; // 4 if ((nd_tmp = d1 + dis[in]) < nd) { nd = nd_tmp; nearestpixel = pos[in]; } in += +width; // 5 if ((nd_tmp = d2 + dis[in]) < nd) { nd = nd_tmp; nearestpixel = pos[in]; } in += - 1 ; // 6 if ((nd_tmp = d1 + dis[in]) < nd) { nd = nd_tmp; nearestpixel = pos[in]; } in += - 1 ; // 7 if ((nd_tmp = d2 + dis[in]) < nd) { nd = nd_tmp; nearestpixel = pos[in]; } dis[i] = nd; pos[i] = nearestpixel; } } } for ( int row = 0 ; row < height; row++) { for ( int col = 0 ; col < width; col++) { index = row * width + col; if ( float .max_value != dis[index]) { int gray = clamp(( int ) (dis[index])); inpixels[index] = ( 255 << 24 ) | (gray << 16 ) | (gray << 8 ) | gray; } } } setrgb(dest, 0 , 0 , width, height, inpixels); return dest; } private int clamp( int i) { return i > 255 ? 255 : (i < 0 ? 0 : i); } } |
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。
原文鏈接:http://blog.csdn.net/jia20003/article/details/42620499