1 //This is brl/bseg/bvxm/pro/processes/bvxm_detect_edge_tangent_process.cxx
2 #include "bvxm_detect_edge_tangent_process.h"
3 //:
4 // \file
5 
6 #include <sdet/sdet_img_edge.h>
7 
8 #include <bprb/bprb_func_process.h>
9 #include <bprb/bprb_parameters.h>
10 #include <brdb/brdb_value.h>
11 #include <bvxm/bvxm_voxel_world.h>
12 #include <bvxm/bvxm_image_metadata.h>
13 #include <sdet/sdet_detector.h>
14 #include <sdet/sdet_fit_lines.h>
15 #include <vdgl/vdgl_digital_curve.h>
16 #include <vdgl/vdgl_edgel.h>
17 #include <vdgl/vdgl_edgel_chain.h>
18 #include <vdgl/vdgl_interpolator.h>
19 #include "vil/vil_image_view.h"
20 #include "vil/vil_convert.h"
21 #include <vsol/vsol_curve_2d_sptr.h>
22 #include <vsol/vsol_line_2d.h>
23 #include <vsol/vsol_point_2d.h>
24 #include <vtol/vtol_edge_2d.h>
25 #include "vgl/vgl_line_2d.h"
26 
27 //: initialize input and output types
bvxm_detect_edge_tangent_process_cons(bprb_func_process & pro)28 bool bvxm_detect_edge_tangent_process_cons(bprb_func_process& pro)
29 {
30   using namespace bvxm_detect_edge_tangent_process_globals;
31   // process takes 1 input:
32   //input[0]: input grayscale image
33   //input[1]: string indicating the output format
34   std::vector<std::string> input_types_(n_inputs_);
35   input_types_[0] = "vil_image_view_base_sptr";
36   input_types_[1] = "vcl_string";
37   if (!pro.set_input_types(input_types_))
38     return false;
39 
40   // process has 1 output image with 3 bands:
41   // output[0]: output edge image with 3 planes
42   // case pos_dir
43   // plane 0 - sub-pixel column position of the edge.
44   //           Negative value indicates no edge is present
45   // plane 1 - sub-pixel row position of the edge.
46   //           Negative value indicates no edge is present
47   // plane 2 - Orientation of local edge tangent direction in radians
48   // range is [0, 2pi).
49   // case line_2d
50   // plane 0 - line coefficient a --
51   //                                |-- components of line normal vector
52   // plane 1 - line coefficient b --
53   //
54   // plane 2 - line coefficient c
55 
56   std::vector<std::string> output_types_(n_outputs_);
57   output_types_[0] = "vil_image_view_base_sptr";
58   return pro.set_output_types(output_types_);
59 }
60 
61 //: generates the edge map
bvxm_detect_edge_tangent_process(bprb_func_process & pro)62 bool bvxm_detect_edge_tangent_process(bprb_func_process& pro)
63 {
64  using namespace bvxm_detect_edge_tangent_process_globals;
65 
66   if (!pro.verify_inputs())
67   {
68     std::cout << pro.name() << " Invalid inputs" << std::endl;
69     return false;
70   }
71 
72   // get inputs
73   // image
74   vil_image_view_base_sptr input_image_sptr = pro.get_input<vil_image_view_base_sptr>(0);
75 
76   //check input validity
77   if (!input_image_sptr) {
78     std::cout << pro.name() <<" :-- null input image\n";
79     return false;
80   }
81 
82   vil_image_view<vxl_byte> input_image =
83     *vil_convert_cast(vxl_byte(), input_image_sptr);
84 
85   std::string out_type = pro.get_input<std::string>(1);
86   // get parameters
87   double noise_multiplier=1.5, smooth=1.5;
88   bool automatic_threshold=false, junctionp=false, aggressive_junction_closure=false;
89 
90   pro.parameters()->get_value(param_noise_multiplier_, noise_multiplier);
91   pro.parameters()->get_value(param_smooth_, smooth);
92   pro.parameters()->get_value(param_automatic_threshold_, automatic_threshold);
93   pro.parameters()->get_value(param_junctionp_, junctionp);
94   pro.parameters()->get_value(param_aggressive_junction_closure_, aggressive_junction_closure);
95 #if 0
96   std::cout << "Edge detection parameters\n";
97   pro.parameters()->print_all(std::cout);
98 #endif
99   vil_image_view<float> edge_image =
100     sdet_img_edge::detect_edge_tangent(input_image,
101                                        noise_multiplier,
102                                        smooth,
103                                        automatic_threshold,
104                                        junctionp,
105                                        aggressive_junction_closure);
106 
107   // return the output edge image in pos_dir format
108   if (out_type=="pos_dir") {
109     pro.set_output_val<vil_image_view_base_sptr>(0,new vil_image_view<float>(edge_image));
110     return true;
111   }
112   //else convert to line format
113   if (out_type == "line_2d") {
114     unsigned ni = edge_image.ni(), nj = edge_image.nj();
115     auto* line_image = new vil_image_view<float>(ni, nj, 3);
116     line_image->fill(-2.0f);
117     for (unsigned j = 0; j<nj; ++j)
118       for (unsigned i = 0; i<ni; ++i) {
119         float x = edge_image(i,j,0);
120         float y = edge_image(i,j,1);
121         if (x<0||y<0)
122           continue;
123         float angle = edge_image(i,j,2);
124         vgl_vector_2d<float> tangent(std::cos(angle), std::sin(angle));
125         vgl_point_2d<float> pt(x,y);
126         vgl_line_2d<float> l(pt, tangent);
127         float a = l.a(), b = l.b(), c = l.c();
128         float norm = std::sqrt(a*a+b*b);
129         a/=norm; b/=norm; c/=norm;
130         (*line_image)(i,j,0)= a;
131         (*line_image)(i,j,1)= b;
132         (*line_image)(i,j,2)= c;
133       }
134     pro.set_output_val<vil_image_view_base_sptr>(0, line_image);
135     return true;
136   }
137   return false;
138 }
139