1 #include <iostream>
2 #include <cstring>
3 #ifdef _MSC_VER
4 # include "vcl_msvc_warnings.h"
5 #endif
6
7 #include "vgl/vgl_box_2d.h"
8 #include "vgl/vgl_box_3d.h"
9 #include "vgl/vgl_point_2d.h"
10 #include "vgl/vgl_point_3d.h"
11 #include <vsol/vsol_box_2d.h>
12
13 #include <vil/vil_config.h> // for HAS_GEOTIFF definition
14 #include "vil/vil_load.h"
15 #include "vil/vil_image_resource.h"
16 #include <vil/file_formats/vil_tiff.h>
17
18 #include <bprb/bprb_parameters.h>
19 #include <bprb/bprb_func_process.h>
20
21 #include "vpgl/vpgl_lvcs.h"
22 #include <vpgl/file_formats/vpgl_geo_camera.h>
23
24 #include <brip/brip_roi.h>
25 #include <brdb/brdb_value.h>
26 #include <bmdl/bmdl_classify.h>
27
28 template<class T>
corners_of_box_3d(vgl_box_3d<T> box)29 std::vector<vgl_point_3d<T> > corners_of_box_3d(vgl_box_3d<T> box)
30 {
31 std::vector<vgl_point_3d<T> > corners;
32
33 corners.push_back(box.min_point());
34 corners.push_back(vgl_point_3d<T> (box.min_x()+box.width(), box.min_y(), box.min_z()));
35 corners.push_back(vgl_point_3d<T> (box.min_x()+box.width(), box.min_y()+box.height(), box.min_z()));
36 corners.push_back(vgl_point_3d<T> (box.min_x(), box.min_y()+box.height(), box.min_z()));
37 corners.push_back(vgl_point_3d<T> (box.min_x(), box.min_y(), box.max_z()));
38 corners.push_back(vgl_point_3d<T> (box.min_x()+box.width(), box.min_y(), box.max_z()));
39 corners.push_back(box.max_point());
40 corners.push_back(vgl_point_3d<T> (box.min_x(), box.min_y()+box.height(), box.max_z()));
41 return corners;
42 }
43
compute_ground(const vil_image_resource_sptr & ground,const vil_image_view_base_sptr & first_roi,const vil_image_view_base_sptr & last_roi,vil_image_view_base_sptr & ground_roi)44 bool compute_ground(const vil_image_resource_sptr& ground,
45 const vil_image_view_base_sptr& first_roi,
46 const vil_image_view_base_sptr& last_roi,
47 vil_image_view_base_sptr& ground_roi)
48 {
49 if (ground == nullptr)
50 {
51 if ((first_roi->pixel_format() == VIL_PIXEL_FORMAT_FLOAT) &&
52 (last_roi->pixel_format() == VIL_PIXEL_FORMAT_FLOAT)) {
53 auto* ground_view = new vil_image_view<float>();
54 vil_image_view<float> first_view(first_roi);
55 vil_image_view<float> last_view(last_roi);
56 bmdl_classify<float> classifier;
57 classifier.set_lidar_data(first_view, last_view);
58 classifier.estimate_bare_earth();
59 ground_view->deep_copy(classifier.bare_earth());
60 ground_roi = ground_view;
61 }
62 else if ((first_roi->pixel_format() == VIL_PIXEL_FORMAT_DOUBLE) &&
63 (last_roi->pixel_format() == VIL_PIXEL_FORMAT_DOUBLE)) {
64 auto* ground_view = new vil_image_view<double>();
65 vil_image_view<double> first_view(first_roi);
66 vil_image_view<double> last_view(last_roi);
67 bmdl_classify<double> classifier;
68 classifier.set_lidar_data(first_view, last_view);
69 classifier.estimate_bare_earth();
70 ground_view->deep_copy(classifier.bare_earth());
71 ground_roi = ground_view;
72 }
73 else {
74 std::cout << "input images have different bit depths" << std::endl;
75 return false;
76 }
77 }
78 return true;
79 }
80
81
lidar_roi(unsigned type,const vil_image_resource_sptr & lidar_first,const vil_image_resource_sptr & lidar_last,const vil_image_resource_sptr & ground,float min_lat,float min_lon,float max_lat,float max_lon,vil_image_view_base_sptr & first_roi,vil_image_view_base_sptr & last_roi,vil_image_view_base_sptr & ground_roi,vpgl_geo_camera * & camera)82 bool lidar_roi(unsigned type, //0 for geo coordinates, 1 for image coord
83 const vil_image_resource_sptr& lidar_first,
84 const vil_image_resource_sptr& lidar_last,
85 const vil_image_resource_sptr& ground,
86 float min_lat, float min_lon,
87 float max_lat, float max_lon,
88 vil_image_view_base_sptr& first_roi,
89 vil_image_view_base_sptr& last_roi,
90 vil_image_view_base_sptr& ground_roi,
91 vpgl_geo_camera*& camera)
92 {
93 // the file should be at least a tiff (better, geotiff)
94 if (std::strcmp(lidar_first->file_format(), "tiff") != 0 &&
95 std::strcmp(lidar_last->file_format(),"tiff") != 0) {
96 std::cout << "bmdl_lidar_roi_process::lidar_roi -- The lidar images should be a TIFF!\n";
97 return false;
98 }
99
100 #if HAS_GEOTIFF
101 auto* tiff_first = static_cast<vil_tiff_image*> (lidar_first.ptr());
102 auto* tiff_last = static_cast<vil_tiff_image*> (lidar_last.ptr());
103
104 if (vpgl_geo_camera::init_geo_camera(tiff_first, nullptr, camera))
105 {
106 vgl_box_2d<double> roi_box;
107
108 if (type == 0) // geographic coordinates
109 {
110 // backproject the 3D world coordinates on the image
111 vgl_point_3d<double> min_pos(min_lon, min_lat, 0);
112 vgl_point_3d<double> max_pos(max_lon, max_lat, 30);
113 vgl_box_3d<double> world(min_pos, max_pos);
114 std::vector<vgl_point_3d<double> > corners = corners_of_box_3d<double>(world);
115 for (auto & corner : corners) {
116 double x = corner.x();
117 double y = corner.y();
118 double z = corner.z();
119 double lx, ly, lz;
120 camera->lvcs()->global_to_local(x, y, z,vpgl_lvcs::wgs84, lx, ly, lz);
121 double u,v;
122 camera->project(lx,ly,lz,u,v);
123 vgl_point_2d<double> p(u,v);
124 roi_box.add(p);
125 }
126 }
127 else if (type == 1) {
128 roi_box.add(vgl_point_2d<double> (min_lat, min_lon));
129 roi_box.add(vgl_point_2d<double> (max_lat, max_lon));
130 }
131
132 brip_roi broi(tiff_first->ni(), tiff_first->nj());
133 vsol_box_2d_sptr bb = new vsol_box_2d();
134 bb->add_point(roi_box.min_x(), roi_box.min_y());
135 bb->add_point(roi_box.max_x(), roi_box.max_y());
136
137 bb = broi.clip_to_image_bounds(bb);
138 //std::cout << "Cut out area------>" << std::endl;
139 //std::cout << *bb << std::endl;
140 first_roi = tiff_first->get_copy_view((unsigned int)bb->get_min_x(),
141 (unsigned int)bb->width(),
142 (unsigned int)bb->get_min_y(),
143 (unsigned int)bb->height());
144
145 last_roi = tiff_last->get_copy_view((unsigned int)bb->get_min_x(),
146 (unsigned int)bb->width(),
147 (unsigned int)bb->get_min_y(),
148 (unsigned int)bb->height());
149
150 // if no ground input, create an estimated one
151 if (ground == nullptr) {
152 compute_ground(ground, first_roi, last_roi, ground_roi);
153 }
154 else { // crop the given one
155 ground_roi = ground->get_copy_view((unsigned int)bb->get_min_x(),
156 (unsigned int)bb->width(),
157 (unsigned int)bb->get_min_y(),
158 (unsigned int)bb->height());
159 }
160
161 //add the translation to the camera
162 double ox = bb->get_min_x();
163 double oy = bb->get_min_y();
164 double elev = 0;
165 if (ground_roi->pixel_format() == VIL_PIXEL_FORMAT_FLOAT) {
166 vil_image_view<float> ground_view(ground_roi);
167 elev = ground_view(0,0);
168 }
169 else if (ground_roi->pixel_format() == VIL_PIXEL_FORMAT_DOUBLE) {
170 vil_image_view<double> ground_view(ground_roi);
171 elev = ground_view(0,0);
172 }
173 camera->translate(ox, oy, elev);
174
175 if (!first_roi) {
176 std::cout << "bmdl_lidar_roi_process::lidar_init()-- clipping box is out of image boundaries\n";
177 return false;
178 }
179 }
180 else {
181 std::cout << "bmdl_lidar_roi_process::lidar_init()-- Only ProjectedCSTypeGeoKey=PCS_WGS84_UTM_zoneXX_X is defined rigth now, please define yours!!" << std::endl;
182 return false;
183 }
184
185 return true;
186 #else // if !HAS_GEOTIFF
187 std::cout << "bmdl_lidar_roi_process::lidar_init()-- GEOTIFF lib is needed to run bmdl_lidar_roi_process--\n";
188 return false;
189 #endif // HAS_GEOTIFF
190
191 return true;
192 }
193
bmdl_lidar_roi_process(bprb_func_process & pro)194 bool bmdl_lidar_roi_process(bprb_func_process& pro)
195 {
196 if (pro.n_inputs()< 8) {
197 std::cout << "lidar_roi_process: The input number should be 8" << std::endl;
198 return false;
199 }
200
201 unsigned int i=0;
202 std::string first = pro.get_input<std::string>(i++);
203 std::string last = pro.get_input<std::string>(i++);
204 std::string ground = pro.get_input<std::string>(i++);
205 auto min_lat = pro.get_input<float>(i++);
206 auto min_lon = pro.get_input<float>(i++);
207 auto max_lat = pro.get_input<float>(i++);
208 auto max_lon = pro.get_input<float>(i++);
209 auto type = pro.get_input<unsigned>(i++);
210
211 // check first return's validity
212 vil_image_resource_sptr first_ret = vil_load_image_resource(first.c_str());
213 if (!first_ret) {
214 std::cout << "bmdl_lidar_roi_process -- First return image path is not valid!\n";
215 return false;
216 }
217
218 // check last return's validity
219 vil_image_resource_sptr last_ret = vil_load_image_resource(last.c_str());
220 if (!last_ret) {
221 std::cout << "bmdl_lidar_roi_process -- Last return image path is not valid!\n";
222 return false;
223 }
224
225 // Ground image path can be invalid or empty, in that case an estimated ground will be computed
226 vil_image_resource_sptr ground_img =nullptr;
227 if (ground.size() > 0) {
228 ground_img = vil_load_image_resource(ground.c_str());
229 }
230
231 vil_image_view_base_sptr first_roi=nullptr, last_roi=nullptr, ground_roi;
232 vpgl_geo_camera* lidar_cam =nullptr;
233 if (!lidar_roi(type, first_ret, last_ret, ground_img,
234 min_lat, min_lon, max_lat, max_lon, first_roi, last_roi, ground_roi, lidar_cam)) {
235 std::cout << "bmdl_lidar_roi_process -- The process has failed!\n";
236 return false;
237 }
238
239 unsigned j=0;
240 // store image output (first return roi)
241 pro.set_output_val<vil_image_view_base_sptr>(j++, first_roi);
242
243 // store image output (last return roi)
244 pro.set_output_val<vil_image_view_base_sptr>(j++,last_roi);
245
246 // store image output (ground roi)
247 pro.set_output_val<vil_image_view_base_sptr>(j++,ground_roi);
248
249 // store the camera (camera of first return is sufficient)
250 pro.set_output_val<vpgl_camera_double_sptr >(j++, lidar_cam);
251
252 return true;
253 }
254
bmdl_lidar_roi_process_cons(bprb_func_process & pro)255 bool bmdl_lidar_roi_process_cons(bprb_func_process& pro)
256 {
257 bool ok=false;
258 std::vector<std::string> input_types;
259 input_types.emplace_back("vcl_string");
260 input_types.emplace_back("vcl_string");
261 input_types.emplace_back("vcl_string");
262 input_types.emplace_back("float");
263 input_types.emplace_back("float");
264 input_types.emplace_back("float");
265 input_types.emplace_back("float");
266 input_types.emplace_back("unsigned");
267 ok = pro.set_input_types(input_types);
268 if (!ok) return ok;
269
270 std::vector<std::string> output_types;
271 output_types.emplace_back("vil_image_view_base_sptr"); // label image
272 output_types.emplace_back("vil_image_view_base_sptr"); // height image
273 output_types.emplace_back("vil_image_view_base_sptr"); // ground roi
274 output_types.emplace_back("vpgl_camera_double_sptr"); // lvcs
275 ok = pro.set_output_types(output_types);
276 if (!ok) return ok;
277
278 return true;
279 }
280