1 // This is brl/bpro/core/sdet_pro/processes/sdet_texture_training_process.cxx
2 //:
3 // \file
4 
5 #include <bprb/bprb_func_process.h>
6 #include <bprb/bprb_parameters.h>
7 #include <brdb/brdb_value.h>
8 #include <sdet/sdet_texture_classifier.h>
9 #include <sdet/sdet_texture_classifier_params.h>
10 #include "vil/vil_image_view.h"
11 #include <bbas_pro/bbas_1d_array_string.h>
12 #include <bbas_pro/bbas_1d_array_string_sptr.h>
13 #include <vsol/vsol_polygon_2d.h>
14 #include "vsl/vsl_binary_io.h"
15 
16 //: initialize input and output types
sdet_texture_training_process_cons(bprb_func_process & pro)17 bool sdet_texture_training_process_cons(bprb_func_process& pro)
18 {
19   vsl_add_to_binary_loader(vsol_polygon_2d());
20   // process takes 6 inputs:
21   std::vector<std::string> input_types;
22   input_types.emplace_back("sdet_texture_classifier_sptr"); //texture classifier
23   input_types.emplace_back("bool"); //if true, compute textons for category,
24   //otherwise append filter responses from the image to the training data
25   input_types.emplace_back("vil_image_view_base_sptr"); //input image
26   input_types.emplace_back("vcl_string"); //polygon file
27   input_types.emplace_back("vcl_string"); // category name
28   input_types.emplace_back("vcl_string"); // texton dictionary path
29 
30   if (!pro.set_input_types(input_types))
31     return false;
32 
33   // process has 1 output:
34   // output[0]: the current state of the texture classifier
35   std::vector<std::string> output_types;
36   output_types.emplace_back("sdet_texture_classifier_sptr");
37   return pro.set_output_types(output_types);
38 }
39 
sdet_texture_training_process(bprb_func_process & pro)40 bool sdet_texture_training_process(bprb_func_process& pro)
41 {
42   if (!pro.verify_inputs())
43   {
44     std::cout << pro.name() << "texture classifier process inputs are not valid"<< std::endl;
45     return false;
46   }
47 
48   // get inputs
49   //== the texture classifier
50   sdet_texture_classifier_sptr tc_ptr = pro.get_input<sdet_texture_classifier_sptr>(0);
51 
52   //== compute textons (true) or just append samples to training data
53   //for the category (false)
54   bool compute_textons = pro.get_input<bool>(1);
55 
56   //== the input image
57   vil_image_view_base_sptr view_ptr =
58     pro.get_input<vil_image_view_base_sptr>(2);
59   if (!view_ptr)
60   {
61     std::cout << "null image in sdet_texture_classifier_process\n";
62     return false;
63   }
64   //assumes a float image on the range [0, 1] so cast without checking
65   vil_image_view<float> fview(view_ptr);
66 
67   //go ahead and compute the filter bank as well as laplace and Gauss filters
68   if (!tc_ptr->compute_filter_bank(fview)){
69     std::cout << "failed to compute filter bank\n";
70     return false;
71   }
72 
73   //remaining arguments
74   //== polygon region delineating samples of the texture
75   std::string poly_path = pro.get_input<std::string>(3);
76 
77   //== the string name of the texture category
78   std::string category = pro.get_input<std::string>(4);
79 
80   // extract the training data from the current image filter responses
81   if (!tc_ptr->compute_training_data(category, poly_path))
82   {
83     std::cout << "failed to compute training data\n";
84     return false;
85   }
86   // if the last training image for the category then complete the
87   // texton dictionary entry
88   if (compute_textons)
89     if (!tc_ptr->compute_textons(category))
90       return false;
91 
92   // pass the texture classifier into the database for additional training
93   // data or additional categories
94   pro.set_output_val<sdet_texture_classifier_sptr>(0, tc_ptr);
95 
96   return true;
97 }
98 
99 // this method is called if all training is complete
100 // the texton dictionary is finalized and written out to the specified
101 // file
sdet_texture_training_process_finish(bprb_func_process & pro)102 bool sdet_texture_training_process_finish(bprb_func_process& pro)
103 {
104   if (!pro.verify_inputs())
105   {
106     std::cout << pro.name() << "texture classifier process inputs are not valid"<< std::endl;
107     return false;
108   }
109   // get inputs
110   sdet_texture_classifier_sptr tc_ptr = pro.get_input<sdet_texture_classifier_sptr>(0);
111   if (!tc_ptr){
112     std::cout << "In finishing texture training - null texture_classifier\n";
113     return false;
114   }
115   std::string dict_path = pro.get_input<std::string>(5);
116   if (dict_path == "")
117     return false;
118   tc_ptr->compute_category_histograms();
119   std::cout << "Saving dictionary\n";
120   if (!tc_ptr->save_dictionary(dict_path))
121     return false;
122   return true;
123 }
124 
125 
126 //: this process assumes that the input classifier already has the filter bank of the training image (e.g. run sdetExtractFilterBankProcess first)
sdet_texture_training_process2_cons(bprb_func_process & pro)127 bool sdet_texture_training_process2_cons(bprb_func_process& pro)
128 {
129   vsl_add_to_binary_loader(vsol_polygon_2d());
130   // process takes 5 inputs:
131   std::vector<std::string> input_types;
132   input_types.emplace_back("sdet_texture_classifier_sptr"); //texture classifier
133   input_types.emplace_back("bool"); //if true, compute textons for category,
134   //otherwise append filter responses from the image to the training data
135   input_types.emplace_back("vcl_string"); //polygon file
136   input_types.emplace_back("vcl_string"); // category name
137   input_types.emplace_back("vcl_string"); // texton dictionary path
138 
139   if (!pro.set_input_types(input_types))
140     return false;
141 
142   std::vector<std::string> output_types;
143   output_types.emplace_back("sdet_texture_classifier_sptr");
144   return pro.set_output_types(output_types);
145 }
146 
sdet_texture_training_process2(bprb_func_process & pro)147 bool sdet_texture_training_process2(bprb_func_process& pro)
148 {
149   if (!pro.verify_inputs())
150   {
151     std::cout << pro.name() << "texture classifier process2 inputs are not valid"<< std::endl;
152     return false;
153   }
154 
155   // get inputs
156   //== the texture classifier
157   sdet_texture_classifier_sptr tc_ptr = pro.get_input<sdet_texture_classifier_sptr>(0);
158 
159   //== compute textons (true) or just append samples to training data
160   //for the category (false)
161   bool compute_textons = pro.get_input<bool>(1);
162 
163   //remaining arguments
164   //== polygon region delineating samples of the texture
165   std::string poly_path = pro.get_input<std::string>(2);
166 
167   //== the string name of the texture category
168   std::string category = pro.get_input<std::string>(3);
169 
170   // extract the training data from the current image filter responses
171   if (!tc_ptr->compute_training_data(category, poly_path))
172   {
173     std::cout << "failed to compute training data\n";
174     return false;
175   }
176   // if the last training image for the category then complete the
177   // texton dictionary entry
178   if (compute_textons)
179     if (!tc_ptr->compute_textons(category))
180       return false;
181 
182   // pass the texture classifier into the database for additional training
183   // data or additional categories
184   pro.set_output_val<sdet_texture_classifier_sptr>(0, tc_ptr);
185 
186   return true;
187 }
188 
189 // this method is called if all training is complete
190 // the texton dictionary is finalized and written out to the specified
191 // file
sdet_texture_training_process2_finish(bprb_func_process & pro)192 bool sdet_texture_training_process2_finish(bprb_func_process& pro)
193 {
194   if (!pro.verify_inputs())
195   {
196     std::cout << pro.name() << "texture classifier process inputs are not valid"<< std::endl;
197     return false;
198   }
199   // get inputs
200   sdet_texture_classifier_sptr tc_ptr = pro.get_input<sdet_texture_classifier_sptr>(0);
201   if (!tc_ptr){
202     std::cout << "In finishing texture training - null texture_classifier\n";
203     return false;
204   }
205   std::string dict_path = pro.get_input<std::string>(4);
206   if (dict_path == "")
207     return false;
208   tc_ptr->compute_category_histograms();
209   std::cout << "Saving dictionary\n";
210   if (!tc_ptr->save_dictionary(dict_path))
211     return false;
212   return true;
213 }
214 
215 //: this process converts vsol objects saved as .bin files to .txt files
sdet_dump_vsol_binary_data_process_cons(bprb_func_process & pro)216 bool sdet_dump_vsol_binary_data_process_cons(bprb_func_process& pro)
217 {
218   vsl_add_to_binary_loader(vsol_polygon_2d());
219   // process takes 5 inputs:
220   std::vector<std::string> input_types;
221   input_types.emplace_back("vcl_string"); //polygon file
222   input_types.emplace_back("vcl_string"); //output file name
223   if (!pro.set_input_types(input_types))
224     return false;
225 
226   std::vector<std::string> output_types;
227   return pro.set_output_types(output_types);
228 }
229 
sdet_dump_vsol_binary_data_process(bprb_func_process & pro)230 bool sdet_dump_vsol_binary_data_process(bprb_func_process& pro)
231 {
232   if (!pro.verify_inputs())
233   {
234     std::cout << pro.name() << "texture classifier process2 inputs are not valid"<< std::endl;
235     return false;
236   }
237 
238   //== polygon region delineating samples of the texture
239   std::string poly_path = pro.get_input<std::string>(0);
240 
241   //== the string name of the texture category
242   std::string output_file = pro.get_input<std::string>(1);
243   std::ofstream ofs(output_file.c_str());
244   if (!ofs) {
245     std::cout << " In sdet_dump_vsol_binary_data_process() -- cannot open file: " << output_file << std::endl;
246     return false;
247   }
248 
249   // dummy classifier
250   sdet_texture_classifier_params param;
251   sdet_texture_classifier_sptr tc_ptr = new sdet_texture_classifier(param);
252   std::vector<vgl_polygon<double> > polys;
253   polys = tc_ptr->load_polys(poly_path);
254 
255   for (auto & poly : polys) {
256     for (unsigned j = 0; j < poly.num_sheets(); j++)
257       for (unsigned k = 0; k < poly[j].size(); k++)
258         ofs << poly[j][k].x() << " " << poly[j][k].y() << " ";
259     ofs << '\n';
260   }
261   ofs.close();
262   return true;
263 }
264