00001
00002
00003 #include "sdet_img_edge.h"
00004
00005 #include <sdet/sdet_detector.h>
00006 #include <bsta/bsta_gaussian_sphere.h>
00007 #include <brip/brip_vil_float_ops.h>
00008 #include <vdgl/vdgl_digital_curve.h>
00009 #include <vdgl/vdgl_edgel.h>
00010 #include <vdgl/vdgl_edgel_chain.h>
00011 #include <vdgl/vdgl_interpolator.h>
00012 #include <vdgl/vdgl_interpolator_cubic.h>
00013 #include <vdgl/vdgl_interpolator_linear.h>
00014 #include <vtol/vtol_edge_2d.h>
00015 #include <bil/algo/bil_edt.h>
00016 #include <vil/vil_convert.h>
00017 #include <vnl/algo/vnl_gaussian_kernel_1d.h>
00018 #include <vnl/algo/vnl_chi_squared.h>
00019 #include <vnl/vnl_vector_fixed.h>
00020 #include <vil/vil_new.h>
00021 #include <vnl/vnl_math.h>
00022 #include <vcl_iostream.h>
00023 #include <vcl_fstream.h>
00024 #include <vcl_cmath.h>
00025 #include <vcl_string.h>
00026 #include <vcl_vector.h>
00027 #include <vcl_cassert.h>
00028 #include <vgl/vgl_line_2d.h>
00029 #include <vsol/vsol_line_2d.h>
00030 #include <vsol/vsol_point_2d_sptr.h>
00031 #include <vsol/vsol_digital_curve_2d.h>
00032 #include <sdet/sdet_fit_lines_params.h>
00033 #include <sdet/sdet_fit_lines.h>
00034
00035 vil_image_view<vxl_byte> sdet_img_edge::detect_edges(vil_image_view<vxl_byte> img,
00036 double noise_multiplier,
00037 double smooth,
00038 bool automatic_threshold,
00039 bool junctionp,
00040 bool aggressive_junction_closure)
00041 {
00042 if ( img.nplanes() >= 3 )
00043 {
00044 vil_image_view<vxl_byte> img_rgb;
00045 img_rgb.deep_copy(img);
00046 vil_convert_planes_to_grey(img_rgb,img);
00047 }
00048
00049
00050 sdet_detector_params dp;
00051 dp.noise_multiplier = (float)noise_multiplier;
00052 dp.smooth = (float)smooth;
00053 dp.automatic_threshold = automatic_threshold;
00054 dp.junctionp = junctionp;
00055 dp.aggressive_junction_closure = aggressive_junction_closure;
00056
00057
00058 sdet_detector detector(dp);
00059 vil_image_resource_sptr img_res_sptr = vil_new_image_resource_of_view(img);
00060 detector.SetImage(img_res_sptr);
00061 detector.DoContour();
00062 vcl_vector<vtol_edge_2d_sptr> * edges = detector.GetEdges();
00063
00064
00065 vil_image_view<vxl_byte> img_edge(img.ni(),img.nj(),1);
00066 img_edge.fill(0);
00067
00068
00069 for (vcl_vector<vtol_edge_2d_sptr>::iterator eit = edges->begin(); eit != edges->end(); eit++)
00070 {
00071 vsol_curve_2d_sptr c = (*eit)->curve();
00072 vdgl_digital_curve_sptr dc = c->cast_to_vdgl_digital_curve();
00073 if (!dc)
00074 continue;
00075 vdgl_interpolator_sptr intp = dc->get_interpolator();
00076 vdgl_edgel_chain_sptr ec = intp->get_edgel_chain();
00077
00078
00079 for (unsigned j=0; j<ec->size(); j++) {
00080 vdgl_edgel curr_edgel = ec->edgel(j);
00081 int cr_x = (int)curr_edgel.x();
00082 int cr_y = (int)curr_edgel.y();
00083
00084
00085 img_edge(cr_x,cr_y) = 255;
00086 }
00087 }
00088
00089
00090 int temp_index = img_edge.nj()-1;
00091 for (unsigned i=0; i<img_edge.ni(); i++) {
00092 img_edge(i,0) = 0;
00093 img_edge(i,temp_index) = 0;
00094 }
00095 temp_index = img_edge.ni()-1;
00096 for (unsigned j=0; j<img_edge.nj(); j++) {
00097 img_edge(0,j) = 0;
00098 img_edge(temp_index,j) = 0;
00099 }
00100 return img_edge;
00101 }
00102
00103 static double angle_0_360(double angle)
00104 {
00105 double ang = angle;
00106 while (ang<0)
00107 ang += (2.0*vnl_math::pi);
00108 while (ang > 2.0*vnl_math::pi)
00109 ang -= (2.0*vnl_math::pi);
00110 return ang;
00111 }
00112
00113 vil_image_view<float>
00114 sdet_img_edge::detect_edge_tangent(vil_image_view<vxl_byte> img,
00115 double noise_multiplier,
00116 double smooth,
00117 bool automatic_threshold,
00118 bool junctionp,
00119 bool aggressive_junction_closure)
00120 {
00121
00122 sdet_detector_params dp;
00123 dp.noise_multiplier = (float)noise_multiplier;
00124 dp.smooth = (float)smooth;
00125 dp.automatic_threshold = automatic_threshold;
00126 dp.junctionp = junctionp;
00127 dp.aggressive_junction_closure = aggressive_junction_closure;
00128
00129
00130 sdet_detector detector(dp);
00131 vil_image_resource_sptr img_res_sptr = vil_new_image_resource_of_view(img);
00132 detector.SetImage(img_res_sptr);
00133 detector.DoContour();
00134 vcl_vector<vtol_edge_2d_sptr> * edges = detector.GetEdges();
00135
00136
00137 vil_image_view<float> edge_img(img.ni(),img.nj(),3);
00138 edge_img.fill(-1.0f);
00139
00140
00141 for (vcl_vector<vtol_edge_2d_sptr>::iterator eit = edges->begin(); eit != edges->end(); eit++)
00142 {
00143 vsol_curve_2d_sptr c = (*eit)->curve();
00144 vdgl_digital_curve_sptr dc = c->cast_to_vdgl_digital_curve();
00145 if (!dc)
00146 continue;
00147 vdgl_interpolator_sptr intp = dc->get_interpolator();
00148 vdgl_edgel_chain_sptr ec = intp->get_edgel_chain();
00149 unsigned n = ec->size();
00150 if (n<3) continue;
00151
00152 vdgl_edgel e0 = ec->edgel(0);
00153 vdgl_edgel e1 = ec->edgel(1);
00154 double e0x = e0.x(), e0y = e0.y();
00155 double e1x = e1.x(), e1y = e0.y();
00156 if (e0x<0||e0y<0) continue;
00157 double ang = angle_0_360(vcl_atan2(e1y-e0y, e1x-e0x));
00158 unsigned x0 = static_cast<unsigned>(e0x);
00159 unsigned y0 = static_cast<unsigned>(e0y);
00160 edge_img(x0, y0, 0) = static_cast<float>(e0x);
00161 edge_img(x0, y0, 1) = static_cast<float>(e0y);
00162 edge_img(x0, y0, 2) = static_cast<float>(ang);
00163
00164 vdgl_edgel enm2 = ec->edgel(n-2);
00165 vdgl_edgel enm1 = ec->edgel(n-1);
00166 double enm2x = enm2.x(), enm2y = enm2.y();
00167 double enm1x = enm1.x(), enm1y = enm1.y();
00168 if (enm1x<0||enm1y<0) continue;
00169 double angnm1 = angle_0_360(vcl_atan2(enm1y-enm2y, enm1x-enm2x));
00170 unsigned xnm1 = static_cast<unsigned>(enm1x);
00171 unsigned ynm1 = static_cast<unsigned>(enm1y);
00172 edge_img(xnm1, ynm1, 0) = static_cast<float>(enm1x);
00173 edge_img(xnm1, ynm1, 1) = static_cast<float>(enm1y);
00174 edge_img(xnm1, ynm1, 2) = static_cast<float>(angnm1);
00175
00176 for (unsigned j=1; j<n-1; j++) {
00177 vdgl_edgel pe = ec->edgel(j-1);
00178 vdgl_edgel ce = ec->edgel(j);
00179 vdgl_edgel ne = ec->edgel(j+1);
00180 double pex = pe.x(), pey = pe.y();
00181 double cex = ce.x(), cey = ce.y();
00182 double nex = ne.x(), ney = ne.y();
00183 if (cex<0||cey<0) continue;
00184 double angle = angle_0_360(vcl_atan2(ney-pey, nex-pex));
00185 unsigned xc = static_cast<unsigned>(cex);
00186 unsigned yc = static_cast<unsigned>(cey);
00187
00188 edge_img(xc, yc, 0) = static_cast<float>(cex);
00189 edge_img(xc, yc, 1) = static_cast<float>(cey);
00190 edge_img(xc, yc, 2) = static_cast<float>(angle);
00191 }
00192 }
00193
00194
00195 int temp_index = edge_img.nj()-1;
00196 for (unsigned i=0; i<edge_img.ni(); i++) {
00197 edge_img(i,0,0) = -1; edge_img(i,0,1) = -1;
00198 edge_img(i,temp_index,0) = -1;
00199 edge_img(i,temp_index,1) = -1;
00200 }
00201 temp_index = edge_img.ni()-1;
00202 for (unsigned j=0; j<edge_img.nj(); j++) {
00203 edge_img(0,j,0) = -1; edge_img(0,j,1) = -1;
00204 edge_img(temp_index,j,0) = -1;
00205 edge_img(temp_index,j,1) = -1;
00206 }
00207 return edge_img;
00208 }
00209
00210
00211
00212 vil_image_view<float>
00213 sdet_img_edge::detect_edge_tangent_interpolated(vil_image_view<vxl_byte> img,
00214 double noise_multiplier,
00215 double smooth,
00216 bool automatic_threshold,
00217 bool junctionp,
00218 bool aggressive_junction_closure)
00219 {
00220
00221 sdet_detector_params dp;
00222 dp.noise_multiplier = (float)noise_multiplier;
00223 dp.smooth = (float)smooth;
00224 dp.automatic_threshold = automatic_threshold;
00225 dp.junctionp = junctionp;
00226 dp.aggressive_junction_closure = aggressive_junction_closure;
00227
00228
00229 sdet_detector detector(dp);
00230 vil_image_resource_sptr img_res_sptr = vil_new_image_resource_of_view(img);
00231 detector.SetImage(img_res_sptr);
00232 detector.DoContour();
00233 vcl_vector<vdgl_digital_curve_sptr> edges;
00234 detector.get_vdgl_edges(edges);
00235
00236
00237 vil_image_view<float> edge_img(img.ni(),img.nj(),3);
00238 edge_img.fill(-1.0f);
00239
00240
00241
00242 for (unsigned ii = 0; ii < edges.size(); ii++)
00243 {
00244 vdgl_digital_curve_sptr dc = edges[ii];
00245 if (!dc)
00246 continue;
00247 vdgl_interpolator_sptr intp = dc->get_interpolator();
00248 vdgl_edgel_chain_sptr ec = intp->get_edgel_chain();
00249 unsigned n = ec->size();
00250
00251 vdgl_interpolator_sptr cubic_intp = new vdgl_interpolator_cubic(ec);
00252
00253 vcl_cout << " length: " << cubic_intp->get_length() << vcl_endl;
00254
00255 for (unsigned j=1; j<n-1; j++) {
00256 double cex = cubic_intp->get_x(j);
00257 double cey = cubic_intp->get_y(j);
00258
00259 unsigned xc = static_cast<unsigned>(cex);
00260 unsigned yc = static_cast<unsigned>(cey);
00261 double angle = angle_0_360((vnl_math::pi_over_180)*cubic_intp->get_theta(j)+vnl_math::pi_over_2);
00262
00263
00264 edge_img(xc, yc, 0) = static_cast<float>(cex);
00265 edge_img(xc, yc, 1) = static_cast<float>(cey);
00266 edge_img(xc, yc, 2) = static_cast<float>(angle);
00267 }
00268 }
00269
00270
00271 int temp_index = edge_img.nj()-1;
00272 for (unsigned i=0; i<edge_img.ni(); i++) {
00273 edge_img(i,0,0) = -1; edge_img(i,0,1) = -1;
00274 edge_img(i,temp_index,0) = -1;
00275 edge_img(i,temp_index,1) = -1;
00276 }
00277 temp_index = edge_img.ni()-1;
00278 for (unsigned j=0; j<edge_img.nj(); j++) {
00279 edge_img(0,j,0) = -1; edge_img(0,j,1) = -1;
00280 edge_img(temp_index,j,0) = -1;
00281 edge_img(temp_index,j,1) = -1;
00282 }
00283 return edge_img;
00284 }
00285
00286
00287 vil_image_view<float>
00288 sdet_img_edge::detect_edge_line_fitted(vil_image_view<vxl_byte> img,
00289 double noise_multiplier,
00290 double smooth,
00291 bool automatic_threshold,
00292 bool junctionp,
00293 bool aggressive_junction_closure,
00294 int min_fit_length, double rms_distance)
00295 {
00296 sdet_detector_params dp;
00297
00298 dp.noise_multiplier = (float)noise_multiplier;
00299 dp.smooth = (float)smooth;
00300 dp.automatic_threshold = automatic_threshold;
00301 dp.junctionp = junctionp;
00302 dp.aggressive_junction_closure = aggressive_junction_closure;
00303 dp.borderp = false;
00304
00305 sdet_fit_lines_params flp;
00306 flp.min_fit_length_ = min_fit_length;
00307 flp.rms_distance_ = rms_distance;
00308
00309 sdet_detector det(dp);
00310
00311 vil_image_resource_sptr img_res_sptr = vil_new_image_resource_of_view(img);
00312 unsigned ni = img.ni(); unsigned nj = img.nj();
00313
00314
00315 vil_image_view<float> edge_img(img.ni(),img.nj(),3);
00316 edge_img.fill(-1.0f);
00317
00318 det.SetImage(img_res_sptr);
00319 det.DoContour();
00320 vcl_vector<vtol_edge_2d_sptr>* edges = det.GetEdges();
00321 if (!edges)
00322 {
00323 vcl_cerr << "In sdet_img_edge::detect_edge_line_fitted() - No edges found in the image\n";
00324 return edge_img;
00325 }
00326 sdet_fit_lines fl(flp);
00327 fl.set_edges(*edges);
00328 fl.fit_lines();
00329 vcl_vector<vsol_line_2d_sptr> lines = fl.get_line_segs();
00330
00331 for (unsigned i = 0; i < lines.size(); i++) {
00332 vsol_line_2d_sptr l = lines[i];
00333 int length = (int)vcl_ceil(l->length());
00334 double angle = angle_0_360(vnl_math::pi_over_180*l->tangent_angle());
00335 #if 0
00336 vcl_cout << " line: " << i << " length: " << l->length()
00337 << " p0: (" << l->p0()->x() << ", " << l->p0()->y() << ')'
00338 << " p1: (" << l->p1()->x() << ", " << l->p1()->y() << ')'
00339 << " mid: (" << l->middle()->x() << ", " << l->middle()->y() << ")\n";
00340 #endif
00341 vcl_vector<vsol_point_2d_sptr> samples; samples.push_back(l->p0()); samples.push_back(l->p1());
00342 vsol_digital_curve_2d_sptr dc = new vsol_digital_curve_2d(samples);
00343
00344
00345 float inc = 1.0f/(float)length;
00346 for (float index = 0.0f; index <= 1.0f; index += inc) {
00347 vgl_point_2d<double> pt = dc->interp((double)index);
00348
00349 double cex = pt.x();
00350 double cey = pt.y();
00351 if (cex < 0 || cey < 0) continue;
00352
00353 unsigned xc = static_cast<unsigned>(cex);
00354 unsigned yc = static_cast<unsigned>(cey);
00355 if (xc > ni || yc > nj) continue;
00356
00357 edge_img(xc, yc, 0) = static_cast<float>(cex);
00358 edge_img(xc, yc, 1) = static_cast<float>(cey);
00359 edge_img(xc, yc, 2) = static_cast<float>(angle);
00360 }
00361 }
00362 return edge_img;
00363 }
00364
00365
00366 void
00367 sdet_img_edge::convert_edge_image_to_line_image(vil_image_view<float>& edge_image, vil_image_view<float>& line_image)
00368 {
00369 if (line_image.ni() != edge_image.ni() || line_image.nj() != edge_image.nj() ||
00370 line_image.nplanes() != edge_image.nplanes() || line_image.nplanes() != 3) {
00371 vcl_cerr << "In sdet_img_edge::convert_edge_image_to_line_image() -- incompatible input output image pair!\n";
00372 return;
00373 }
00374
00375 line_image.fill(-2.0f);
00376 for (unsigned j = 0; j<line_image.nj(); ++j)
00377 for (unsigned i = 0; i<line_image.ni(); ++i) {
00378 float x = edge_image(i,j,0);
00379 float y = edge_image(i,j,1);
00380 if (x<0||y<0)
00381 continue;
00382 float angle = edge_image(i,j,2);
00383 vgl_vector_2d<float> tangent(vcl_cos(angle), vcl_sin(angle));
00384 vgl_point_2d<float> pt(x,y);
00385 vgl_line_2d<float> l(pt, tangent);
00386 float a = l.a(), b = l.b(), c = l.c();
00387 float norm = vcl_sqrt(a*a+b*b);
00388 a/=norm; b/=norm; c/=norm;
00389 line_image(i,j,0)= a;
00390 line_image(i,j,1)= b;
00391 line_image(i,j,2)= c;
00392 }
00393 }
00394
00395 void sdet_img_edge::edge_distance_transform(vil_image_view<vxl_byte>& inp_image, vil_image_view<float>& out_edt)
00396 {
00397 vil_image_view<vxl_byte> edge_image_negated(inp_image);
00398 vil_math_scale_and_offset_values<vxl_byte,double>(edge_image_negated,-1.0,255.0);
00399
00400 unsigned ni = edge_image_negated.ni();
00401 unsigned nj = edge_image_negated.nj();
00402
00403 vil_image_view<vxl_uint_32> curr_image_edt(ni,nj,1);
00404 for (unsigned i=0; i<ni; i++) {
00405 for (unsigned j=0; j<nj; j++) {
00406 curr_image_edt(i,j) = edge_image_negated(i,j);
00407 }
00408 }
00409
00410 bil_edt_maurer(curr_image_edt);
00411
00412 out_edt.set_size(ni,nj,1);
00413 for (unsigned i=0; i<ni; i++) {
00414 for (unsigned j=0; j<nj; j++) {
00415 out_edt(i,j) = vcl_sqrt((float)curr_image_edt(i,j));
00416 }
00417 }
00418 }
00419
00420
00421
00422
00423
00424
00425 vil_image_view<float> sdet_img_edge::multiply_image_with_gaussian_kernel(vil_image_view<float> img, double gaussian_sigma)
00426 {
00427 vil_image_view<float> ret_img(img.ni(),img.nj(),1);
00428
00429 vnl_gaussian_kernel_1d gaussian(gaussian_sigma);
00430
00431 for (unsigned i=0; i<img.ni(); i++) {
00432 for (unsigned j=0; j<img.nj(); j++) {
00433 ret_img(i,j) = (float)gaussian.G((double)img(i,j));
00434 }
00435 }
00436 return ret_img;
00437 }
00438
00439 vbl_array_2d<float> sdet_img_edge::get_spherical_gaussian_kernel(const int size, const float sigma)
00440 {
00441 assert(size>=3 && size%2==1);
00442
00443 vbl_array_2d<float> kernel(size,size,0.0f);
00444
00445 vnl_vector_fixed<float,2> mean(0.0f);
00446 float variance = (sigma*sigma);
00447 bsta_gaussian_sphere<float,2> gaussian(mean,variance);
00448
00449 int center = (size-1)/2;
00450
00451 vnl_vector_fixed<float,2> min_pt;
00452 vnl_vector_fixed<float,2> max_pt;
00453 for (int i=0; i<size; i++) {
00454 for (int j=0; j<size; j++) {
00455 min_pt[0] = ((float)(i-center))-0.5f;
00456 min_pt[1] = ((float)(j-center))-0.5f;
00457 max_pt[0] = ((float)(i-center))+0.5f;
00458 max_pt[1] = ((float)(j-center))+0.5f;
00459 kernel(i,j) = gaussian.probability(min_pt,max_pt);
00460 }
00461 }
00462 return kernel;
00463 }
00464
00465 void sdet_img_edge::estimate_edge_prob_image(const vil_image_view<vxl_byte>& img_edge, vil_image_view<float>& img_edgeness, const int mask_size, const float mask_sigma)
00466 {
00467 vbl_array_2d<float> kernel = get_spherical_gaussian_kernel(mask_size,mask_sigma);
00468
00469 for (unsigned i=0; i<kernel.rows(); i++) {
00470 for (unsigned j=0; j<kernel.columns(); j++) {
00471 kernel(i,j) = vcl_log(1.0f - kernel(i,j));
00472 }
00473 }
00474
00475 vil_convert_cast<vxl_byte,float>(img_edge,img_edgeness);
00476 vil_math_scale_values<float>(img_edgeness,1.0/255.0);
00477 img_edgeness = brip_vil_float_ops::convolve(img_edgeness,kernel);
00478
00479 for (unsigned i=0; i<img_edgeness.ni(); i++) {
00480 for (unsigned j=0; j<img_edgeness.nj(); j++) {
00481 img_edgeness(i,j) = 1.0f - vcl_exp(img_edgeness(i,j));
00482 }
00483 }
00484 }
00485
00486 void sdet_img_edge::convert_true_edge_prob_to_edge_statistics(
00487 const vil_image_view<float>& img_tep,
00488 vil_image_view<float>& img_es)
00489 {
00490 float img_mean,img_var;
00491 vil_math_mean_and_variance(img_mean,img_var,img_tep,0);
00492 img_var = vcl_sqrt(img_mean*img_var);
00493
00494 img_es.set_size(img_tep.ni(),img_tep.nj());
00495
00496 for (unsigned i=0; i<img_tep.ni(); i++) {
00497 for (unsigned j=0; j<img_tep.nj(); j++) {
00498 img_es(i,j) = ((img_tep(i,j)-img_mean)*(img_tep(i,j)-img_mean))/img_var;
00499 }
00500 }
00501 }
00502
00503 float sdet_img_edge::convert_edge_statistics_to_probability(float edge_statistic, float n_normal, int dof)
00504 {
00505 if (dof<1) {
00506 return edge_statistic;
00507 }
00508 return (float)vnl_chi_squared_cumulative(edge_statistic,dof);
00509 }