00001
00002
00046 #include "ros/ros.h"
00047
00048 #include <iostream>
00049 #include <iomanip>
00050 #include <vector>
00051 #include <string>
00052 #include <sstream>
00053
00054 #include <opencv/cv.h>
00055 #include <opencv/highgui.h>
00056
00057 #include "../MetaFile.h"
00058
00059 #include "DUtils.h"
00060 #include "DUtilsCV.h"
00061 #include "DVision.h"
00062
00063 typedef DVision::PMVS::PLYFile PLYFile;
00064 typedef DVision::PMVS::PLYFile::PLYPoint PLYPoint;
00065 typedef DVision::Bundle::CameraFile::Camera Camera;
00066
00067 using namespace std;
00068
00069
00070
00082 void createPLYpoints(const cv::Mat &img, float width, float height,
00083 const DVision::SurfSet &surfset, std::vector<PLYPoint> &plypoints);
00084
00094 void createCamera(const cv::Mat &im, float width, float height,
00095 Camera &camera);
00096
00106 void saveFace(const std::string &model_dir, int face_idx, const cv::Mat &img,
00107 const DVision::SurfSet &surfs, const std::vector<PLYPoint> &plypoints,
00108 const Camera &camera);
00109
00110
00111
00112 static const int DEFAULT_HESSIAN_THRESHOLD = 400;
00113
00114
00115
00116 int main(int argc, char **argv)
00117 {
00118 ros::init(argc, argv, "createPlanarModel");
00119
00120 if(argc < 6)
00121 {
00122 ROS_WARN("Usage: createPlanarModel <training image> <object name> "
00123 "<width (m)> <height (m)> <output model dir> [surf threshold]");
00124 return 1;
00125 }
00126
00127 cout << argc << endl;
00128
00129 string image_file = argv[1];
00130 string object_name = argv[2];
00131 float width = atof(argv[3]);
00132 float height = atof(argv[4]);
00133 string out_model_dir = argv[5];
00134 int hessian = (argc >= 7 ? atoi(argv[6]) : DEFAULT_HESSIAN_THRESHOLD);
00135
00136 ROS_INFO("Reading image...");
00137 cv::Mat img_color = cv::imread(image_file, 1);
00138 cv::Mat bw_img = cv::imread(image_file, 0);
00139
00140 ROS_INFO("Extracting SURFs (hessian threshold: %d)...", hessian);
00141 DVision::SurfSet surfset;
00142 surfset.Extract(bw_img, hessian);
00143 ROS_INFO(" %d points obtained", surfset.size());
00144
00145 ROS_INFO("Computing 3D coords and camera info...");
00146 vector<PLYPoint> plypoints;
00147 createPLYpoints(img_color, width, height, surfset, plypoints);
00148
00149 Camera camera;
00150 createCamera(img_color, width, height, camera);
00151
00152 ROS_INFO("Creating meta data...");
00153 MetaFile::MetaData meta;
00154 meta.Name = object_name;
00155 meta.NFaces = 1;
00156 meta.Type = "planar";
00157 meta.Dimensions.Planar.Width = width;
00158 meta.Dimensions.Planar.Height = height;
00159 meta.Dimensions.Planar.Depth = 0;
00160 meta.Dimensions.Planar.Faces.resize(1);
00161 meta.Dimensions.Planar.Faces[0].Width = width;
00162 meta.Dimensions.Planar.Faces[0].Height = height;
00163 meta.Dimensions.Planar.Faces[0].oTf = cv::Mat::eye(4,4,CV_64F);
00164
00165
00166
00167
00168
00169 ROS_INFO("Saving...");
00170
00171 if(!DUtils::FileFunctions::DirExists(out_model_dir.c_str()))
00172 DUtils::FileFunctions::MkDir(out_model_dir.c_str());
00173
00174 saveFace(out_model_dir, 0, img_color, surfset, plypoints, camera);
00175 MetaFile::saveFile(out_model_dir + "/meta.xml", meta);
00176
00177 ROS_INFO("Done");
00178
00179 return 0;
00180 }
00181
00182
00183
00184 void createPLYpoints(const cv::Mat &img, float width, float height,
00185 const DVision::SurfSet &surfset, std::vector<PLYPoint> &plypoints)
00186 {
00187 plypoints.resize(0);
00188 if(surfset.keys.empty()) return;
00189
00190 double mperpixel;
00191 if(width > 0.f && height > 0.f)
00192 mperpixel = ((width / (float)img.cols) + (height / (float)img.rows)) / 2.f;
00193 else if(width > 0.f) mperpixel = width / (float)img.cols;
00194 else mperpixel = height / (float)img.rows;
00195
00196 const float cx = (float)img.cols / 2.f;
00197 const float cy = (float)img.rows / 2.f;
00198
00199 vector<cv::Mat> bgr_planes;
00200 cv::split(img, bgr_planes);
00201
00202 plypoints.reserve(surfset.size());
00203
00204 vector<cv::KeyPoint>::const_iterator kit;
00205 for(kit = surfset.keys.begin(); kit != surfset.keys.end(); ++kit)
00206 {
00207 plypoints.push_back(PLYPoint());
00208 PLYPoint &p = plypoints.back();
00209
00210 p.x = (kit->pt.x - cx) * mperpixel;
00211 p.y = (kit->pt.y - cy) * mperpixel;
00212 p.z = 0.;
00213
00214 p.nx = 0.;
00215 p.ny = 0.;
00216 p.nz = 1.;
00217
00218 p.r = bgr_planes[2].at<uchar>(kit->pt.y, kit->pt.x);
00219 p.g = bgr_planes[1].at<uchar>(kit->pt.y, kit->pt.x);
00220 p.b = bgr_planes[0].at<uchar>(kit->pt.y, kit->pt.x);
00221 }
00222
00223 }
00224
00225
00226
00227 void createCamera(const cv::Mat &im, float width, float height,
00228 Camera &camera)
00229 {
00230 cv::Mat cTo = DUtilsCV::Transformations::transl(0, 0, 1);
00231
00232 float fx = im.cols / width;
00233 float fy = im.rows / height;
00234 camera.f = (fx + fy) / 2;
00235 camera.k1 = camera.k2 = 0;
00236
00237 camera.t = cv::Mat::zeros(3, 1, CV_64F);
00238 DUtilsCV::Transformations::decomposeRt(cTo, camera.R, camera.t);
00239 }
00240
00241
00242
00243 void saveFace(const std::string &model_dir, int face_idx, const cv::Mat &img,
00244 const DVision::SurfSet &surfs, const std::vector<PLYPoint> &plypoints,
00245 const Camera &camera)
00246 {
00247 stringstream prefix;
00248 prefix << model_dir << "/face_" << setw(3) << setfill('0') << face_idx;
00249
00250 cv::imwrite(prefix.str() + ".png", img);
00251 surfs.Save(prefix.str() + ".key.gz");
00252 PLYFile::saveFile(prefix.str() + ".ply", plypoints);
00253 camera.save(prefix.str() + ".txt",
00254 "Fake camera. Assumes cx=w/2, cy=h/2, Z_object=1");
00255 }
00256
00257
00258