1 // This is brl/bpro/core/vpgl_pro/processes/vpgl_convert_to_generic_camera_process.cxx
2 #include <iostream>
3 #include <bprb/bprb_func_process.h>
4 //:
5 // \file
6 // \brief A process to convert perspective camera to rational camera.
7 
8 #ifdef _MSC_VER
9 #  include "vcl_msvc_warnings.h"
10 #endif
11 #include "vpgl/vpgl_generic_camera.h"
12 #include <vpgl/algo/vpgl_camera_compute.h>
13 #include <vpgl/algo/vpgl_camera_convert.h>
14 
15 
16 //: Init function
vpgl_convert_to_generic_camera_process_cons(bprb_func_process & pro)17 bool vpgl_convert_to_generic_camera_process_cons(bprb_func_process& pro)
18 {
19   //this process takes 4 inputs and has 3 outputs:
20   //  0) abstract camera
21   //  1) ni (# image columns)
22   //  2) nj (# image rows)
23   //  3) level (the pyramid scale)
24   std::vector<std::string> input_types;
25   input_types.emplace_back("vpgl_camera_double_sptr");
26   input_types.emplace_back("unsigned"); // ni
27   input_types.emplace_back("unsigned"); // nj
28   input_types.emplace_back("unsigned"); // level, e.g. camera needs to be scaled or not, pass the ni-nj of the original image
29   bool ok = pro.set_input_types(input_types);
30 
31   // in case the 4th input is not set
32   brdb_value_sptr idx = new brdb_value_t<unsigned>(0);
33   pro.set_input(3, idx);
34 
35   if (!ok) return ok;
36 
37   std::vector<std::string> output_types;
38   output_types.emplace_back("vpgl_camera_double_sptr");  // label image
39   output_types.emplace_back("unsigned");
40   output_types.emplace_back("unsigned");
41   return pro.set_output_types(output_types);
42 }
43 
44 //: Execute the process
vpgl_convert_to_generic_camera_process(bprb_func_process & pro)45 bool vpgl_convert_to_generic_camera_process(bprb_func_process& pro)
46 {
47   if (pro.n_inputs()!= 4) {
48     std::cout << "vpgl_convert_to_generic_camera_process: The number of inputs should be 4" << std::endl;
49     return false;
50   }
51   // get the inputs
52   vpgl_camera_double_sptr camera = pro.get_input<vpgl_camera_double_sptr>(0);
53   if (!camera) {
54     std::cout<<"Null camera input\n"<<std::endl;
55     return false;
56   }
57   auto ni = pro.get_input<unsigned>(1), nj = pro.get_input<unsigned>(2);
58   auto level = pro.get_input<unsigned>(3);
59   vpgl_generic_camera<double> gcam;
60 
61   if (!vpgl_generic_camera_convert::convert(camera, (int)ni, (int)nj, gcam, level)) {
62    std::cout<<"camera conversion failed\n"<<std::endl;
63     return false;
64   }
65   vpgl_camera_double_sptr out = new vpgl_generic_camera<double>(gcam);
66   pro.set_output_val<vpgl_camera_double_sptr>(0, out);
67   pro.set_output_val<unsigned>(1,gcam.cols());
68   pro.set_output_val<unsigned>(2,gcam.rows());
69   return true;
70 }
71 
72 //: Init function
vpgl_convert_to_generic_camera_w_margin_process_cons(bprb_func_process & pro)73 bool vpgl_convert_to_generic_camera_w_margin_process_cons(bprb_func_process& pro)
74 {
75   std::vector<std::string> input_types;
76   input_types.emplace_back("vpgl_camera_double_sptr");
77   input_types.emplace_back("unsigned");// ni
78   input_types.emplace_back("unsigned");// nj
79   input_types.emplace_back("unsigned"); // level, e.g. camera needs to be scaled or not, pass the ni-nj of the original image
80   input_types.emplace_back("int"); // margin, e.g. to create a wider expected image
81   bool ok = pro.set_input_types(input_types);
82 
83   // in case the 5th input is not set
84   brdb_value_sptr idx = new brdb_value_t<unsigned>(0);
85   pro.set_input(3, idx);
86 
87   if (!ok) return ok;
88 
89   std::vector<std::string> output_types;
90   output_types.emplace_back("vpgl_camera_double_sptr");  // label image
91   output_types.emplace_back("unsigned");
92   output_types.emplace_back("unsigned");
93   output_types.emplace_back("vpgl_camera_double_sptr");
94   return pro.set_output_types(output_types);
95 }
96 
97 //: Execute the process
vpgl_convert_to_generic_camera_w_margin_process(bprb_func_process & pro)98 bool vpgl_convert_to_generic_camera_w_margin_process(bprb_func_process& pro)
99 {
100   if (pro.n_inputs()!= 5) {
101     std::cout << "vpgl_convert_to_generic_camera_w_margin_process: The number of inputs should be 5" << std::endl;
102     return false;
103   }
104   // get the inputs
105   vpgl_camera_double_sptr camera = pro.get_input<vpgl_camera_double_sptr>(0);
106   if (!camera) {
107     std::cout<<"Null camera input\n"<<std::endl;
108     return false;
109   }
110   auto ni = pro.get_input<unsigned>(1), nj = pro.get_input<unsigned>(2);
111   auto level = pro.get_input<unsigned>(3);
112   int margin = pro.get_input<int>(4);
113   vpgl_generic_camera<double> gcam;
114 
115   auto *cam = dynamic_cast<vpgl_perspective_camera<double>*>(camera.as_pointer());
116   if (!cam) {
117     std::cout<<"Input camera is not perspective, not implemented for other camera types!\n";
118     return false;
119   }
120 
121   if (!vpgl_generic_camera_convert::convert_with_margin(*cam,(int)ni,(int)nj,gcam,margin,level)) {
122     std::cout<<"camera conversion failed\n"<<std::endl;
123     return false;
124   }
125   //: adjust the calibration matrix
126   auto* ncam =
127     new vpgl_perspective_camera<double>(*cam);
128 
129   vnl_matrix_fixed<double, 3, 3> T(0.0);
130   T[0][0] = 1.0;   T[1][1] = 1.0; T[2][2] = 1.0;
131   T[0][2] = margin;   T[1][2] = margin;
132 
133   vnl_matrix_fixed<double,3,3> M = cam->get_calibration().get_matrix();
134   M = T*M;
135   vpgl_calibration_matrix<double> K(M);
136   ncam->set_calibration(K);
137 
138   vpgl_camera_double_sptr out = new vpgl_generic_camera<double>(gcam);
139   pro.set_output_val<vpgl_camera_double_sptr>(0, out);
140   pro.set_output_val<unsigned>(1,gcam.cols());
141   pro.set_output_val<unsigned>(2,gcam.rows());
142   pro.set_output_val<vpgl_camera_double_sptr>(3,ncam);
143   return true;
144 }
145 
146 
147 //: Init function
vpgl_write_generic_camera_process_cons(bprb_func_process & pro)148 bool vpgl_write_generic_camera_process_cons(bprb_func_process& pro)
149 {
150   std::vector<std::string> input_types;
151   input_types.emplace_back("vpgl_camera_double_sptr");
152   input_types.emplace_back("vcl_string"); // name of output vrml file
153   input_types.emplace_back("unsigned"); // name of output vrml file
154   bool ok = pro.set_input_types(input_types);
155 
156   if (!ok) return ok;
157 
158   std::vector<std::string> output_types;
159   return pro.set_output_types(output_types);
160 }
161 
162 //: Execute the process
vpgl_write_generic_camera_process(bprb_func_process & pro)163 bool vpgl_write_generic_camera_process(bprb_func_process& pro)
164 {
165   if (pro.n_inputs()!= 3) {
166     std::cout << "vpgl_write_generic_camera_process: The number of inputs should be 2" << std::endl;
167     return false;
168   }
169   // get the inputs
170   vpgl_camera_double_sptr camera = pro.get_input<vpgl_camera_double_sptr>(0);
171   if (!camera) {
172     std::cout<<"Null camera input\n"<<std::endl;
173     return false;
174   }
175   std::string out_name = pro.get_input<std::string>(1);
176   auto level = pro.get_input<unsigned>(2);
177 
178   auto* gcam = dynamic_cast<vpgl_generic_camera<double>* >(camera.ptr());
179 
180   std::ofstream ofs(out_name.c_str());
181   ofs << "#VRML V2.0 utf8\n";
182   gcam->print_to_vrml(level, ofs);
183   ofs.close();
184 
185   return true;
186 }
187 
188 //: fetch the ray origin and direction for a given image pixel
vpgl_get_generic_camera_ray_process_cons(bprb_func_process & pro)189 bool vpgl_get_generic_camera_ray_process_cons(bprb_func_process& pro)
190 {
191   std::vector<std::string> input_types;
192   input_types.emplace_back("vpgl_camera_double_sptr");
193   input_types.emplace_back("unsigned"); // u
194   input_types.emplace_back("unsigned"); // v
195   bool ok = pro.set_input_types(input_types);
196 
197   if (!ok) return ok;
198 
199   std::vector<std::string> output_types;
200   output_types.emplace_back("double");  // ray origin x
201   output_types.emplace_back("double");  // ray origin y
202   output_types.emplace_back("double");  // ray origin z
203   output_types.emplace_back("double");  // ray direction x
204   output_types.emplace_back("double");  // ray direction y
205   output_types.emplace_back("double");  // ray direction z
206   return pro.set_output_types(output_types);
207 }
208 
209 //: Execute the process
vpgl_get_generic_camera_ray_process(bprb_func_process & pro)210 bool vpgl_get_generic_camera_ray_process(bprb_func_process& pro)
211 {
212   if (pro.n_inputs()!= 3) {
213     std::cout << "vpgl_get_generic_camera_ray_process: The number of inputs should be 3" << std::endl;
214     return false;
215   }
216   // get the inputs
217   vpgl_camera_double_sptr camera = pro.get_input<vpgl_camera_double_sptr>(0);
218   if (!camera) {
219     std::cout<<"Null camera input\n"<<std::endl;
220     return false;
221   }
222 
223   auto u = pro.get_input<unsigned>(1);
224   auto v = pro.get_input<unsigned>(2);
225 
226   auto* gcam = dynamic_cast<vpgl_generic_camera<double>* >(camera.ptr());
227   vgl_ray_3d<double> ray = gcam->ray(u, v);
228 
229   pro.set_output_val<double>(0, ray.origin().x());
230   pro.set_output_val<double>(1, ray.origin().y());
231   pro.set_output_val<double>(2, ray.origin().z());
232   pro.set_output_val<double>(3, ray.direction().x());
233   pro.set_output_val<double>(4, ray.direction().y());
234   pro.set_output_val<double>(5, ray.direction().z());
235   return true;
236 }
237