00001 #include "vil_distance_transform.h"
00002
00003
00004
00005
00006
00007 #include <vil/vil_fill.h>
00008 #include <vcl_algorithm.h>
00009 #include <vcl_cassert.h>
00010
00011
00012
00013
00014
00015
00016 void vil_distance_transform(vil_image_view<float>& image)
00017 {
00018
00019 vil_distance_transform_one_way(image);
00020
00021
00022
00023 unsigned ni = image.ni(), nj = image.nj();
00024 vil_image_view<float> flip_image(image.memory_chunk(),
00025 &image(ni-1,nj-1), ni,nj,1,
00026 -image.istep(), -image.jstep(),
00027 image.nplanes());
00028 vil_distance_transform_one_way(flip_image);
00029 }
00030
00031
00032
00033
00034
00035
00036
00037 void vil_distance_transform_one_way(vil_image_view<float>& image)
00038 {
00039 assert(image.nplanes()==1);
00040 unsigned ni = image.ni();
00041 unsigned nj = image.nj();
00042 unsigned ni1 = ni-1;
00043 vcl_ptrdiff_t istep = image.istep(), jstep = image.jstep();
00044 vcl_ptrdiff_t o1 = -istep, o2 = -jstep-istep, o3 = -jstep, o4 = istep-jstep;
00045 float* row0 = image.top_left_ptr();
00046
00047 const float sqrt2 = 1.4142135f;
00048
00049
00050 float* p0 = row0+istep;
00051 for (unsigned i=1;i<ni;++i,p0+=istep)
00052 {
00053 *p0 = vcl_min(p0[-istep]+1.0f,*p0);
00054 }
00055
00056 row0 += jstep;
00057
00058
00059 for (unsigned j=1;j<nj;++j,row0+=jstep)
00060 {
00061
00062 *row0 = vcl_min(row0[o3]+1.0f,*row0);
00063 *row0 = vcl_min(row0[o4]+sqrt2,*row0);
00064
00065 float* p0 = row0+istep;
00066 for (unsigned i=1;i<=ni1;++i,p0+=istep)
00067 {
00068 *p0 = vcl_min(p0[o1]+1.0f ,*p0);
00069 *p0 = vcl_min(p0[o2]+sqrt2,*p0);
00070 *p0 = vcl_min(p0[o3]+1.0f ,*p0);
00071 *p0 = vcl_min(p0[o4]+sqrt2,*p0);
00072 }
00073
00074
00075 *p0 = vcl_min(p0[o1]+1.0f ,*p0);
00076 *p0 = vcl_min(p0[o2]+sqrt2,*p0);
00077 *p0 = vcl_min(p0[o3]+1.0f ,*p0);
00078 }
00079 }
00080
00081
00082
00083
00084 void vil_distance_transform(const vil_image_view<bool>& mask,
00085 vil_image_view<float>& distance_image,
00086 float max_dist)
00087 {
00088 distance_image.set_size(mask.ni(),mask.nj());
00089 distance_image.fill(max_dist);
00090 vil_fill_mask(distance_image,mask,0.0f);
00091
00092 vil_distance_transform(distance_image);
00093 }
00094
00095
00096
00097 void vil_distance_transform_r2_one_way(vil_image_view<float>& image)
00098 {
00099 assert(image.nplanes()==1);
00100 unsigned ni = image.ni();
00101 unsigned nj = image.nj();
00102 unsigned ni2 = ni-2;
00103 vcl_ptrdiff_t istep = image.istep(), jstep = image.jstep();
00104
00105
00106
00107
00108
00109 vcl_ptrdiff_t o1 = -istep, o2 = -jstep-istep;
00110 vcl_ptrdiff_t o3 = -jstep, o4 = istep-jstep;
00111 vcl_ptrdiff_t o5 = -2*istep-jstep;
00112 vcl_ptrdiff_t o6 = -istep-2*jstep;
00113 vcl_ptrdiff_t o7 = istep-2*jstep;
00114 vcl_ptrdiff_t o8 = 2*istep-jstep;
00115
00116 float* row0 = image.top_left_ptr();
00117
00118 const float sqrt2 = 1.4142135f;
00119 const float sqrt5 = 2.236068f;
00120
00121
00122 float* p0 = row0+istep;
00123 for (unsigned i=1;i<ni;++i,p0+=istep)
00124 {
00125 *p0 = vcl_min(p0[-istep]+1.0f,*p0);
00126 }
00127
00128 row0 += jstep;
00129
00130
00131
00132 *row0 = vcl_min(row0[o3]+1.0f,*row0);
00133 *row0 = vcl_min(row0[o4]+sqrt5,*row0);
00134 *row0 = vcl_min(row0[o8]+sqrt5,*row0);
00135
00136 p0 = row0+istep;
00137 *p0 = vcl_min(p0[o1]+1.0f,*p0);
00138 *p0 = vcl_min(p0[o2]+sqrt2,*p0);
00139 *p0 = vcl_min(p0[o3]+1.0f,*p0);
00140 *p0 = vcl_min(p0[o4]+sqrt2,*p0);
00141 *p0 = vcl_min(p0[o8]+sqrt5,*p0);
00142
00143 p0+=istep;
00144 for (unsigned i=2;i<ni2;++i,p0+=istep)
00145 {
00146 *p0 = vcl_min(p0[o1]+1.0f,*p0);
00147 *p0 = vcl_min(p0[o2]+sqrt2,*p0);
00148 *p0 = vcl_min(p0[o3]+1.0f,*p0);
00149 *p0 = vcl_min(p0[o4]+sqrt2,*p0);
00150 *p0 = vcl_min(p0[o5]+sqrt5,*p0);
00151 *p0 = vcl_min(p0[o8]+sqrt5,*p0);
00152 }
00153
00154
00155 *p0 = vcl_min(p0[o1]+1.0f,*p0);
00156 *p0 = vcl_min(p0[o2]+sqrt2,*p0);
00157 *p0 = vcl_min(p0[o3]+1.0f,*p0);
00158 *p0 = vcl_min(p0[o4]+sqrt2,*p0);
00159 *p0 = vcl_min(p0[o5]+sqrt5,*p0);
00160
00161 p0+=istep;
00162
00163 *p0 = vcl_min(p0[o1]+1.0f,*p0);
00164 *p0 = vcl_min(p0[o2]+sqrt2,*p0);
00165 *p0 = vcl_min(p0[o3]+1.0f,*p0);
00166 *p0 = vcl_min(p0[o5]+sqrt5,*p0);
00167
00168 row0 += jstep;
00169
00170
00171 for (unsigned j=2;j<nj;++j,row0+=jstep)
00172 {
00173
00174 *row0 = vcl_min(row0[o3]+1.0f,*row0);
00175 *row0 = vcl_min(row0[o4]+sqrt2,*row0);
00176 *row0 = vcl_min(row0[o7]+sqrt5,*row0);
00177 *row0 = vcl_min(row0[o8]+sqrt5,*row0);
00178
00179 float* p0 = row0+istep;
00180
00181 *p0 = vcl_min(p0[o1]+1.0f,*p0);
00182 *p0 = vcl_min(p0[o2]+sqrt2,*p0);
00183 *p0 = vcl_min(p0[o3]+1.0f,*p0);
00184 *p0 = vcl_min(p0[o4]+sqrt2,*p0);
00185 *p0 = vcl_min(p0[o6]+sqrt5,*p0);
00186 *p0 = vcl_min(p0[o7]+sqrt5,*p0);
00187 *p0 = vcl_min(p0[o8]+sqrt5,*p0);
00188
00189 p0+=istep;
00190 for (unsigned i=2;i<ni2;++i,p0+=istep)
00191 {
00192 *p0 = vcl_min(p0[o1]+1.0f,*p0);
00193 *p0 = vcl_min(p0[o2]+sqrt2,*p0);
00194 *p0 = vcl_min(p0[o3]+1.0f,*p0);
00195 *p0 = vcl_min(p0[o4]+sqrt2,*p0);
00196 *p0 = vcl_min(p0[o5]+sqrt5,*p0);
00197 *p0 = vcl_min(p0[o6]+sqrt5,*p0);
00198 *p0 = vcl_min(p0[o7]+sqrt5,*p0);
00199 *p0 = vcl_min(p0[o8]+sqrt5,*p0);
00200 }
00201
00202
00203
00204 *p0 = vcl_min(p0[o1]+1.0f,*p0);
00205 *p0 = vcl_min(p0[o2]+sqrt2,*p0);
00206 *p0 = vcl_min(p0[o3]+1.0f,*p0);
00207 *p0 = vcl_min(p0[o4]+sqrt2,*p0);
00208 *p0 = vcl_min(p0[o5]+sqrt5,*p0);
00209 *p0 = vcl_min(p0[o6]+sqrt5,*p0);
00210 *p0 = vcl_min(p0[o7]+sqrt5,*p0);
00211
00212 p0+=istep;
00213
00214 *p0 = vcl_min(p0[o1]+1.0f,*p0);
00215 *p0 = vcl_min(p0[o2]+sqrt2,*p0);
00216 *p0 = vcl_min(p0[o3]+1.0f,*p0);
00217 *p0 = vcl_min(p0[o5]+sqrt5,*p0);
00218 *p0 = vcl_min(p0[o6]+sqrt5,*p0);
00219 }
00220 }
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230 void vil_distance_transform_r2(vil_image_view<float>& image)
00231 {
00232
00233 vil_distance_transform_r2_one_way(image);
00234
00235
00236
00237 unsigned ni = image.ni(), nj = image.nj();
00238 vil_image_view<float> flip_image(image.memory_chunk(),
00239 &image(ni-1,nj-1), ni,nj,1,
00240 -image.istep(), -image.jstep(),
00241 image.nplanes());
00242 vil_distance_transform_r2_one_way(flip_image);
00243 }
00244