00001
00002 #ifndef vil_suppress_non_max_edges_txx_
00003 #define vil_suppress_non_max_edges_txx_
00004
00005
00006
00007
00008
00009 #include "vil_suppress_non_max_edges.h"
00010 #include <vil/vil_bilin_interp.h>
00011 #include <vil/vil_fill.h>
00012 #include <vcl_cmath.h>
00013 #include <vcl_cassert.h>
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 template<class srcT, class destT>
00024 void vil_suppress_non_max_edges(const vil_image_view<srcT>& grad_i,
00025 const vil_image_view<srcT>& grad_j,
00026 double grad_mag_threshold,
00027 vil_image_view<destT>& grad_mag)
00028 {
00029 assert(grad_i.nplanes()==grad_j.nplanes());
00030 assert(grad_i.nplanes()==1);
00031 unsigned ni = grad_i.ni(), nj = grad_i.nj();
00032 assert(ni>2 && nj>2);
00033 assert(grad_j.ni()==ni && grad_j.nj()==nj);
00034 grad_mag.set_size(ni,nj,1);
00035
00036
00037 vil_fill_col(grad_mag,0,destT(0));
00038 vil_fill_col(grad_mag,1,destT(0));
00039 vil_fill_col(grad_mag,ni-1,destT(0));
00040 vil_fill_col(grad_mag,ni-2,destT(0));
00041 vil_fill_row(grad_mag,0,destT(0));
00042 vil_fill_row(grad_mag,1,destT(0));
00043 vil_fill_row(grad_mag,nj-1,destT(0));
00044 vil_fill_row(grad_mag,nj-2,destT(0));
00045
00046 const vcl_ptrdiff_t gi_istep = grad_i.istep(), gi_jstep = grad_i.jstep();
00047 const vcl_ptrdiff_t gj_istep = grad_j.istep(), gj_jstep = grad_j.jstep();
00048 const vcl_ptrdiff_t gm_istep = grad_mag.istep(), gm_jstep = grad_mag.jstep();
00049
00050 const srcT * gi_data = &grad_i(0,0);
00051 const srcT * gj_data = &grad_j(0,0);
00052 const srcT * gi_row = &grad_i(2,2);
00053 const srcT * gj_row = &grad_j(2,2);
00054 destT * gm_row = &grad_mag(2,2);
00055 unsigned ihi=ni-3;
00056 unsigned jhi=nj-3;
00057
00058 for (unsigned j=2; j<=jhi; ++j, gi_row+=gi_jstep, gj_row+=gj_jstep,
00059 gm_row+=gm_jstep)
00060 {
00061 const srcT* pgi = gi_row;
00062 const srcT* pgj = gj_row;
00063 destT *pgm = gm_row;
00064 for (unsigned i=2; i<=ihi; ++i, pgi+=gi_istep, pgj+=gj_istep,
00065 pgm+=gm_istep)
00066 {
00067 double gmag=vcl_sqrt(double(pgi[0]*pgi[0] + pgj[0]*pgj[0]));
00068 if (gmag<grad_mag_threshold) *pgm=0;
00069 else
00070 {
00071 double dx=pgi[0]/gmag;
00072 double dy=pgj[0]/gmag;
00073
00074 double gx1=vil_bilin_interp_unsafe(i+dx,j+dy,gi_data,gi_istep,gi_jstep);
00075 double gy1=vil_bilin_interp_unsafe(i+dx,j+dy,gj_data,gj_istep,gj_jstep);
00076 if (dx*gx1+dy*gy1>gmag) *pgm=0;
00077 else
00078 {
00079
00080 double gx2=vil_bilin_interp_unsafe(i-dx,j-dy,gi_data,gi_istep,gi_jstep);
00081 double gy2=vil_bilin_interp_unsafe(i-dx,j-dy,gj_data,gj_istep,gj_jstep);
00082 if (dx*gx2+dy*gy2>gmag) *pgm=0;
00083 else
00084 *pgm = destT(gmag);
00085 }
00086 }
00087 }
00088 }
00089 }
00090
00091 namespace {
00092
00093
00094
00095 double interpolate_parabola(double y_1, double y_0, double y_2,
00096 double& y_peak)
00097 {
00098 double diff1 = y_2 - y_1;
00099 double diff2 = 2 * y_0 - y_1 - y_2;
00100 y_peak = y_0 + diff1 * diff1 / (8 * diff2);
00101 return diff1 / (2 * diff2);
00102 }
00103 }
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134 template<class srcT, class destT>
00135 void vil_suppress_non_max_edges_subpixel(const vil_image_view<srcT>& grad_i,
00136 const vil_image_view<srcT>& grad_j,
00137 double grad_mag_threshold,
00138 vil_image_view<destT>& grad_moo)
00139 {
00140 assert(grad_i.nplanes()==grad_j.nplanes());
00141 assert(grad_i.nplanes()==1);
00142 unsigned ni = grad_i.ni(), nj = grad_i.nj();
00143 assert(ni>2 && nj>2);
00144 assert(grad_j.ni()==ni && grad_j.nj()==nj);
00145 grad_moo.set_size(ni,nj,3);
00146
00147
00148 vil_fill_col(grad_moo,0,destT(0));
00149 vil_fill_col(grad_moo,1,destT(0));
00150 vil_fill_col(grad_moo,ni-1,destT(0));
00151 vil_fill_col(grad_moo,ni-2,destT(0));
00152 vil_fill_row(grad_moo,0,destT(0));
00153 vil_fill_row(grad_moo,1,destT(0));
00154 vil_fill_row(grad_moo,nj-1,destT(0));
00155 vil_fill_row(grad_moo,nj-2,destT(0));
00156
00157 const vcl_ptrdiff_t gi_istep = grad_i.istep(), gi_jstep = grad_i.jstep();
00158 const vcl_ptrdiff_t gj_istep = grad_j.istep(), gj_jstep = grad_j.jstep();
00159 const vcl_ptrdiff_t gm_istep = grad_moo.istep(), gm_jstep = grad_moo.jstep();
00160 const vcl_ptrdiff_t gm_pstep = grad_moo.planestep();
00161
00162 const srcT * gi_data = &grad_i(0,0);
00163 const srcT * gj_data = &grad_j(0,0);
00164 const srcT * gi_row = &grad_i(2,2);
00165 const srcT * gj_row = &grad_j(2,2);
00166 destT * gm_row = &grad_moo(2,2);
00167 unsigned ihi=ni-3;
00168 unsigned jhi=nj-3;
00169
00170 for (unsigned j=2; j<=jhi; ++j, gi_row+=gi_jstep, gj_row+=gj_jstep,
00171 gm_row+=gm_jstep)
00172 {
00173 const srcT* pgi = gi_row;
00174 const srcT* pgj = gj_row;
00175 destT *pgm = gm_row;
00176 for (unsigned i=2; i<=ihi; ++i, pgi+=gi_istep, pgj+=gj_istep,
00177 pgm+=gm_istep)
00178 {
00179 double gmag=vcl_sqrt(double(pgi[0]*pgi[0] + pgj[0]*pgj[0]));
00180 if (gmag<grad_mag_threshold){
00181 *pgm=0;
00182 *(pgm+gm_pstep)=0;
00183 *(pgm+2*gm_pstep)=0;
00184 }
00185 else
00186 {
00187 double dx=pgi[0]/gmag;
00188 double dy=pgj[0]/gmag;
00189
00190 double gx1=vil_bilin_interp_unsafe(i+dx,j+dy,gi_data,gi_istep,gi_jstep);
00191 double gy1=vil_bilin_interp_unsafe(i+dx,j+dy,gj_data,gj_istep,gj_jstep);
00192 double g1mag = dx*gx1+dy*gy1;
00193 if (g1mag>gmag){
00194 *pgm=0;
00195 *(pgm+gm_pstep)=0;
00196 *(pgm+2*gm_pstep)=0;
00197 }
00198 else
00199 {
00200
00201 double gx2=vil_bilin_interp_unsafe(i-dx,j-dy,gi_data,gi_istep,gi_jstep);
00202 double gy2=vil_bilin_interp_unsafe(i-dx,j-dy,gj_data,gj_istep,gj_jstep);
00203 double g2mag = dx*gx2+dy*gy2;
00204 if (g2mag>gmag){
00205 *pgm=0;
00206 *(pgm+gm_pstep)=0;
00207 *(pgm+2*gm_pstep)=0;
00208 }
00209 else
00210 {
00211
00212 double peak;
00213 double offset = interpolate_parabola(g2mag, gmag, g1mag, peak);
00214 *pgm = destT(peak);
00215 *(pgm+gm_pstep) = destT(vcl_atan2(dy,dx));
00216 *(pgm+2*gm_pstep) = destT(offset);
00217 }
00218 }
00219 }
00220 }
00221 }
00222 }
00223
00224 #undef VIL_SUPPRESS_NON_MAX_EDGES_INSTANTIATE
00225 #define VIL_SUPPRESS_NON_MAX_EDGES_INSTANTIATE(srcT, destT) \
00226 template void vil_suppress_non_max_edges(const vil_image_view<srcT >& grad_i,\
00227 const vil_image_view<srcT >& grad_j,\
00228 double grad_mag_threshold,\
00229 vil_image_view<destT >& grad_mag);\
00230 template void vil_suppress_non_max_edges_subpixel(const vil_image_view<srcT >& grad_i,\
00231 const vil_image_view<srcT >& grad_j,\
00232 double grad_mag_threshold,\
00233 vil_image_view<destT >& grad_moo)
00234
00235 #endif // vil_suppress_non_max_edges_txx_