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