$search
00001 00034 #define NO_ROS 0 00035 00036 #include "cv.h" 00037 #include "highgui.h" 00038 #include <stdio.h> 00039 #include <ctype.h> 00040 #include <Eigen/Eigen> 00041 #include <assert.h> 00042 #include <iostream> 00043 #include <set> 00044 #include <opencv2/core/eigen.hpp> 00045 #include <cmath> 00046 #include <ros/ros.h> 00047 #include "sensor_msgs/Image.h" 00048 #include "sensor_msgs/PointCloud2.h" 00049 #include "cv_bridge/CvBridge.h" 00050 #include "camera_self_filter/mask.h" 00051 #include "Timer.h" 00052 #include <pcl/point_cloud.h> 00053 #include <pcl/point_types.h> 00054 #include <pcl/ros/conversions.h> 00055 #include <pcl/filters/voxel_grid.h> 00056 #include <math.h> 00057 //#include <boost/math/distributions/beta.hpp> 00058 00059 using std::cout; 00060 using std::endl; 00061 00062 /*** 00063 * Retrives rotation and translation minimzing the error of the rigid transformation between two sets of points. 00064 * Modified opencv version. 00065 */ 00066 static void icvGetRTMatrix(const CvPoint2D32f* a, const CvPoint2D32f* b, 00067 int count, CvMat* M) { 00068 00069 double sa[16], sb[4], m[4], *om = M->data.db; 00070 CvMat A = cvMat(4, 4, CV_64F, sa), B = cvMat(4, 1, CV_64F, sb); 00071 CvMat MM = cvMat(4, 1, CV_64F, m); 00072 00073 int i; 00074 00075 memset(sa, 0, sizeof(sa)); 00076 memset(sb, 0, sizeof(sb)); 00077 00078 for (i = 0; i < count; i++) { 00079 sa[0] += a[i].x * a[i].x + a[i].y * a[i].y; 00080 sa[1] += 0; 00081 sa[2] += a[i].x; 00082 sa[3] += a[i].y; 00083 00084 sa[4] += 0; 00085 sa[5] += a[i].x * a[i].x + a[i].y * a[i].y; 00086 sa[6] += -a[i].y; 00087 sa[7] += a[i].x; 00088 00089 sa[8] += a[i].x; 00090 sa[9] += -a[i].y; 00091 sa[10] += 1; 00092 sa[11] += 0; 00093 00094 sa[12] += a[i].y; 00095 sa[13] += a[i].x; 00096 sa[14] += 0; 00097 sa[15] += 1; 00098 00099 sb[0] += a[i].x * b[i].x + a[i].y * b[i].y; 00100 sb[1] += a[i].x * b[i].y - a[i].y * b[i].x; 00101 sb[2] += b[i].x; 00102 sb[3] += b[i].y; 00103 } 00104 00105 cvSolve(&A, &B, &MM, CV_SVD); 00106 00107 om[0] = om[4] = m[0]; 00108 om[1] = -m[1]; 00109 om[3] = m[1]; 00110 om[2] = m[2]; 00111 om[5] = m[3]; 00112 00113 } 00114 00115 /*** 00116 * Retrives rotation and translation minimzing the error of the rigid transformation between two sets of points. 00117 * 00118 */ 00119 cv::Mat cvEstimateRigidTransformFrom2(const cv::Mat& A, const cv::Mat& B) { 00120 cv::Mat M = cv::Mat(2, 3, CV_64F); 00121 00122 CvPoint2D32f* a = (CvPoint2D32f*) A.data; 00123 CvPoint2D32f* b = (CvPoint2D32f*) B.data; 00124 CvMat matM = M; 00125 icvGetRTMatrix(a, b, 2, &matM); 00126 return M; 00127 } 00128 00129 pcl::PointXYZ NanCheckContours(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, int i, 00130 int j, int iterations) { 00131 int k = 0; 00132 pcl::PointXYZ pointRet; 00133 iterations = iterations * 2; 00134 for (; k <= iterations; k++) { 00135 if (!isnan(cloud->points[i + 640 * (j + 1 * k)].x)) { 00136 pointRet = cloud->points[i + 640 * (j + 1 * k)]; 00137 break; 00138 } else if (!isnan(cloud->points[i + 1 * k + 640 * j].x)) { 00139 pointRet = cloud->points[i + 1 * k + 640 * j]; 00140 break; 00141 } else if (!isnan( 00142 cloud->points[i + iterations - 1 * k + 640 * (j + iterations)].x)) { 00143 pointRet = cloud->points[i + iterations - 1 * k 00144 + 640 * (j + iterations)]; 00145 break; 00146 00147 } else if (!isnan( 00148 cloud->points[i + iterations + 640 * (j + iterations - 1 * k)].x)) { 00149 pointRet = cloud->points[i + iterations 00150 + 640 * (j + iterations - 1 * k)]; 00151 break; 00152 } 00153 00154 } 00155 return pointRet; 00156 } 00157 00158 bool dealingWithNanPointsOpt(pcl::PointCloud<pcl::PointXYZ>::Ptr& cloud, int i, 00159 int j, int iterations) { 00160 00161 int k = 1; 00162 if ((isnan(cloud->points[i + 640 * j].x))) { 00163 00164 for (; k <= iterations; k++) { 00165 00166 if (((i - 1 * k) < 0) && ((j - 1 * k < 0)) 00167 && ((i + 1 * k) > cloud->height) 00168 && ((j + 1 * k) > cloud->width)) 00169 break; 00170 if (NanCheckContours(cloud, i - 1 * k, j - 1 * k, k).x != 0) 00171 cloud->points[i + 640 * j] = NanCheckContours(cloud, i - 1 * k, 00172 j - 1 * k, k); 00173 00174 if (!isnan(cloud->points[i + 640 * j].x)) { 00175 break; 00176 00177 } 00178 } 00179 if ((isnan(cloud->points[i + 640 * j].x))) { 00180 printf( 00181 "it couldn't find not nan point that is near to cloud->at(i,j) in ", 00182 k, " iterations"); 00183 return false; 00184 } 00185 00186 } 00187 00188 return true; 00189 } 00190 00191 //function to deal with Nan points from the kinect camera. It is looking for the neighbor 00192 //that is not a Nan and assigns it to the given point. 00193 // 00194 00195 bool getPclPoint(int x, int y) 00196 { 00197 00198 00199 00200 } 00201 00202 00203 bool dealingWithNanPoints( 00204 pcl::PointCloud<pcl::PointXYZ>::Ptr& cloud, int i, int j, 00205 int iterations) { 00206 int k = 1; 00207 if ((isnan(cloud->at(i, j).x))) { 00208 00209 for (; k <= iterations; k++) { 00210 00211 if (((i - 1 * k) < 0) && ((j - 1 * k < 0)) 00212 && ((i + 1 * k) > cloud->height) 00213 && ((j + 1 * k) > cloud->width)) 00214 break; 00215 00216 if ((!isnan(cloud->points[i - 1 * k + 640*j].x)) 00217 ) { 00218 cloud->points[i+640* j] = cloud->points[i - 1 * k + 640*j]; 00219 } else if ((!isnan(cloud->points[i + 1 * k+ 640* j].x)) 00220 ) { 00221 cloud->points[i+640* j] = cloud->points[i + 1 * k+ 640* j]; 00222 } else if ((!isnan(cloud->points[i+640*( j + 1 * k)].x)) 00223 ) { 00224 cloud->points[i+640* j] = cloud->points[i+640*( j + 1 * k)]; 00225 } else if ((!isnan(cloud->points[i+640*( j - 1 * k)].x)) 00226 ) { 00227 cloud->points[i+640* j] = cloud->points[i+640*( j - 1 * k)]; 00228 } else if ((!isnan(cloud->points[i + 1 * k+640*( j + 1 * k)].x)) 00229 ) { 00230 cloud->points[i+640* j] = cloud->points[i + 1 * k+640*( j + 1 * k)]; 00231 } else if ((!isnan(cloud->points[i - 1 * k+640*( j + 1 * k)].x)) 00232 ) { 00233 cloud->points[i+640* j] = cloud->points[i - 1 * k+640*( j + 1 * k)]; 00234 } else if ((!isnan(cloud->points[i + 1 * k+640*( j - 1 * k)].x)) 00235 ) { 00236 cloud->points[i+640* j] = cloud->points[i + 1 * k+640*( j - 1 * k)]; 00237 } else if ((!isnan(cloud->points[i - 1 * k+640*( j - 1 * k)].x)) 00238 ) { 00239 cloud->points[i+640* j] = cloud->points[i - 1 * k+640*( j - 1 * k)]; 00240 } 00241 00242 } 00243 00244 if ((isnan(cloud->at(i, j).x)) ) 00245 {printf( 00246 "it couldn't find not nan point that is near to cloud->at(i,j) in ", 00247 k, " iterations"); 00248 00249 return false; 00250 } 00251 } else { 00252 //do nothing 00253 } 00254 00255 return true; 00256 } 00257 00258 /*** 00259 * Extracts corner features from an image and tracks them in subsequent images. 00260 * The features are clustered such that each feature cluster consists of features with similar trajectories, i.e. 00261 * which can be explained by the same sequence of rigid transforms. 00262 */ 00263 00264 class FeatureTracker { 00265 public: 00266 00267 //Parameters for feature detection 00268 static const int MAX_CORNERS = 500; 00269 static const double quality = 0.01; 00270 static const double min_distance = 10; 00271 static const int WIN_SIZE = 10; 00272 00273 //number of points used to calculate RT 00274 const static int num_points_to_select = 3; 00275 00276 cv::Mat vis_image; 00277 cv::Mat vis_image_orig; 00278 cv::Mat last_image; 00279 00280 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud; 00281 00282 std::vector<std::vector<cv::Point2f> > corner_trajectories; 00283 std::vector<std::vector<cv::Point2f> > corner_trajectories_filtered_and_transposed; 00284 std::vector<std::vector<pcl::PointXYZ> > corner_trajectories_filtered_and_transposed_3d; 00285 00286 Eigen::VectorXi good_corners; 00287 00288 //executed tracking steps 00289 int num_tracking_steps; 00290 00291 // colormap for disparities, RGB order 00292 static unsigned char colormap[]; 00293 00294 static const float residual_error_comp = 0.1; // 0.1; //deduct half a pixel from the residuals at each timestep 00295 00296 FeatureTracker() : 00297 num_tracking_steps(0) { 00298 } 00299 00300 /*** 00301 * Find corners using OpnecCV's goodFeaturesToTrack. 00302 */ 00303 std::vector<cv::Point2f> findCorners(cv::Mat& first_image, 00304 cv::Mat* mask = 0); 00305 00306 /*** 00307 * Execute one tracking step: 00308 * Calculate sparse optical flow from all corners in old image 00309 */ 00310 bool tracking_step(cv::Mat& new_image); 00311 00312 /*** 00313 * Caluculates residuals as squared reprojection error between rigid transform trajectory predicted by hypothesis and actual trajectory. 00314 */ 00315 bool calcResiduals(const std::vector<Eigen::Matrix3f>& RTs, 00316 const std::vector<std::vector<cv::Point2f> >& corner_trajectories_t, 00317 Eigen::VectorXf& residuals); 00318 00319 bool filterTrajectories3d(); 00320 00324 int draw(Eigen::VectorXf& prob_dist); 00325 00326 bool selectRandomFeatures(std::vector<int>& features_idx, 00327 const Eigen::VectorXf& mask); 00328 00329 /*** 00330 * generates a rotation translation trajectory hypothesis for all features marked in mask in a RANSAC like fashion. 00331 */ 00332 bool generateHypothesis(const Eigen::VectorXf& mask, 00333 std::vector<Eigen::Matrix3f>& RTs); 00334 00335 /*** Top-level function: 00336 * Samples a number of hypothesis sets, i.e. samples sets of possible feature clusters. 00337 * Hypothesis sets are scored and best one is returned/visualized. 00338 */ 00339 bool evluateTrajectories(); 00340 00341 /*** 00342 * Sample recursively possible feature-to-cluster associations (hypotheses) by generating a hypothesis 00343 * on the input features set, calculate outliers and generate another hypothesis, ... and so on until a 00344 * hypothesis exists for each feature. 00345 */ 00346 float sampleHypothesisSet(std::vector<int>& feature_assocoation); 00347 00348 }; 00349 00350 /*** 00351 * Find corners using OpnecCV's goodFeaturesToTrack. 00352 */ 00353 std::vector<cv::Point2f> FeatureTracker::findCorners(cv::Mat& first_image, 00354 cv::Mat* mask) { 00355 num_tracking_steps = 0; 00356 cv::Mat first_image_grey; 00357 cv::cvtColor(first_image, first_image_grey, CV_BGR2GRAY); 00358 std::vector<cv::Point2f> corners; 00359 cv::goodFeaturesToTrack(first_image_grey, corners, MAX_CORNERS, quality, 00360 min_distance); 00361 00362 // vector to store the good corners 00363 good_corners = Eigen::VectorXi::Ones(corners.size()); 00364 cv::cornerSubPix(first_image_grey, corners, cv::Size(WIN_SIZE, WIN_SIZE), 00365 cv::Size(-1, -1), 00366 cv::TermCriteria(CV_TERMCRIT_ITER | CV_TERMCRIT_EPS, 20, 0.03)); 00367 00368 // vector of vectors of corners; put the very first ones into the structure 00369 corner_trajectories.push_back(corners); 00370 last_image = first_image_grey; 00371 00372 //visulization 00373 vis_image_orig = first_image; 00374 vis_image = vis_image_orig.clone(); 00375 for (unsigned int i = 0; i < corners.size(); i++) { 00376 int color_idx = ((num_tracking_steps * 11) % 256) * 3; 00377 cv::circle( 00378 vis_image, 00379 corners[i], 00380 3, 00381 cv::Scalar(colormap[color_idx], colormap[color_idx + 1], 00382 colormap[color_idx + 2], 0), -1); 00383 } 00384 00385 return corners; 00386 } 00387 00388 /*** 00389 * Execute one tracking step: 00390 * Calculate sparse optical flow from all corners in old image 00391 */ 00392 bool FeatureTracker::tracking_step(cv::Mat& new_image) { 00393 num_tracking_steps++; 00394 cv::Mat new_image_grey; 00395 cv::cvtColor(new_image, new_image_grey, CV_BGR2GRAY); 00396 std::vector<cv::Point2f> new_corners; 00397 std::vector<unsigned char> status; 00398 std::vector<float> error; 00399 00400 // calculate optical flow between the last image and the current one 00401 cv::calcOpticalFlowPyrLK(last_image, new_image_grey, 00402 corner_trajectories.back(), new_corners, status, error, 00403 cv::Size(WIN_SIZE, WIN_SIZE), 3, 00404 cv::TermCriteria(CV_TERMCRIT_ITER | CV_TERMCRIT_EPS, 20, 0.03)); 00405 00406 last_image = new_image_grey; 00407 00408 // add corners which we recognized to the structure we have 00409 corner_trajectories.push_back(new_corners); 00410 for (unsigned int i = 0; i < good_corners.rows(); i++) { 00411 // put 1 in these elements of the vector where we found corresponding corner, 0 otherwise 00412 good_corners[i] = good_corners[i] & status[i]; 00413 } 00414 printf("num good corners %d %d new _corner_size %d \n", good_corners.sum(), 00415 good_corners.rows(), corner_trajectories.back().size()); 00416 00417 //visulization 00418 vis_image_orig = new_image; 00419 vis_image = vis_image_orig.clone(); 00420 std::vector<cv::Point2f>& old_corners = 00421 corner_trajectories[num_tracking_steps - 1]; 00422 for (unsigned int i = 0; i < new_corners.size(); i++) { 00423 if (!good_corners[i]) 00424 continue; 00425 int color_idx = ((num_tracking_steps * 11) % 256) * 3; 00426 // cv::circle(vis_image, new_corners[i], 3, cv::Scalar(colormap[color_idx], colormap[color_idx +1], colormap[color_idx +2],0), -1); 00427 // cv::line(vis_image,new_corners[i], old_corners[i], cv::Scalar(0,0,255,0), 1); 00428 // cv::line(vis_image,new_corners[i], old_corners[i], cv::Scalar(colormap[color_idx], colormap[color_idx +1], colormap[color_idx +2]), 1); 00429 00430 } 00431 00432 return true; 00433 00434 } 00435 00436 /*** 00437 * Caluculates residuals as squared reprojection error between rigid transform trajectory predicted by hypothesis and actual trajectory. 00438 */ 00439 bool FeatureTracker::calcResiduals(const std::vector<Eigen::Matrix3f>& RTs, 00440 const std::vector<std::vector<cv::Point2f> >& corner_trajectories_t, 00441 Eigen::VectorXf& residuals) { 00442 00443 // the same size as the number of the corners we have 00444 residuals = Eigen::VectorXf(corner_trajectories_t.size()); 00445 // for each feature 00446 for (unsigned int t = 0; t < corner_trajectories_t.size(); t++) { 00447 const std::vector<cv::Point2f>& current_trajectory = 00448 corner_trajectories_t[t]; 00449 // printf("RTs.size() %d current_trajectory.size() %d\n",RTs.size(),current_trajectory.size()); 00450 00451 // it should be as big as number of steps -1 00452 assert(RTs.size() == current_trajectory.size() - 1); 00453 float residual = 0; 00454 00455 // for one feature calculate the difference for every two time steps and calculate the error with the hypothesis 00456 for (unsigned int c = 0; c < current_trajectory.size() - 1; c++) { 00457 Eigen::Vector3f old_corner(current_trajectory[c].x, 00458 current_trajectory[c].y, 1.0); 00459 Eigen::Vector3f new_corner(current_trajectory[c + 1].x, 00460 current_trajectory[c + 1].y, 1.0); 00461 Eigen::Vector3f res = new_corner - (RTs[c] * old_corner); 00462 // cout<<"res for traj "<<t<<": vec\n"<<res<<endl; 00463 // sum up all the errors for one feature 00464 residual += std::max(0.0f, res.squaredNorm() - residual_error_comp); 00465 00466 } 00467 // residuals for all features sum up for all time steps 00468 residuals[t] = residual; 00469 } 00470 return true; 00471 } 00472 00473 // function to filter and transpose corner_trajectories vector 00474 bool FeatureTracker::filterTrajectories3d() { 00475 00476 std::vector<std::vector<cv::Point2f> > corner_trajectories_filtered; 00477 //std::vector<std::vector<pcl::PointXYZ> > corner_trajectories_filtered3d; 00478 00479 printf( 00480 "corner_trajectories size %d corner_trajectories[0].size() %d good _corners %d\n", 00481 corner_trajectories.size(), corner_trajectories[0].size(), 00482 good_corners.rows()); 00483 // how many good features do we have 00484 int num_good_features = good_corners.sum(); 00485 00486 //filter out bad features 00487 for (unsigned int j = 0; j < corner_trajectories.size(); j++) { 00488 std::vector<cv::Point2f> features_filtered; 00489 //std::vector<pcl::PointXYZ> features_filtered3d; 00490 00491 features_filtered.reserve(num_good_features); 00492 for (unsigned int i = 0; i < good_corners.rows(); i++) { 00493 if (good_corners[i]) { 00494 features_filtered.push_back(corner_trajectories[j][i]); 00495 //features_filtered3d.push_back(cloud->at(corner_trajectories[j][i].x,corner_trajectories[j][i].y)); 00496 } 00497 } 00498 corner_trajectories_filtered.push_back(features_filtered); 00499 //corner_trajectories_filtered3d.push_back(features_filtered3d); 00500 00501 } 00502 00503 //transpose, so that we have vector of vectors with good corners in time 00504 corner_trajectories_filtered_and_transposed.clear(); 00505 corner_trajectories_filtered_and_transposed.reserve(good_corners.rows()); 00506 for (unsigned int i = 0; i < good_corners.rows(); i++) { 00507 std::vector<cv::Point2f> features_trans; 00508 00509 std::vector<pcl::PointXYZ> features_trans_3d; 00510 features_trans.reserve(corner_trajectories_filtered.size()); 00511 for (unsigned int j = 0; j < corner_trajectories_filtered.size(); j++) { 00512 features_trans.push_back(corner_trajectories_filtered[j][i]); 00513 // printf("0000000 normal %d \n",corner_trajectories_filtered[j][i].x); 00514 00515 // features_trans_3d.push_back(cloud->at(corner_trajectories_filtered3d[j][i].x,corner_trajectories_filtered3d[j][i].y)); 00516 00517 //features_trans_3d.push_back(cloud->at(corner_trajectories_filtered[j][i].x,corner_trajectories_filtered[j][i].y)); 00518 // printf("0000000 3d %d \n",corner_trajectories_filtered3d[j][i].x); 00519 00520 //for each corner calculate relevant 3d pcl point 00521 00522 // printf("features trans %d \n",features_trans.size()); 00523 // printf("features trans 3d %d \n",features_trans_3d.size()); 00524 00525 00526 } 00527 corner_trajectories_filtered_and_transposed.push_back(features_trans); 00528 //corner_trajectories_filtered_and_transposed_3d.push_back(features_trans_3d); 00529 00530 } 00531 //how many good corners we have 00532 printf("corner_trajectories_filtered size %d \n", 00533 corner_trajectories_filtered.size()); 00534 00535 //printf("corner_trajectories_filtered3d size %d \n", 00536 //corner_trajectories_filtered3d.size()); 00537 // printf ("normal******************** %d \n",corner_trajectories_filtered_and_transposed.at(1).back().y); 00538 // printf ("3d******************** %d \n",corner_trajectories_filtered_and_transposed_3d.at(1).back().y); 00539 // printf ("3d******************** %d \n",corner_trajectories_filtered_and_transposed_3d.at(1).back().z); 00540 00541 00542 return true; 00543 00544 } 00545 00549 int FeatureTracker::draw(Eigen::VectorXf& prob_dist) { 00550 float pos = (float) rand() / RAND_MAX; 00551 int idx = 0; 00552 float accumulator = 0.0f; 00553 for (;;) { 00554 accumulator += prob_dist[idx]; 00555 if (accumulator > pos) 00556 break; 00557 idx++; 00558 } 00559 return idx; 00560 00561 } 00562 00563 //it gets two numbers of random features from the outliers 00564 //TODO: This needs to be done more efficiently... 00565 bool FeatureTracker::selectRandomFeatures(std::vector<int>& features_idx, 00566 const Eigen::VectorXf& mask) { 00567 00568 float variance = 200.0f * 200.0f; //pixel size of objects 00569 //select random but depending on gaussian distance 00570 //first create map 00571 // how many elements we should consider - outliers from previous hypothesis 00572 int num_non_masked_elements = mask.sum(); 00573 if (num_non_masked_elements < 3) { 00574 printf("num non masked elements %d\n", num_non_masked_elements); 00575 return false; 00576 } 00577 int* map_array = new int[num_non_masked_elements]; 00578 int counter = 0; 00579 // we store all the outliers numbers in the map_array array 00580 for (int i = 0; i < mask.rows(); i++) { 00581 if (mask[i] > 0.0) { 00582 map_array[counter] = i; 00583 counter++; 00584 } 00585 00586 } 00587 00588 //we assume 3 points are selected... 00589 // we get random corner number 00590 int idx1 = rand() % num_non_masked_elements; 00591 Eigen::VectorXf prob_dist(num_non_masked_elements); 00592 // we get last position for the picked corner 00593 cv::Point2f current_point = 00594 corner_trajectories_filtered_and_transposed[map_array[idx1]].back(); 00595 // for all outliers 00596 for (int i = 0; i < num_non_masked_elements; i++) { 00597 00598 // if we have bad luck and pick the same outlier- continue 00599 if (i == idx1) { 00600 prob_dist[i] = 0.0; 00601 continue; 00602 } 00603 // if not we take every outlier and calculate the distance to the random taken other one 00604 cv::Point2f other = 00605 corner_trajectories_filtered_and_transposed[map_array[i]].back(); 00606 float dist_sqr = pow((other.x - current_point.x), 2) 00607 + pow((other.y - current_point.y), 2); 00608 printf("dist sqr %d %f\n", i, dist_sqr); 00609 float dist_sqr_n = dist_sqr / variance; 00610 00611 // not sure - we sum up the distances from all outlier to our randomly picked point 00612 prob_dist[i] = exp(-0.5 * dist_sqr_n); 00613 00614 } 00615 00616 // summed distances from every outlier to our one 00617 cout << "prob_dist\n" << prob_dist << endl; 00618 float normalizer = prob_dist.sum(); 00619 00620 //take care of the case where numbers are really low 00621 if (normalizer < 0.0000000001) { 00622 return false; 00623 } 00624 00625 // we have normalized prob_dist vector which consists of distance from every outlier to our one 00626 prob_dist = prob_dist / normalizer; 00627 cout << "prob_dist_n\n" << prob_dist << endl; 00628 // now we have to draw randomly another outlier from the outliers that are good- not so close to our one 00629 int idx2 = draw(prob_dist); 00630 00631 assert(map_array[idx1] < mask.rows()); 00632 assert(map_array[idx2] < mask.rows()); 00633 features_idx.clear(); 00634 features_idx.push_back(map_array[idx1]); 00635 features_idx.push_back(map_array[idx2]); 00636 00637 delete[] map_array; 00638 return true; 00639 } 00640 00641 /*** 00642 * generates a rotation translation trajectory hypothesis for all features marked in mask in a RANSAC like fashion. 00643 */ 00644 bool FeatureTracker::generateHypothesis(const Eigen::VectorXf& mask, 00645 std::vector<Eigen::Matrix3f>& RTs) { 00646 00647 // how many outliers we have 00648 int num_elements = mask.sum(); 00649 printf("in generateHypothesis num_elements %d\n", num_elements); 00650 if (num_elements < 3) 00651 return false; 00652 00653 std::vector<int> features_idx; 00654 if (!selectRandomFeatures(features_idx, mask)) 00655 return false; 00656 00657 // reserve place for every time step 00658 RTs.reserve(num_tracking_steps); 00659 printf("num_tracking_steps %d\n", num_tracking_steps); 00660 // for every time step do 00661 for (int i = 1; i < num_tracking_steps + 1; i++) { 00662 printf("step gen %d \n", i); 00663 cv::Mat new_points(features_idx.size(), 1, CV_32FC2); 00664 cv::Mat old_points(features_idx.size(), 1, CV_32FC2); 00665 // for our (2) randomly picked features store them in two matrices 00666 // in every matrix there are both cordinates of i.e. 2 randomly picked features 00667 for (int j = 0; j < features_idx.size(); j++) { 00668 cv::Point2f& new_point = 00669 corner_trajectories_filtered_and_transposed[features_idx[j]][i]; 00670 new_points.ptr<float>()[j * 2] = new_point.x; 00671 new_points.ptr<float>()[j * 2 + 1] = new_point.y; 00672 cv::Point2f& old_point = 00673 corner_trajectories_filtered_and_transposed[features_idx[j]][i 00674 - 1]; 00675 old_points.ptr<float>()[j * 2] = old_point.x; 00676 old_points.ptr<float>()[j * 2 + 1] = old_point.y; 00677 } 00678 // cv::Mat RT_cv = cv::estimateRigidTransform(old_points, new_points, false); 00679 // estimate rigid transform between two sets of points during one time step 00680 cv::Mat RT_cv = cvEstimateRigidTransformFrom2(old_points, new_points); 00681 Eigen::Matrix3f RT = Eigen::Matrix3f::Identity(); 00682 Eigen::Matrix<float, 2, 3> rt_temp; 00683 cv::cv2eigen(RT_cv, rt_temp); 00684 RT.block<2, 3>(0, 0) = rt_temp; 00685 // write the transform in the vector 00686 RTs.push_back(RT); 00687 } 00688 cout << "last hyp tf \n" << RTs.back() << endl; 00689 return true; 00690 00691 } 00692 00693 /*** Top-level function: 00694 * Samples a number of hypothesis sets, i.e. samples sets of possible feature clusters. 00695 * Hypothesis sets are scored and best one is returned/visualized. 00696 */ 00697 bool FeatureTracker::evluateTrajectories() { 00698 00699 int num_samples = 15; 00700 int num_hypotheses = 10; 00701 filterTrajectories3d(); 00702 Eigen::VectorXf scores = Eigen::VectorXf::Zero(num_samples); 00703 std::vector<std::vector<int> > feature_assocoations; 00704 00705 //create hypothesis set samples 00706 for (int i = 0; i < num_samples; i++) { 00707 std::vector<int> feature_assocoation; 00708 // try 15 sets of hypotheses and look fo the best one by looking up the scores vector 00709 // feature_assocoation - vector which describes for which features(place in the vector) there is the best hypothesis (value) 00710 00711 scores[i] = sampleHypothesisSet(feature_assocoation); 00712 00713 // store all the vectors of feature_assocoation for every sample 00714 feature_assocoations.push_back(feature_assocoation); 00715 // if(feature_assocoation.size() != 1){ 00716 // cv::imshow("tracker_temp", vis_image); 00717 // cvWaitKey(1500); 00718 // } 00719 } 00720 00721 00722 //find best hypothesis... 00723 // actually find the best set of hypotheses 00724 int best_hypthesis_set_idx; 00725 scores.minCoeff(&best_hypthesis_set_idx); 00726 00727 //..which becomes final feature-to-cluster association. 00728 std::vector<int>& final_feature_association = 00729 feature_assocoations[best_hypthesis_set_idx]; 00730 00731 vis_image = vis_image_orig.clone(); 00732 for (int i = 0; i < corner_trajectories_filtered_and_transposed.size(); 00733 i++) { 00734 // idx being the number of hypothesis 00735 // if that many features have the same hypothesis then they will have the same color 00736 int idx = final_feature_association[i]; 00737 if (idx >= 0) { 00738 cv::circle( 00739 vis_image, 00740 corner_trajectories_filtered_and_transposed[i].back(), 00741 9, 00742 cv::Scalar(colormap[3 * idx], colormap[3 * idx + 1], 00743 colormap[3 * idx + 2], 0), 5); 00744 // }else{ 00745 // cv::circle(vis_image, corner_trajectories_filtered_and_transposed[i].back(), 9, cv::Scalar( 0 , 0, 0, 0), 5, 1); 00746 } 00747 } 00748 00749 return true; 00750 00751 } 00752 00753 /*** 00754 * Sample recursively possible feature-to-cluster associations (hypotheses) by generating a hypothesis 00755 * on the input features set, calculate outliers and generate another hypothesis, ... and so on until a 00756 * hypothesis exists for each feature. 00757 */ 00758 float FeatureTracker::sampleHypothesisSet( 00759 std::vector<int>& feature_assocoation) { 00760 int num_hypotheses = 10; 00761 float mask_threshold = 80; 00762 00763 Eigen::MatrixXf residualMatrix( 00764 corner_trajectories_filtered_and_transposed.size(), num_hypotheses); 00765 00766 // each hypothesis consists of the corners transformations 00767 std::vector<std::vector<Eigen::Matrix3f> > hypothesis; 00768 00769 //create identity Matrix as first hypothesos 00770 // we build hypothesis for one feature in num_tracking_steps time steps 00771 std::vector<Eigen::Matrix3f> RTs_I; 00772 RTs_I.resize(num_tracking_steps, Eigen::Matrix3f::Identity()); 00773 printf("num_tracking_steps %d RTs_I.size() %d \n", num_tracking_steps, 00774 RTs_I.size()); 00775 hypothesis.push_back(RTs_I); 00776 00777 // vector with size of all the good corners 00778 Eigen::VectorXf mask = Eigen::VectorXf::Ones( 00779 corner_trajectories_filtered_and_transposed.size()); 00780 bool points_left; 00781 int i = 1; 00782 00783 // for all hypotheses - max 10 00784 for (; i < num_hypotheses; i++) { 00785 Eigen::VectorXf residuals; 00786 std::vector<Eigen::Matrix3f>& last_hypothesis = hypothesis[i - 1]; 00787 printf("last_hypothesis size %d\n", last_hypothesis.size()); 00788 00789 //calculate the residuals incurred by current hypothesis (i.e. error between features' actual RT and the hypothetical RT). 00790 calcResiduals(last_hypothesis, 00791 corner_trajectories_filtered_and_transposed, residuals); 00792 00793 //store residuals for one hypothesis 00794 residualMatrix.col(i - 1) = residuals; 00795 00796 // cout<<"residuals\n"<<residuals<<endl; 00797 // cout<<"residuals_mat \n"<<residualMatrix<<endl; 00798 00799 //find inliers and mark them in binary mask - 0 for an inlier 00800 Eigen::VectorXf mask_bin = 00801 (residuals.array() - mask_threshold).matrix(); 00802 for (int i = 0; i < mask_bin.rows(); i++) { 00803 mask_bin[i] = (mask_bin[i] > 0.0f) ? 1.0f : 0.0f; 00804 } 00805 00806 Eigen::ArrayXf mask_array = mask.array(); 00807 Eigen::ArrayXf mask_array_bin = mask_bin.array(); 00808 00809 // in mask we store for every ith corner whether it is an inlier- 0 or outlier - 1 00810 mask = mask_array.min(mask_array_bin); 00811 00812 // mask = mask.array().min(mask_bin.array()); 00813 00814 std::vector<Eigen::Matrix3f> new_hypothesis; 00815 00816 //for the outliers, generate a new hypothesis 00817 // it generates hypothesis just for one set of points 00818 points_left = generateHypothesis(mask, new_hypothesis); 00819 if (!points_left) 00820 break; 00821 printf("generated new hyp of size %d\n", new_hypothesis.size()); 00822 hypothesis.push_back(new_hypothesis); 00823 00824 } 00825 //calc last residuals if all hypothesis had to be used 00826 int& actual_num_hypothesis = i; 00827 printf("actual_num_hypothesis %d num_hypotheses %d\n", 00828 actual_num_hypothesis, num_hypotheses); 00829 if (actual_num_hypothesis == num_hypotheses) { 00830 Eigen::VectorXf residuals; 00831 printf("hypothesis.back() size %d\n", hypothesis.back().size()); 00832 calcResiduals(hypothesis.back(), 00833 corner_trajectories_filtered_and_transposed, residuals); 00834 // cout<<"last residuals\n"<<residuals; 00835 residualMatrix.col(residualMatrix.cols() - 1) = residuals; 00836 } else { 00837 // get just these residuals that were calculated 00838 // to remind - residualMatrix consists of hypothesis and residuals for each of them 00839 // cout<<"residuals_mat \n"<<residualMatrix<<endl; 00840 Eigen::MatrixXf residualMatrix2 = residualMatrix.block(0, 0, 00841 residualMatrix.rows(), actual_num_hypothesis); 00842 residualMatrix = residualMatrix2; 00843 // cout<<"residuals_mat \n"<<residualMatrix<<endl; 00844 } 00845 00846 cout << "residuals_mat \n" << residualMatrix << endl; 00847 00848 // sum of all residuals for every hypothesis 00849 Eigen::VectorXf summed_residuals = residualMatrix.colwise().sum(); 00850 00851 cout << "summed_residuals \n" << summed_residuals << endl; 00852 00853 Eigen::VectorXf summed_residuals_per_h = Eigen::VectorXf::Zero( 00854 residualMatrix.cols()); 00855 00856 // until here we have many hypotheses and every one of them describe just a group o features 00857 //Finally run the process again and assign each feature to its best possible RT hypothesis (or mark it as complete outlier). 00858 std::vector<int> best_feature_h_idx; 00859 best_feature_h_idx.resize( 00860 corner_trajectories_filtered_and_transposed.size(), 0); 00861 Eigen::VectorXf feature_per_hyp_count = Eigen::VectorXf::Ones( 00862 residualMatrix.cols()); 00863 feature_per_hyp_count *= 0.0000001f; 00864 int num_outliers = 0; 00865 for (int i = 0; i < corner_trajectories_filtered_and_transposed.size(); 00866 i++) { 00867 int idx; 00868 residualMatrix.row(i).minCoeff(&idx); 00869 float residual_value = residualMatrix(i, idx); 00870 00871 //check if feature was an outlier 00872 if (mask[i] > 0.0f) { 00873 num_outliers++; 00874 best_feature_h_idx[i] = -1; 00875 continue; 00876 } 00877 00878 // idx - number of hypothesis, i - number of feature 00879 // for ith feature the best deal hypothesis number idx 00880 best_feature_h_idx[i] = idx; 00881 // how many features deals this hypothesis with 00882 feature_per_hyp_count[idx]++; 00883 00884 // general result of clustering, summed up all of the features with respecting hypothesis for them 00885 summed_residuals_per_h[idx] += residualMatrix(i, idx); 00886 // if (idx >= 0 && feature_per_hyp_count[idx] > 2.1){ 00887 // cv::circle(vis_image, corner_trajectories_filtered_and_transposed[i].back(), 9, cv::Scalar( colormap[3*idx], colormap[3*idx+1], colormap[3*idx+2],0), 5); 00888 // }else{ 00889 // cv::circle(vis_image, corner_trajectories_filtered_and_transposed[i].back(), 9, cv::Scalar( 0 , 0, 0, 0), 5, 1); 00890 // } 00891 // 00892 // 00897 } 00898 00899 vis_image = vis_image_orig.clone(); 00900 for (int i = 0; i < corner_trajectories_filtered_and_transposed.size(); 00901 i++) { 00902 int idx = best_feature_h_idx[i]; 00903 // if the number of hypothesis is correct and hypothesis deals with more than 5 features then 00904 if (idx >= 0 && feature_per_hyp_count[idx] > 5.1) { 00905 cv::circle( 00906 vis_image, 00907 corner_trajectories_filtered_and_transposed[i].back(), 00908 9, 00909 cv::Scalar(colormap[3 * idx], colormap[3 * idx + 1], 00910 colormap[3 * idx + 2], 0), 5); 00911 } else { //stupid feature 00912 best_feature_h_idx[i] = -1; 00913 } 00914 } 00915 00916 cout << "num feature_per_hyp_count \n" << feature_per_hyp_count << endl; 00917 summed_residuals.array() /= feature_per_hyp_count.array(); 00918 00919 cout << "summed_residuals \n" << summed_residuals << endl; 00920 00921 cout << "summed_residuals_per_h \n" << summed_residuals_per_h << endl; 00922 00923 summed_residuals_per_h.array() /= feature_per_hyp_count.array(); 00924 cout << "summed_residuals_per_h \n" << summed_residuals_per_h << endl; 00925 00926 cout << "total average residual error " << summed_residuals_per_h.sum() 00927 << endl; 00928 00929 // vector which describes for which features there is the best hypothesis 00930 feature_assocoation = best_feature_h_idx; 00931 float outlier_penalty = num_outliers * 100.0; 00932 printf("outlier num %d penalty %f\n", num_outliers, outlier_penalty); 00933 return summed_residuals_per_h.sum(); 00934 00935 } 00936 00937 unsigned char FeatureTracker::colormap[36] = { 255, 0, 0, 0, 255, 0, 0, 0, 255, 00938 255, 255, 0, 255, 0, 255, 0, 255, 255, 127, 0, 0, 0, 127, 0, 0, 0, 127, 00939 127, 127, 0, 127, 0, 127, 0, 127, 127, }; 00940 00941 //unsigned char FeatureTracker::colormap[768] = 00942 // { 150, 150, 150, 00943 // 107, 0, 12, 00944 // 106, 0, 18, 00945 // 105, 0, 24, 00946 // 103, 0, 30, 00947 // 102, 0, 36, 00948 // 101, 0, 42, 00949 // 99, 0, 48, 00950 // 98, 0, 54, 00951 // 97, 0, 60, 00952 // 96, 0, 66, 00953 // 94, 0, 72, 00954 // 93, 0, 78, 00955 // 92, 0, 84, 00956 // 91, 0, 90, 00957 // 89, 0, 96, 00958 // 88, 0, 102, 00959 // 87, 0, 108, 00960 // 85, 0, 114, 00961 // 84, 0, 120, 00962 // 83, 0, 126, 00963 // 82, 0, 131, 00964 // 80, 0, 137, 00965 // 79, 0, 143, 00966 // 78, 0, 149, 00967 // 77, 0, 155, 00968 // 75, 0, 161, 00969 // 74, 0, 167, 00970 // 73, 0, 173, 00971 // 71, 0, 179, 00972 // 70, 0, 185, 00973 // 69, 0, 191, 00974 // 68, 0, 197, 00975 // 66, 0, 203, 00976 // 65, 0, 209, 00977 // 64, 0, 215, 00978 // 62, 0, 221, 00979 // 61, 0, 227, 00980 // 60, 0, 233, 00981 // 59, 0, 239, 00982 // 57, 0, 245, 00983 // 56, 0, 251, 00984 // 55, 0, 255, 00985 // 54, 0, 255, 00986 // 52, 0, 255, 00987 // 51, 0, 255, 00988 // 50, 0, 255, 00989 // 48, 0, 255, 00990 // 47, 0, 255, 00991 // 46, 0, 255, 00992 // 45, 0, 255, 00993 // 43, 0, 255, 00994 // 42, 0, 255, 00995 // 41, 0, 255, 00996 // 40, 0, 255, 00997 // 38, 0, 255, 00998 // 37, 0, 255, 00999 // 36, 0, 255, 01000 // 34, 0, 255, 01001 // 33, 0, 255, 01002 // 32, 0, 255, 01003 // 31, 0, 255, 01004 // 29, 0, 255, 01005 // 28, 0, 255, 01006 // 27, 0, 255, 01007 // 26, 0, 255, 01008 // 24, 0, 255, 01009 // 23, 0, 255, 01010 // 22, 0, 255, 01011 // 20, 0, 255, 01012 // 19, 0, 255, 01013 // 18, 0, 255, 01014 // 17, 0, 255, 01015 // 15, 0, 255, 01016 // 14, 0, 255, 01017 // 13, 0, 255, 01018 // 11, 0, 255, 01019 // 10, 0, 255, 01020 // 9, 0, 255, 01021 // 8, 0, 255, 01022 // 6, 0, 255, 01023 // 5, 0, 255, 01024 // 4, 0, 255, 01025 // 3, 0, 255, 01026 // 1, 0, 255, 01027 // 0, 4, 255, 01028 // 0, 10, 255, 01029 // 0, 16, 255, 01030 // 0, 22, 255, 01031 // 0, 28, 255, 01032 // 0, 34, 255, 01033 // 0, 40, 255, 01034 // 0, 46, 255, 01035 // 0, 52, 255, 01036 // 0, 58, 255, 01037 // 0, 64, 255, 01038 // 0, 70, 255, 01039 // 0, 76, 255, 01040 // 0, 82, 255, 01041 // 0, 88, 255, 01042 // 0, 94, 255, 01043 // 0, 100, 255, 01044 // 0, 106, 255, 01045 // 0, 112, 255, 01046 // 0, 118, 255, 01047 // 0, 124, 255, 01048 // 0, 129, 255, 01049 // 0, 135, 255, 01050 // 0, 141, 255, 01051 // 0, 147, 255, 01052 // 0, 153, 255, 01053 // 0, 159, 255, 01054 // 0, 165, 255, 01055 // 0, 171, 255, 01056 // 0, 177, 255, 01057 // 0, 183, 255, 01058 // 0, 189, 255, 01059 // 0, 195, 255, 01060 // 0, 201, 255, 01061 // 0, 207, 255, 01062 // 0, 213, 255, 01063 // 0, 219, 255, 01064 // 0, 225, 255, 01065 // 0, 231, 255, 01066 // 0, 237, 255, 01067 // 0, 243, 255, 01068 // 0, 249, 255, 01069 // 0, 255, 255, 01070 // 0, 255, 249, 01071 // 0, 255, 243, 01072 // 0, 255, 237, 01073 // 0, 255, 231, 01074 // 0, 255, 225, 01075 // 0, 255, 219, 01076 // 0, 255, 213, 01077 // 0, 255, 207, 01078 // 0, 255, 201, 01079 // 0, 255, 195, 01080 // 0, 255, 189, 01081 // 0, 255, 183, 01082 // 0, 255, 177, 01083 // 0, 255, 171, 01084 // 0, 255, 165, 01085 // 0, 255, 159, 01086 // 0, 255, 153, 01087 // 0, 255, 147, 01088 // 0, 255, 141, 01089 // 0, 255, 135, 01090 // 0, 255, 129, 01091 // 0, 255, 124, 01092 // 0, 255, 118, 01093 // 0, 255, 112, 01094 // 0, 255, 106, 01095 // 0, 255, 100, 01096 // 0, 255, 94, 01097 // 0, 255, 88, 01098 // 0, 255, 82, 01099 // 0, 255, 76, 01100 // 0, 255, 70, 01101 // 0, 255, 64, 01102 // 0, 255, 58, 01103 // 0, 255, 52, 01104 // 0, 255, 46, 01105 // 0, 255, 40, 01106 // 0, 255, 34, 01107 // 0, 255, 28, 01108 // 0, 255, 22, 01109 // 0, 255, 16, 01110 // 0, 255, 10, 01111 // 0, 255, 4, 01112 // 2, 255, 0, 01113 // 8, 255, 0, 01114 // 14, 255, 0, 01115 // 20, 255, 0, 01116 // 26, 255, 0, 01117 // 32, 255, 0, 01118 // 38, 255, 0, 01119 // 44, 255, 0, 01120 // 50, 255, 0, 01121 // 56, 255, 0, 01122 // 62, 255, 0, 01123 // 68, 255, 0, 01124 // 74, 255, 0, 01125 // 80, 255, 0, 01126 // 86, 255, 0, 01127 // 92, 255, 0, 01128 // 98, 255, 0, 01129 // 104, 255, 0, 01130 // 110, 255, 0, 01131 // 116, 255, 0, 01132 // 122, 255, 0, 01133 // 128, 255, 0, 01134 // 133, 255, 0, 01135 // 139, 255, 0, 01136 // 145, 255, 0, 01137 // 151, 255, 0, 01138 // 157, 255, 0, 01139 // 163, 255, 0, 01140 // 169, 255, 0, 01141 // 175, 255, 0, 01142 // 181, 255, 0, 01143 // 187, 255, 0, 01144 // 193, 255, 0, 01145 // 199, 255, 0, 01146 // 205, 255, 0, 01147 // 211, 255, 0, 01148 // 217, 255, 0, 01149 // 223, 255, 0, 01150 // 229, 255, 0, 01151 // 235, 255, 0, 01152 // 241, 255, 0, 01153 // 247, 255, 0, 01154 // 253, 255, 0, 01155 // 255, 251, 0, 01156 // 255, 245, 0, 01157 // 255, 239, 0, 01158 // 255, 233, 0, 01159 // 255, 227, 0, 01160 // 255, 221, 0, 01161 // 255, 215, 0, 01162 // 255, 209, 0, 01163 // 255, 203, 0, 01164 // 255, 197, 0, 01165 // 255, 191, 0, 01166 // 255, 185, 0, 01167 // 255, 179, 0, 01168 // 255, 173, 0, 01169 // 255, 167, 0, 01170 // 255, 161, 0, 01171 // 255, 155, 0, 01172 // 255, 149, 0, 01173 // 255, 143, 0, 01174 // 255, 137, 0, 01175 // 255, 131, 0, 01176 // 255, 126, 0, 01177 // 255, 120, 0, 01178 // 255, 114, 0, 01179 // 255, 108, 0, 01180 // 255, 102, 0, 01181 // 255, 96, 0, 01182 // 255, 90, 0, 01183 // 255, 84, 0, 01184 // 255, 78, 0, 01185 // 255, 72, 0, 01186 // 255, 66, 0, 01187 // 255, 60, 0, 01188 // 255, 54, 0, 01189 // 255, 48, 0, 01190 // 255, 42, 0, 01191 // 255, 36, 0, 01192 // 255, 30, 0, 01193 // 255, 24, 0, 01194 // 255, 18, 0, 01195 // 255, 12, 0, 01196 // 255, 6, 0, 01197 // 255, 0, 0, 01198 // }; 01199 01200 // 01201 // IplImage *image = 0, *grey = 0, *prev_grey = 0, *pyramid = 0, *prev_pyramid = 0, *swap_temp; 01202 // 01203 // int win_size = 10; 01204 // const int MAX_COUNT = 500; 01205 // CvPoint2D32f* points[2] = {0,0}, *swap_points; 01206 // char* status = 0; 01207 // int count1 = 0; 01208 // int need_to_init = 0; 01209 // int night_mode = 0; 01210 // int flags = 0; 01211 // int add_remove_pt = 0; 01212 // CvPoint pt; 01213 // 01214 01215 #if NO_ROS 01216 int main( int argc, char** argv ) std::vector<cv::Point2f> features_trans; 01217 01218 { 01219 if (argc == 1) 01220 { 01221 std::cerr << "Usage: " << argv[0] << " <images>" << std::endl; 01222 exit(0); 01223 } 01224 cv::namedWindow("tracker", 0); 01225 cv::namedWindow("tracker_temp", 0); 01226 01227 int num_images = argc - 1; 01228 int num_images_loaded = 0; 01229 IplImage** all_images = new IplImage*[num_images]; 01230 // for (int i = 0 ; i < num_images; i++){ 01231 // all_images[i] = cvLoadImage(argv[i+1]); 01232 // } 01233 01234 FeatureTracker ft; 01235 all_images[0] = cvLoadImage(argv[1]); 01236 num_images_loaded++; 01237 cv::Mat img(all_images[0]); 01238 ft.findCorners(img); 01239 01240 cv::imshow("tracker", ft.vis_image); 01241 cv::waitKey(); 01242 01243 int c; 01244 for (int i = 1; i < num_images; i++) { 01245 all_images[i] = cvLoadImage(argv[i+1]); 01246 num_images_loaded++; 01247 printf("loading image %s\n", argv[i+1]); 01248 cv::Mat img(all_images[i]); 01249 ft.tracking_step(img); 01250 01251 if( (i-1) % 5 == 0) { 01252 Timer t; 01253 ft.evluateTrajectories(); 01254 printf("took %f secs\n", t.stop()); 01255 cv::imshow("tracker", ft.vis_image); 01256 c = cvWaitKey(); 01257 if( (char)c == 27 ) 01258 break; 01259 } 01260 01261 } 01262 01263 for (int i = 0; i < num_images_loaded; i++) { 01264 cvReleaseImage(&all_images[i]); 01265 } 01266 delete [] all_images; 01267 01268 } 01269 01270 #else 01271 01272 /*** 01273 * Main method to be run with PR2 robot 01274 */ 01275 01276 int main(int argc, char** argv) { 01277 01278 ros::init(argc, argv, "image_tracker"); 01279 ros::NodeHandle nh; 01280 sensor_msgs::CvBridge _bridge; 01281 cv::namedWindow("tracker", 0); 01282 cv::namedWindow("tracker_temp", 0); 01283 01284 std::string input_image_topic = 01285 argc == 2 ? argv[1] : "/camera/rgb/image_color"; 01286 01287 FeatureTracker ft; 01288 01289 //mycode 01290 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud( 01291 new pcl::PointCloud<pcl::PointXYZ>); 01292 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered( 01293 new pcl::PointCloud<pcl::PointXYZ>); 01294 01295 sensor_msgs::PointCloud2ConstPtr pclmasg_ptr; 01296 01297 pclmasg_ptr = ros::topic::waitForMessage<sensor_msgs::PointCloud2>( 01298 "/camera/rgb/points"); 01299 01300 pcl::fromROSMsg(*pclmasg_ptr, *cloud); 01301 01302 ft.cloud=cloud; 01303 01304 01305 // pcl::VoxelGrid<pcl::PointXYZ> sor; 01306 // sor.setInputCloud (cloud); 01307 // sor.setLeafSize (0.01f, 0.01f, 0.01f); 01308 // sor.filter (*cloud_filtered); 01309 01310 std::cout << " height of the cloud: " << cloud->height << std::endl; 01311 std::cout << " width of the cloud: " << cloud->width << std::endl; 01312 std::cout << "size " << cloud->points.size() << std::endl; 01313 01314 // for (size_t i = 0; i < cloud->points.size (); ++i) 01315 // std::cout << " " << cloud->points[i].x 01316 // << " " << cloud->points[i].y 01317 // << " " << cloud->points[i].z << std::endl; 01318 01319 01320 01321 for (int i = 26; i < 31; i++) { 01322 01323 for (int j = 26; j < 31; j++) { 01324 std::cout << " " << cloud->at(i, j) << " "; 01325 01326 } 01327 std::cout << std::endl; 01328 01329 } 01330 01331 std::cout << std::endl; 01332 std::cout << std::endl; 01333 01334 std::cout << "before: " << cloud->at(26, 26) << " " << std::endl; 01335 std::cout << "Filtering" << std::endl; 01336 01337 bool done; 01338 01339 done=dealingWithNanPointsOpt(cloud, 26, 26, 4); 01340 std::cout << std::endl; 01341 01342 std::cout <<"Is it done? " << done <<std::endl; 01343 std::cout << std::endl; 01344 01345 01346 01347 std::cout << std::endl; 01348 std::cout << "after: " << cloud->at(26, 26)<< " " << std::endl; 01349 01350 std::cout << std::endl; 01351 std::cout << std::endl; 01352 01353 for (int i = 26; i < 31; i++) { 01354 01355 for (int j = 26; j < 31; j++) { 01356 std::cout << " " << cloud->at(i, j) << " "; 01357 01358 } 01359 std::cout << std::endl; 01360 01361 } 01362 01363 std::cout << std::endl; 01364 std::cout << std::endl; 01365 01366 //end 01367 01368 sensor_msgs::ImageConstPtr imgmasg_ptr = ros::topic::waitForMessage< 01369 sensor_msgs::Image>(input_image_topic); 01370 IplImage* ipl_img = _bridge.imgMsgToCv(imgmasg_ptr, "passthrough"); 01371 cv::Mat img(ipl_img); 01372 01373 // ros::ServiceClient svc = nh.serviceClient<camera_self_filter::mask>("self_mask"); 01374 // camera_self_filter::mask servicecall; 01375 // servicecall.request.header.frame_id = "high_def_optical_frame"; 01376 // servicecall.request.header.stamp = ros::Time::now(); 01377 // svc.call(servicecall); 01378 // sensor_msgs::ImageConstPtr maskptr = boost::make_shared<sensor_msgs::Image>(boost::ref(servicecall.response.mask_image)); 01379 // 01380 // IplImage* ipl_mask = _bridge.imgMsgToCv(maskptr, "passthrough"); 01381 // cvDilate(ipl_mask, ipl_mask, 0, 3); 01382 // cvNot(ipl_mask,ipl_mask); 01383 // cv::Mat mask(ipl_mask); 01384 // 01385 // cv::Mat ROI_mat = cv::Mat::zeros(img.rows, img.cols, CV_8U); 01386 // cv::rectangle(ROI_mat, cv::Point(0,0), cv::Point(img.cols-1, 1400),cv::Scalar(255,255,255,0), -1); 01387 // 01388 // cv::resize(mask, mask, cv::Size(img.cols, img.rows), 0, 0, CV_INTER_NN); 01389 // 01390 // cv::bitwise_and(ROI_mat,mask, mask); 01391 // 01392 // 01393 // cv::imshow("tracker", mask); 01394 // cv::waitKey(); 01395 01396 ft.findCorners(img); 01397 // ft.findCorners(img, &mask); 01398 01399 cv::imshow("tracker", ft.vis_image); 01400 cv::waitKey(); 01401 01402 int c; 01403 for (;;) { 01404 01405 //mycode 01406 01407 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud( 01408 new pcl::PointCloud<pcl::PointXYZ>); 01409 01410 01411 01412 // pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered (new pcl::PointCloud<pcl::PointXYZ>); 01413 01414 sensor_msgs::PointCloud2ConstPtr pclmasg_ptr; 01415 01416 pclmasg_ptr = ros::topic::waitForMessage<sensor_msgs::PointCloud2>( 01417 "/camera/rgb/points"); 01418 01419 pcl::fromROSMsg(*pclmasg_ptr, *cloud); 01420 01421 ft.cloud=cloud; 01422 01423 01424 //end 01425 01426 sensor_msgs::ImageConstPtr imgmasg_ptr = ros::topic::waitForMessage< 01427 sensor_msgs::Image>(input_image_topic); 01428 IplImage* ipl_img = _bridge.imgMsgToCv(imgmasg_ptr, "passthrough"); 01429 cv::Mat img(ipl_img); 01430 Timer t; 01431 ft.tracking_step(img); 01432 ft.evluateTrajectories(); 01433 printf("took %f secs\n", t.stop()); 01434 std::cout << " height of the cloud: " << cloud->height << std::endl; 01435 std::cout << " width of the cloud: " << cloud->width << std::endl; 01436 std::cout << "size " << cloud->points.size() << std::endl; 01437 std::cout << "point " << cloud->at(0, 0) << std::endl; 01438 cv::imshow("tracker", ft.vis_image); 01439 c = cvWaitKey(); 01440 if ((char) c == 27) 01441 break; 01442 01443 } 01444 01445 return 0; 01446 01447 } 01448 01449 #endif 01450