contrib/brl/bseg/bmdl/pro/processes/bmdl_lidar_roi_process.cxx
Go to the documentation of this file.
00001 #include <vcl_cstring.h>
00002 
00003 #include <vgl/vgl_box_2d.h>
00004 #include <vgl/vgl_box_3d.h>
00005 #include <vgl/vgl_point_2d.h>
00006 #include <vgl/vgl_point_3d.h>
00007 #include <vsol/vsol_box_2d.h>
00008 
00009 #include <vil/vil_load.h>
00010 #include <vil/vil_image_resource.h>
00011 #include <vil/file_formats/vil_tiff.h>
00012 
00013 #include <bprb/bprb_parameters.h>
00014 #include <bprb/bprb_func_process.h>
00015 
00016 #include <vpgl/vpgl_utm.h>
00017 #include <vpgl/vpgl_lvcs.h>
00018 #include <vpgl/file_formats/vpgl_geo_camera.h>
00019 
00020 #include <brip/brip_roi.h>
00021 #include <brdb/brdb_value.h>
00022 #include <bmdl/bmdl_classify.h>
00023 
00024 template<class T>
00025 vcl_vector<vgl_point_3d<T> > corners_of_box_3d(vgl_box_3d<T> box)
00026 {
00027   vcl_vector<vgl_point_3d<T> > corners;
00028 
00029   corners.push_back(box.min_point());
00030   corners.push_back(vgl_point_3d<T> (box.min_x()+box.width(), box.min_y(), box.min_z()));
00031   corners.push_back(vgl_point_3d<T> (box.min_x()+box.width(), box.min_y()+box.height(), box.min_z()));
00032   corners.push_back(vgl_point_3d<T> (box.min_x(), box.min_y()+box.height(), box.min_z()));
00033   corners.push_back(vgl_point_3d<T> (box.min_x(), box.min_y(), box.max_z()));
00034   corners.push_back(vgl_point_3d<T> (box.min_x()+box.width(), box.min_y(), box.max_z()));
00035   corners.push_back(box.max_point());
00036   corners.push_back(vgl_point_3d<T> (box.min_x(), box.min_y()+box.height(), box.max_z()));
00037   return corners;
00038 }
00039 
00040 bool compute_ground(vil_image_resource_sptr ground,
00041                     vil_image_view_base_sptr first_roi,
00042                     vil_image_view_base_sptr last_roi,
00043                     vil_image_view_base_sptr& ground_roi)
00044 {
00045   if (ground == 0)
00046   {
00047     if ((first_roi->pixel_format() == VIL_PIXEL_FORMAT_FLOAT) &&
00048         (last_roi->pixel_format() == VIL_PIXEL_FORMAT_FLOAT)) {
00049       vil_image_view<float>* ground_view = new vil_image_view<float>();
00050       vil_image_view<float> first_view(first_roi);
00051       vil_image_view<float> last_view(last_roi);
00052       bmdl_classify<float> classifier;
00053       classifier.set_lidar_data(first_view, last_view);
00054       classifier.estimate_bare_earth();
00055       ground_view->deep_copy(classifier.bare_earth());
00056       ground_roi = ground_view;
00057     }
00058     else if ((first_roi->pixel_format() == VIL_PIXEL_FORMAT_DOUBLE) &&
00059              (last_roi->pixel_format() == VIL_PIXEL_FORMAT_DOUBLE)) {
00060       vil_image_view<double>* ground_view = new vil_image_view<double>();
00061       vil_image_view<double> first_view(first_roi);
00062       vil_image_view<double> last_view(last_roi);
00063       bmdl_classify<double> classifier;
00064       classifier.set_lidar_data(first_view, last_view);
00065       classifier.estimate_bare_earth();
00066       ground_view->deep_copy(classifier.bare_earth());
00067       ground_roi = ground_view;
00068     }
00069     else {
00070       vcl_cout << "input images have different bit depths" << vcl_endl;
00071       return false;
00072     }
00073   }
00074   return true;
00075 }
00076 
00077 
00078 bool lidar_roi(unsigned type,  //0 for geo coordinates, 1 for image coord
00079                vil_image_resource_sptr lidar_first,
00080                vil_image_resource_sptr lidar_last,
00081                vil_image_resource_sptr ground,
00082                float min_lat, float min_lon,
00083                float max_lat, float max_lon,
00084                vil_image_view_base_sptr& first_roi,
00085                vil_image_view_base_sptr& last_roi,
00086                vil_image_view_base_sptr& ground_roi,
00087                vpgl_geo_camera*& camera)
00088 {
00089   // the file should be at least a tiff (better, geotiff)
00090   if (vcl_strcmp(lidar_first->file_format(), "tiff") != 0 &&
00091       vcl_strcmp(lidar_last->file_format(),"tiff") != 0) {
00092     vcl_cout << "bmdl_lidar_roi_process::lidar_roi -- The lidar images should be a TIFF!\n";
00093     return false;
00094   }
00095 
00096 #if HAS_GEOTIFF
00097   vil_tiff_image* tiff_first = static_cast<vil_tiff_image*> (lidar_first.ptr());
00098   vil_tiff_image* tiff_last  = static_cast<vil_tiff_image*> (lidar_last.ptr());
00099 
00100   if (vpgl_geo_camera::init_geo_camera(tiff_first, 0, camera))
00101   {
00102     vgl_box_2d<double> roi_box;
00103 
00104     if (type == 0)    // geographic coordinates
00105     {
00106       // backproject the 3D world coordinates on the image
00107       vgl_point_3d<double> min_pos(min_lon, min_lat, 0);
00108       vgl_point_3d<double> max_pos(max_lon, max_lat, 30);
00109       vgl_box_3d<double> world(min_pos, max_pos);
00110       vcl_vector<vgl_point_3d<double> > corners = corners_of_box_3d<double>(world);
00111       for (unsigned i=0; i<corners.size(); i++) {
00112         double x = corners[i].x();
00113         double y = corners[i].y();
00114         double z = corners[i].z();
00115         double lx, ly, lz;
00116         camera->lvcs()->global_to_local(x, y, z,vpgl_lvcs::wgs84, lx, ly, lz);
00117         double u,v;
00118         camera->project(lx,ly,lz,u,v);
00119         vgl_point_2d<double> p(u,v);
00120         roi_box.add(p);
00121       }
00122     }
00123     else if (type == 1) {
00124       roi_box.add(vgl_point_2d<double> (min_lat, min_lon));
00125       roi_box.add(vgl_point_2d<double> (max_lat, max_lon));
00126     }
00127 
00128     brip_roi broi(tiff_first->ni(), tiff_first->nj());
00129     vsol_box_2d_sptr bb = new vsol_box_2d();
00130     bb->add_point(roi_box.min_x(), roi_box.min_y());
00131     bb->add_point(roi_box.max_x(), roi_box.max_y());
00132 
00133     bb = broi.clip_to_image_bounds(bb);
00134     //vcl_cout << "Cut out area------>" << vcl_endl;
00135     //vcl_cout << *bb << vcl_endl;
00136     first_roi = tiff_first->get_copy_view((unsigned int)bb->get_min_x(),
00137                                           (unsigned int)bb->width(),
00138                                           (unsigned int)bb->get_min_y(),
00139                                           (unsigned int)bb->height());
00140 
00141     last_roi = tiff_last->get_copy_view((unsigned int)bb->get_min_x(),
00142                                         (unsigned int)bb->width(),
00143                                         (unsigned int)bb->get_min_y(),
00144                                         (unsigned int)bb->height());
00145 
00146     // if no ground input, create an estimated one
00147     if (ground == 0) {
00148       compute_ground(ground, first_roi, last_roi, ground_roi);
00149     }
00150     else {   // crop the given one
00151       ground_roi = ground->get_copy_view((unsigned int)bb->get_min_x(),
00152                                          (unsigned int)bb->width(),
00153                                          (unsigned int)bb->get_min_y(),
00154                                          (unsigned int)bb->height());
00155     }
00156 
00157     //add the translation to the camera
00158     double ox = bb->get_min_x();
00159     double oy = bb->get_min_y();
00160     double elev = 0;
00161     if (ground_roi->pixel_format() == VIL_PIXEL_FORMAT_FLOAT) {
00162       vil_image_view<float> ground_view(ground_roi);
00163       elev = ground_view(0,0);
00164     }
00165     else if (ground_roi->pixel_format() == VIL_PIXEL_FORMAT_DOUBLE) {
00166       vil_image_view<double> ground_view(ground_roi);
00167       elev = ground_view(0,0);
00168     }
00169     camera->translate(ox, oy, elev);
00170 
00171     if (!first_roi) {
00172       vcl_cout << "bmdl_lidar_roi_process::lidar_init()-- clipping box is out of image boundaries\n";
00173       return false;
00174     }
00175   }
00176   else {
00177     vcl_cout << "bmdl_lidar_roi_process::lidar_init()-- Only ProjectedCSTypeGeoKey=PCS_WGS84_UTM_zoneXX_X is defined rigth now, please define yours!!" << vcl_endl;
00178     return false;
00179   }
00180 
00181   return true;
00182 #else // if !HAS_GEOTIFF
00183   vcl_cout << "bmdl_lidar_roi_process::lidar_init()-- GEOTIFF lib is needed to run bmdl_lidar_roi_process--\n";
00184   return false;
00185 #endif // HAS_GEOTIFF
00186 
00187   return true;
00188 }
00189 
00190 bool bmdl_lidar_roi_process(bprb_func_process& pro)
00191 {
00192   if (pro.n_inputs()< 8) {
00193     vcl_cout << "lidar_roi_process: The input number should be 8" << vcl_endl;
00194     return false;
00195   }
00196 
00197   unsigned int i=0;
00198   vcl_string first = pro.get_input<vcl_string>(i++);
00199   vcl_string last = pro.get_input<vcl_string>(i++);
00200   vcl_string ground = pro.get_input<vcl_string>(i++);
00201   float min_lat = pro.get_input<float>(i++);
00202   float min_lon = pro.get_input<float>(i++);
00203   float max_lat = pro.get_input<float>(i++);
00204   float max_lon = pro.get_input<float>(i++);
00205   unsigned type = pro.get_input<unsigned>(i++);
00206 
00207   // check first return's validity
00208   vil_image_resource_sptr first_ret = vil_load_image_resource(first.c_str());
00209   if (!first_ret) {
00210     vcl_cout << "bmdl_lidar_roi_process -- First return image path is not valid!\n";
00211     return false;
00212   }
00213 
00214   // check last return's validity
00215   vil_image_resource_sptr last_ret = vil_load_image_resource(last.c_str());
00216   if (!last_ret) {
00217     vcl_cout << "bmdl_lidar_roi_process -- Last return image path is not valid!\n";
00218     return false;
00219   }
00220 
00221   // Ground image path can be invalid or empty, in that case an estimated ground will be computed
00222   vil_image_resource_sptr ground_img =0;
00223   if (ground.size() > 0) {
00224     ground_img = vil_load_image_resource(ground.c_str());
00225   }
00226 
00227   vil_image_view_base_sptr first_roi=0, last_roi=0, ground_roi;
00228   vpgl_geo_camera* lidar_cam =0;
00229   if (!lidar_roi(type, first_ret, last_ret, ground_img,
00230     min_lat, min_lon, max_lat, max_lon, first_roi, last_roi, ground_roi, lidar_cam)) {
00231     vcl_cout << "bmdl_lidar_roi_process -- The process has failed!\n";
00232     return false;
00233   }
00234 
00235   unsigned j=0;
00236   // store image output (first return roi)
00237   pro.set_output_val<vil_image_view_base_sptr>(j++, first_roi);
00238 
00239   // store image output (last return roi)
00240   pro.set_output_val<vil_image_view_base_sptr>(j++,last_roi);
00241 
00242   // store image output (ground roi)
00243   pro.set_output_val<vil_image_view_base_sptr>(j++,ground_roi);
00244 
00245   // store the camera (camera of first return is sufficient)
00246   pro.set_output_val<vpgl_camera_double_sptr >(j++, lidar_cam);
00247 
00248   return true;
00249 }
00250 
00251 bool bmdl_lidar_roi_process_cons(bprb_func_process& pro)
00252 {
00253   bool ok=false;
00254   vcl_vector<vcl_string> input_types;
00255   input_types.push_back("vcl_string");
00256   input_types.push_back("vcl_string");
00257   input_types.push_back("vcl_string");
00258   input_types.push_back("float");
00259   input_types.push_back("float");
00260   input_types.push_back("float");
00261   input_types.push_back("float");
00262   input_types.push_back("unsigned");
00263   ok = pro.set_input_types(input_types);
00264   if (!ok) return ok;
00265 
00266   vcl_vector<vcl_string> output_types;
00267   output_types.push_back("vil_image_view_base_sptr"); // label image
00268   output_types.push_back("vil_image_view_base_sptr"); // height image
00269   output_types.push_back("vil_image_view_base_sptr"); // ground roi
00270   output_types.push_back("vpgl_camera_double_sptr");  // lvcs
00271   ok = pro.set_output_types(output_types);
00272   if (!ok) return ok;
00273 
00274   return true;
00275 }