1 //:
2 // \file
3 // \brief executable to match queries based on the existance of distinguishable objects
4 // \author Yi Dong
5 // \date June 04, 2013
6 
7 #include <algorithm>
8 #include <boxm2/volm/desc/boxm2_volm_desc_ex_land_only_matcher.h>
9 #include <boxm2/volm/desc/boxm2_volm_desc_ex_matcher.h>
10 #include <iostream>
11 #include <utility>
12 #include <volm/desc/volm_desc_ex_2d_matcher.h>
13 #include <volm/volm_buffered_index.h>
14 #include <volm/volm_io.h>
15 #include <volm/volm_tile.h>
16 #include "vul/vul_arg.h"
17 #ifdef _MSC_VER
18 #  include "vcl_msvc_warnings.h"
19 #endif
20 
error_report(std::string error_file,const std::string & error_msg)21 void error_report(std::string error_file, const std::string& error_msg)
22 {
23   std::cerr << error_msg;
24   volm_io::write_post_processing_log(std::move(error_file), error_msg);
25 }
26 
main(int argc,char ** argv)27 int main(int argc, char** argv)
28 {
29   // query input
30   vul_arg<std::string> query_xml("-xml", "tagged xml file for query image", "");
31   vul_arg<std::string> query_vsl("-vsl", "bwm gui vxl file for query image","");
32   vul_arg<std::string> weight_file("-weight", "weight parameter file", "");
33   vul_arg<std::string> world_str("-world", "world region","");
34   vul_arg<std::string> query_name("-query-name", "query name", "");
35   vul_arg<unsigned> tile_id("-tile", "tile id", 1000);
36   // index and geolocation
37   vul_arg<std::string> geo_hypo_folder("-geo", "folder where the geolocation for this tile is stored", "");
38   vul_arg<std::string> desc_index_folder("-index", "directory that contains the created wr3db indices", "");
39   vul_arg<std::string> out_folder("-out", "output folder for the query image", "");
40   vul_arg<float> buffer_capacity("-buff", "buffer size used for loading indices", 2.0f);
41   vul_arg<bool> is_land_only("-land", "option to execute matcher using ex_land_only descriptor", false);
42   vul_arg<bool> is_ex_2d("-ex2d", "option to execute 2D existence matcher", true);
43   // post processing related
44   vul_arg<float> kl("-kl", "parameter for nonlinear score scaling", 200.0f);
45   vul_arg<float> ku("-ku", "parameter for nonlinear score scaling", 10.0f);
46   vul_arg<float> threshold("-thres", "threshold ratio for generating prob map", 0.3f);
47   vul_arg<unsigned> thresc("-thresc", "threshold that used to create candidate list", 0);
48   vul_arg<unsigned> top_size("-top", "desired top list for each candidate list", 1);
49   // options
50   vul_arg<bool> is_matcher("-match", "option to execute the matcher", false);
51   vul_arg<bool> is_cand("-cand", "option to execute the candidate list generation", false);
52 
53   vul_arg_parse(argc, argv);
54 
55   // run the existence matcher and generate probability map
56   if (is_matcher())
57   {
58     // input check
59     if (geo_hypo_folder().compare("") == 0 || desc_index_folder().compare("") == 0 || out_folder().compare("") == 0)
60     {
61       std::cerr << "ERROR: arguments error, check the input" << std::endl;
62       vul_arg_display_usage_and_exit();
63       return volm_io::EXE_ARGUMENT_ERROR;
64     }
65     if (query_xml().compare("") == 0  && query_vsl().compare("") == 0)
66     {
67       std::cerr << "ERROR: no query tagged file, either tagging xml or vsl file required" << std::endl;
68     }
69     // error log
70     std::stringstream err_log;
71     std::stringstream err_log_file;
72     err_log_file << out_folder() << "/err_log.xml";
73     // load the query information
74     std::string world_region;
75     std::string query_name;
76     unsigned ni, nj;
77     std::vector<volm_weight> weights;
78     depth_map_scene_sptr dms = new depth_map_scene;
79 
80     // load query
81     if (!vul_file::exists(query_xml())) {  // load query from vxl file and weight from weight file
82       world_region = world_str();
83       vsl_b_ifstream dis(query_vsl().c_str());
84       dms->b_read(dis);
85       dis.close();
86       // obtain the query name from image file name
87       query_name = vul_file::strip_extension(vul_file::strip_directory(dms->image_path()));
88       // load the weight parameter, if file does not exist, use average weight
89       if (vul_file::exists(weight_file()) ) {
90         // read the weight parameter from pre-loaded
91         volm_weight::read_weight(weights, weight_file());
92         // check whether the loaded weight parameters satisfy the requirement, if not, create default equal weight parameters
93         if (!volm_weight::check_weight(weights)) {
94           weights.clear();
95           volm_weight::equal_weight(weights, dms);
96         }
97       }
98       else {
99         // create equal weight parameter for all objects
100         volm_weight::equal_weight(weights, dms);
101       }
102       // check self_consistency between dms and loaded weight parameters
103       if (!dms->ground_plane().empty()) {
104         bool has_grd = false;
105         for (auto & weight : weights)
106           if ( weight.w_typ_ == "ground_plane" || weight.w_typ_ == "ground" ) {
107             has_grd = true;
108             break;
109           }
110         if (!has_grd) {
111           err_log << " ERROR: inconsistency between depth_map_scene and weight parameter in ground plane\n";
112           error_report(err_log_file.str(), err_log.str());
113           return volm_io::EXE_ARGUMENT_ERROR;
114         }
115       }
116       if (weights.size() != (!dms->sky().empty() + !dms->ground_plane().empty() + dms->scene_regions().size())) {
117         std::cout << " weights_size = " << weights.size() << std::endl;
118         std::cout << " depth map scene size = " << !dms->sky().empty() + !dms->ground_plane().empty() + dms->scene_regions().size() << std::endl;
119         for (auto & weight : weights) {
120           std::cout << " \t\t" << weight.w_name_ << " " << weight.w_obj_ << std::endl;
121         }
122         err_log << " ERROR: number of weight parameters is different from labeled depth_map_region objects\n";
123         error_report(err_log_file.str(), err_log.str());
124         return volm_io::EXE_ARGUMENT_ERROR;
125       }
126     }
127     else {
128       if (!vul_file::exists(query_xml())) {  // load query and weight from tagging xml file
129         err_log << "ERROR: can not find query tag xml file: " << query_xml() << '\n';
130         error_report(err_log_file.str(), err_log.str());
131         return volm_io::EXE_ARGUMENT_ERROR;
132       }
133       volm_io::read_query_tags(query_xml(), dms, weights, world_region, ni, nj, query_name);
134       // check weight parameter (Note during parser, all labeled object are parsed into scene_regions, i.e., no sky or ground_plane
135       if (weights.size() != dms->scene_regions().size()) {
136         err_log << "ERROR: number of weight parameters (" << weights.size() << ") is inconsistent with labeled object (" << dms->scene_regions().size() << ")\n";
137         error_report(err_log_file.str(), err_log.str());
138         return volm_io::EXE_ARGUMENT_ERROR;
139       }
140     }
141 
142     std::string image_name = vul_file::strip_extension(query_name);
143 
144     // create tiles based on world_region
145     std::vector<volm_tile> tiles;
146     if (world_region.compare("Chile")==0)             tiles = volm_tile::generate_p1b_wr1_tiles();
147     else if (world_region.compare("India")==0)        tiles = volm_tile::generate_p1b_wr2_tiles();
148     else if (world_region.compare("Jordan")==0)       tiles = volm_tile::generate_p1b_wr3_tiles();
149     else if (world_region.compare("Philippines")==0)  tiles = volm_tile::generate_p1b_wr4_tiles();
150     else if (world_region.compare("Taiwan")== 0)      tiles = volm_tile::generate_p1b_wr5_tiles();
151     else if (world_region.compare("Coast")== 0)       tiles = volm_tile::generate_p1_wr2_tiles();
152     else if (world_region.compare("Desert")== 0)      tiles = volm_tile::generate_p1_wr1_tiles();
153     else {
154       err_log << "ERROR: unknown ROI region: " << world_region << ", check tag xml.  Available regions are: Coast, Desert, Chile, India, Jordan, Philippines, Taiwan\n";
155       error_report(err_log_file.str(), err_log.str());
156       return volm_io::EXE_ARGUMENT_ERROR;
157     }
158     if (tile_id() >= tiles.size()) {
159       err_log << "ERROR: unknown tile id " << tile_id() << " for ROI region: " << world_region << "!\n";
160       error_report(err_log_file.str(), err_log.str());
161       return volm_io::EXE_ARGUMENT_ERROR;
162     }
163 
164     // create ex_matcher
165     std::stringstream params_file_pre;
166     params_file_pre << desc_index_folder() << "/desc_index_tile_" << tile_id();
167     //std::string params_file_pre = desc_index_folder() + "/desc_index_tile_0";
168     volm_buffered_index_params params;
169     if (!params.read_ex_param_file(params_file_pre.str())) {
170       err_log << " ERROR: fetching parameter failed from file: " << params_file_pre.str() << ".params\n";
171       error_report(err_log_file.str(), err_log.str());
172       return volm_io::EXE_ARGUMENT_ERROR;
173     }
174     volm_desc_matcher_sptr ex_matcher;
175     if (is_land_only()) {
176       ex_matcher = new boxm2_volm_desc_ex_land_only_matcher(dms, params.radius, params.nlands, 0);
177     }
178     else if (is_ex_2d()) {
179       ex_matcher = new volm_desc_ex_2d_matcher(dms, weights, params.radius, params.nlands, 0);
180     }
181     else {
182       ex_matcher = new boxm2_volm_desc_ex_matcher(dms, params.radius, params.norients, params.nlands, 0);
183     }
184 
185     // create query
186     volm_desc_sptr query = ex_matcher->create_query_desc();
187     std::string query_file = out_folder() + "/query_annotation.svg";
188     query->visualize(query_file, 2);
189 
190     // Screen output
191     std::cout << " =========== Start to execute existence matcher for image: " << image_name << " ===============" << std::endl;
192     std::cout << " \t Descriptor type : " << ex_matcher->get_index_type_str() << std::endl;
193     std::cout << " \t world region: " << world_region << std::endl;
194     std::cout << " \t weight parameters: " << std::endl;
195     for (auto & weight : weights) {
196       std::cout << " \t\t" << weight.w_name_ << " " << weight.w_obj_ << std::endl;
197     }
198     std::cout << " \t query " << query_name << " has following objects " << std::endl;
199     std::vector<depth_map_region_sptr> obj = dms->scene_regions();
200     for (unsigned i = 0; i < obj.size(); i++)
201       std::cout << " \t\t" << obj[i]->name() << " --- mindist = " << obj[i]->min_depth() << ", maxdist = " << obj[i]->max_depth()
202                << ", land = " << volm_osm_category_io::volm_land_table[obj[i]->land_id()].name_
203                << ", weight = " << weights[i].w_obj_ << std::endl;
204     std::cout << " \t query descriptor:\n";
205     query->print();
206     std::cout << std::endl;
207 
208     // start the matcher
209     for (unsigned t_id = 0; t_id < tiles.size(); t_id++)
210     {
211       if (t_id != tile_id())
212         continue;
213       std::cout << " matcher on tile " << t_id << " in " << tiles.size() << " tiles...\n";
214       std::cout << std::flush;
215       // run matcher
216       if (!ex_matcher->matcher(query, geo_hypo_folder(), desc_index_folder(), buffer_capacity(), t_id)) {
217         err_log << "ERROR: matcher on tile " << t_id << " failed\n";
218         error_report(err_log_file.str(), err_log.str());
219         return volm_io::EXE_MATCHER_FAILED;
220       }
221       // save score binary
222       if (!ex_matcher->write_out(out_folder(), t_id)) {
223         err_log << "ERROR: matcher on tile " << t_id << " failed (can not save score binary)\n";
224         error_report(err_log_file.str(), err_log.str());
225         return volm_io::EXE_MATCHER_FAILED;
226       }
227       // create probability map
228       float gt_score = -1.0f;
229       vgl_point_3d<double> gt_loc(0.0,0.0,0.0);
230       if (!ex_matcher->create_prob_map(geo_hypo_folder(), out_folder(), t_id, tiles[t_id], gt_loc, gt_score)) {
231         err_log << " ERROR: creating probability map for tile " << t_id << " failed\n";
232         error_report(err_log_file.str(), err_log.str());
233         return volm_io::POST_PROCESS_FAILED;
234       }
235       // create scaled probability map
236       float thres_value = threshold();
237       std::cout << " \t threshold used for scaling probability maps: " << thres_value << std::endl;
238       if (!volm_desc_matcher::create_scaled_prob_map(out_folder(), tiles[t_id], t_id, ku(), kl(), thres_value)) {
239         err_log << "ERROR: create scaled probability map for tile " << t_id << " failed\n";
240         error_report(err_log_file.str(), err_log.str());
241         return volm_io::POST_PROCESS_FAILED;
242       }
243     }
244     std::cout << " ========================================== Finish ===============================================" << std::endl;
245   }
246   // generate candidate list once we have the scaled_probability map
247   if (is_cand())
248   {
249     if (out_folder().compare("") == 0) {
250       std::cerr << "ERROR: output folder and probability map folder can not be empty when creating candidate list.  Check input" << std::endl;
251       vul_arg_display_usage_and_exit();
252       return volm_io::EXE_ARGUMENT_ERROR;
253     }
254     std::stringstream log;
255     std::stringstream log_file;
256     log_file << out_folder() << "/error_log_candidate_list.xml";
257     std::cout << " ============== Start to create candidate list ==================" << std::endl;
258     std::stringstream cand_folder;
259     cand_folder << out_folder() << "/T_" << thresc();
260     if (!vul_file::is_directory(cand_folder.str()))
261       vul_file::make_directory(cand_folder.str());
262     std::cout << "\t threshold: " << thresc() << std::endl;
263     std::cout << "\t probability maps are stored in: " << out_folder() << std::endl;
264     std::cout << "\t result stored in: " << cand_folder.str() << std::endl;
265     if (!volm_desc_matcher::create_candidate_list(out_folder(), cand_folder.str(), thresc(), top_size(), ku(), kl(), threshold(), query_name(), world_str())) {
266       //log << " creating candidate list failed at threshold " << thresc() << '\n';
267       //error_report(log_file.str(), log.str());
268       return volm_io::EXE_ARGUMENT_ERROR;
269     }
270     std::cout << " =========================== Finish =============================" << std::endl;
271     return volm_io::SUCCESS;
272   }
273 
274   return volm_io::SUCCESS;
275 }
276 #if 0
277 int main(int argc, char** argv)
278 {
279   // query input
280   vul_arg<std::string> depth_scene("-dms", "depth map scene file", "");
281   vul_arg<std::string> weight_file("-weight", "weight parameter file", "");
282   // index and geolocation
283   vul_arg<unsigned> world_id("-world", "world id to specify the ROI region", 100);
284   vul_arg<unsigned> tile_id("-tile", "tile id to specify which tile are being matched", 100);
285   vul_arg<std::string> geo_hypo_folder("-geo", "folder where the geolocation for this tile is stored", "");
286   vul_arg<std::string> desc_index_folder("-index", "directory that contains the created wr3db indices", "");
287   vul_arg<std::string> out_folder("-out", "output folder for the query image", "");
288   vul_arg<float> buffer_capacity("-buff", "buffer size used for loading indices", 2.0f);
289   vul_arg<bool> is_land_only("-land", "option to execute matcher using ex_land_only descriptor", false);
290   vul_arg<bool> is_ex_2d("-ex2d", "option to execute 2D existence matcher", true);
291   // post processing related
292   vul_arg<std::string> gt_file("-gt", "ground truth files", "");
293   vul_arg<float> kl("-kl", "parameter for nonlinear score scaling", 200.0f);
294   vul_arg<float> ku("-ku", "parameter for nonlinear score scaling", 10.0f);
295   vul_arg<float> threshold("-thres", "threshold ratio for generating prob map", 0.3);
296   vul_arg<unsigned> test_id("-testid", "phase 1 test id", 1);
297   vul_arg<unsigned> id("-imgid", "query image id", 21);
298   vul_arg<unsigned> thresc("-thresc", "threshold that used to create candidate list", 0);
299   vul_arg<unsigned> top_size("-top", "desired top list for each candidate list", 1);
300   // options
301   vul_arg<bool> is_matcher("-match", "option to execute the matcher", false);
302   vul_arg<bool> is_cand("-cand", "option to execute the candidate list generation", false);
303 
304   vul_arg_parse(argc, argv);
305 
306   std::stringstream image_name;
307   if (id() < 10)
308     image_name << "p1b_test" << test_id() << "_00" << id();
309   else if (id() >= 10 && id() < 100)
310     image_name << "p1b_test" << test_id() << "_0" << id();
311   else
312     image_name << "p1b_test" << test_id() << "_"  << id();
313   // run the existence matcher and generate probability map
314   if (is_matcher()) {
315     // check the argument
316     if (depth_scene().compare("") == 0 || geo_hypo_folder().compare("") == 0 || weight_file().compare("") == 0 ||
317         desc_index_folder().compare("") == 0 || out_folder().compare("") == 0 ||
318         gt_file().compare("") == 0 || id() > 200 || test_id() == 0 || tile_id() == 100 || world_id() == 100)
319     {
320       std::cerr << " ERROR: arguments error, check the input " << std::endl;
321       vul_arg_display_usage_and_exit();
322       return volm_io::EXE_ARGUMENT_ERROR;
323     }
324 
325     // error log
326     std::stringstream err_log;
327     std::stringstream err_log_file;
328     err_log_file << out_folder() << "/err_log_tile_" << tile_id() << ".xml";
329 
330 
331     // load the depth map scene
332     if (!vul_file::exists(depth_scene())) {
333       err_log << " ERROR: can not find depth map scene file" << depth_scene() << '\n';
334       std::cerr << err_log;
335       volm_io::write_post_processing_log(err_log_file.str(), err_log.str());
336       return volm_io::EXE_ARGUMENT_ERROR;
337     }
338     depth_map_scene_sptr dms = new depth_map_scene;
339     vsl_b_ifstream dis(depth_scene().c_str());
340     dms->b_read(dis);
341     dis.close();
342 
343     // load the weight parameter, if file does not exist, use average weight
344     std::vector<volm_weight> weights;
345     if (vul_file::exists(weight_file()) ) {
346       // read the weight parameter from pre-loaded
347       volm_weight::read_weight(weights, weight_file());
348       // check whether the loaded weight parameters satisfy the requirement, if not, create default equal weight parameters
349       if (!volm_weight::check_weight(weights)) {
350         weights.clear();
351         volm_weight::equal_weight(weights, dms);
352       }
353     }
354     else {
355       // create equal weight parameter for all objects
356       volm_weight::equal_weight(weights, dms);
357     }
358 
359     // check self_consistency between dms and loaded weight parameters
360     if (!dms->ground_plane().empty()) {
361       bool has_grd = false;
362       for (std::vector<volm_weight>::iterator wit = weights.begin();  wit != weights.end();  ++wit)
363         if ( (*wit).w_typ_ == "ground_plane" ) {
364           has_grd = true;
365           break;
366         }
367       if (!has_grd) {
368         err_log << " ERROR: inconsistency between depth_map_scene and weight parameter in ground plane\n";
369         error_report(err_log_file.str(), err_log.str());
370         return volm_io::EXE_ARGUMENT_ERROR;
371       }
372     }
373     if (weights.size() != (!dms->sky().empty() + !dms->ground_plane().empty() + dms->scene_regions().size())) {
374       std::cout << " weights_size = " << weights.size() << std::endl;
375       std::cout << " depth map scene size = " << !dms->sky().empty() + !dms->ground_plane().empty() + dms->scene_regions().size() << std::endl;
376       for (unsigned i = 0; i < weights.size(); i++) {
377         std::cout << " \t\t" << weights[i].w_name_ << " " << weights[i].w_obj_ << std::endl;
378       }
379       err_log << " ERROR: number of weight parameters is different from labeled depth_map_region objects\n";
380       error_report(err_log_file.str(), err_log.str());
381       return volm_io::EXE_ARGUMENT_ERROR;
382     }
383 
384     // fetch the ground truth location
385     if (!vul_file::exists(gt_file())) {
386       err_log << " ERROR: can not find ground truth file" << gt_file() << '\n';
387       error_report(err_log_file.str(), err_log.str());
388       return volm_io::EXE_ARGUMENT_ERROR;
389     }
390     std::vector<std::pair<vgl_point_3d<double>, std::pair<std::pair<std::string, int>, std::string> > > samples;
391     unsigned int cnt = volm_io::read_gt_file(gt_file(), samples);
392 
393     int img_info_id = -1;
394     for (unsigned kk = 0; kk < samples.size(); kk++) {
395       if (samples[kk].second.first.second == id()) {
396         img_info_id = kk;
397         break;
398       }
399     }
400     //if (query_img_info.size() <= img_id()) {
401     if (img_info_id < 0) {
402       std::cerr << "query image id: " << id() << " cannot be found in the gt loc file: " << gt_file() << "!\n";
403       return volm_io::EXE_ARGUMENT_ERROR;
404     }
405 
406     vgl_point_3d<double> gt_loc;
407     gt_loc = samples[img_info_id].first;
408 
409     //// create coast tiles
410     //std::vector<volm_tile> tiles = volm_tile::generate_p1_wr2_tiles();
411     std::vector<volm_tile> tiles;
412     if (world_id() == 1)     tiles = volm_tile::generate_p1b_wr1_tiles();
413     else if (world_id() == 2) tiles = volm_tile::generate_p1b_wr2_tiles();
414     else if (world_id() == 3) tiles = volm_tile::generate_p1b_wr3_tiles();
415     else if (world_id() == 4) tiles = volm_tile::generate_p1b_wr4_tiles();
416     else if (world_id() == 5) tiles = volm_tile::generate_p1b_wr5_tiles();
417     else {
418       err_log << " ERROR: unknown world id: " << world_id() << " (only 1 to 5 allowed) " << std::endl;
419       error_report(err_log_file.str(), err_log.str());
420       return volm_io::EXE_ARGUMENT_ERROR;
421     }
422 
423     // create ex_matcher
424     std::string params_file_pre = desc_index_folder() + "/desc_index_tile_0";
425     volm_buffered_index_params params;
426     if (!params.read_ex_param_file(params_file_pre)) {
427       err_log << " ERROR: fetching parameter failed from file: " << params_file_pre << ".params\n";
428       error_report(err_log_file.str(), err_log.str());
429       return volm_io::EXE_ARGUMENT_ERROR;
430     }
431 
432     volm_desc_matcher_sptr ex_matcher;
433     if (is_land_only()) {
434       ex_matcher = new boxm2_volm_desc_ex_land_only_matcher(dms, params.radius, params.nlands, 0);
435     }
436     else if (is_ex_2d()) {
437       ex_matcher = new volm_desc_ex_2d_matcher(dms, weights, params.radius, params.nlands, 0);
438     }
439     else {
440       ex_matcher = new boxm2_volm_desc_ex_matcher(dms, params.radius, params.norients, params.nlands, 0);
441     }
442 
443     std::cout << " ex_matcher is " << ex_matcher->get_index_type_str() << std::endl;
444 
445     // create query
446     volm_desc_sptr query = ex_matcher->create_query_desc();
447     std::string query_file = out_folder() + "/" + "query_annotation.svg";
448     query->visualize(query_file, 2);
449 
450     std::cout << " query = ";
451     query->print();
452     std::cout << std::endl;
453 
454     // start the matcher
455     std::cout << " =========== Start to execute existence matcher on tile " << tile_id() << " for image: " << image_name.str() << " ===============" << std::endl;
456     std::cout << " \t Descriptor type : " << ex_matcher->get_index_type_str() << std::endl;
457     std::cout << " \t weight parameters: " << std::endl;
458     for (unsigned i = 0; i < weights.size(); i++) {
459       std::cout << " \t\t" << weights[i].w_name_ << " " << weights[i].w_obj_ << std::endl;
460     }
461     if (tile_id() != 10) {
462       if (!ex_matcher->matcher(query, geo_hypo_folder(), desc_index_folder(), buffer_capacity(), tile_id())) {
463         err_log << " ERROR: matcher for tile " << tile_id() << " failed\n";
464         error_report(err_log_file.str(), err_log.str());
465         return volm_io::EXE_ARGUMENT_ERROR;
466       }
467       // save the score binary
468       if (!ex_matcher->write_out(out_folder(), tile_id())) {
469         err_log << " ERROR: save the score binary file for tile " << tile_id() << " failed\n";
470         error_report(err_log_file.str(), err_log.str());
471         return volm_io::EXE_ARGUMENT_ERROR;
472       }
473     }
474     // create probability map
475     float gt_score = -1.0f;
476     if (!ex_matcher->create_prob_map(geo_hypo_folder(), out_folder(), tile_id(), tiles[tile_id()], gt_loc, gt_score)) {
477       err_log << " ERROR: creating probability map for tile " << tile_id() << " failed\n";
478       error_report(err_log_file.str(), err_log.str());
479       return volm_io::POST_PROCESS_FAILED;
480     }
481     if (gt_score != -1.0f) {
482       // record the ground score
483       std::stringstream gt_log;
484       std::string gt_log_file = out_folder() + "/gt_score.xml";
485       gt_log << " closest geolocation relative to ground truth [" << gt_loc.x() << ", " << gt_loc.y()
486              << "] is in tile " << tile_id() << ", having score = " << gt_score << '\n';
487       volm_io::write_post_processing_log(gt_log_file, gt_log.str());
488     }
489     std::cout << "\t geo hypothesis folder: " << geo_hypo_folder() << std::endl;
490     std::cout << "\t existence index folder: " << desc_index_folder() << std::endl;
491     std::cout << "\t query image has " << query->get_area() << " bins" << std::endl;
492 
493     if (gt_score != -1.0f)
494       std::cout << "\t ground truth location is in tile " << tile_id() << " with score = " << gt_score << std::endl;
495 
496     // create scaled probability map
497     float thres_value = threshold();
498     //ex_matcher->check_threshold(query, thres_value);
499     if (thres_value != threshold())
500       std::cout << "\t NOTE: the threshold given has changed from " << threshold() << " to " << thres_value << std::endl;
501     std::cout << "\t threshold used for scaling probability maps: " << thres_value << std::endl;
502     if (!volm_desc_matcher::create_scaled_prob_map(out_folder(), tiles[tile_id()], tile_id(), ku(), kl(), thres_value)) {
503       err_log << " ERROR: creating scaled probability map for tile " << tile_id() << " failed\n";
504       error_report(err_log_file.str(), err_log.str());
505       return volm_io::POST_PROCESS_FAILED;
506     }
507     std::cout << " ========================================== Finish ===============================================" << std::endl;
508   }
509   // generate candidate list once we have the scaled_probability_map
510   if (is_cand()) {
511     if (out_folder().compare("") == 0) {
512       std::cerr << " ERROR: output folder and probability map folder can not be empty when creating candidate list.  Check input" << std::endl;
513       vul_arg_display_usage_and_exit();
514       return volm_io::EXE_ARGUMENT_ERROR;
515     }
516     std::stringstream log;
517     std::stringstream log_file;
518     log_file << out_folder() << "/error_log_candidate_list.xml";
519 
520     std::cout << " =========== Start to create candidate list for image: " << image_name.str() << " ===============" << std::endl;
521     std::stringstream prob_map_folder;
522     prob_map_folder << out_folder() << "/ProbMap_scaled_" << threshold();
523 
524     if (!vul_file::exists(prob_map_folder.str())) {
525       log << " can not find the directory for probability map: " << prob_map_folder.str() << '\n';
526       error_report(log_file.str(), log.str());
527       return volm_io::EXE_ARGUMENT_ERROR;
528     }
529 
530     std::stringstream cand_folder;
531     cand_folder << out_folder() << "/T_" << thresc() ;
532     if( !vul_file::is_directory(cand_folder.str()))
533     vul_file::make_directory(cand_folder.str());
534 
535     std::cout << "\t threshold: " << thresc() << std::endl;
536     std::cout << "\t threshold used for the probability maps: " << threshold() << std::endl;
537     std::cout << "\t probability maps are stored in: " << prob_map_folder.str() << std::endl;
538     std::cout << "\t result stored in: " << cand_folder.str() << std::endl;
539     if (!volm_desc_matcher::create_candidate_list(prob_map_folder.str(), cand_folder.str(), thresc(), top_size(), ku(), kl(), threshold(), test_id(), id(), world_id())) {
540       log << " creating candidate list failed for image " << id() << " at threshold " << thresc() << '\n';
541       error_report(log_file.str(), log.str());
542       std::cout << " ========================================== Failed ========================================" << std::endl;
543       return volm_io::EXE_ARGUMENT_ERROR;
544     }
545     std::cout << " ========================================== Finish ========================================" << std::endl;
546     return volm_io::SUCCESS;
547   }
548 
549   return volm_io::SUCCESS;
550 }
551 #endif
552