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
00058
00059 using std::cout;
00060 using std::endl;
00061
00062
00063
00064
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
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
00192
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
00253 }
00254
00255 return true;
00256 }
00257
00258
00259
00260
00261
00262
00263
00264 class FeatureTracker {
00265 public:
00266
00267
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
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
00289 int num_tracking_steps;
00290
00291
00292 static unsigned char colormap[];
00293
00294 static const float residual_error_comp = 0.1;
00295
00296 FeatureTracker() :
00297 num_tracking_steps(0) {
00298 }
00299
00300
00301
00302
00303 std::vector<cv::Point2f> findCorners(cv::Mat& first_image,
00304 cv::Mat* mask = 0);
00305
00306
00307
00308
00309
00310 bool tracking_step(cv::Mat& new_image);
00311
00312
00313
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
00331
00332 bool generateHypothesis(const Eigen::VectorXf& mask,
00333 std::vector<Eigen::Matrix3f>& RTs);
00334
00335
00336
00337
00338
00339 bool evluateTrajectories();
00340
00341
00342
00343
00344
00345
00346 float sampleHypothesisSet(std::vector<int>& feature_assocoation);
00347
00348 };
00349
00350
00351
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
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
00369 corner_trajectories.push_back(corners);
00370 last_image = first_image_grey;
00371
00372
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
00390
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
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
00409 corner_trajectories.push_back(new_corners);
00410 for (unsigned int i = 0; i < good_corners.rows(); i++) {
00411
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
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
00427
00428
00429
00430 }
00431
00432 return true;
00433
00434 }
00435
00436
00437
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
00444 residuals = Eigen::VectorXf(corner_trajectories_t.size());
00445
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
00450
00451
00452 assert(RTs.size() == current_trajectory.size() - 1);
00453 float residual = 0;
00454
00455
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
00463
00464 residual += std::max(0.0f, res.squaredNorm() - residual_error_comp);
00465
00466 }
00467
00468 residuals[t] = residual;
00469 }
00470 return true;
00471 }
00472
00473
00474 bool FeatureTracker::filterTrajectories3d() {
00475
00476 std::vector<std::vector<cv::Point2f> > corner_trajectories_filtered;
00477
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
00484 int num_good_features = good_corners.sum();
00485
00486
00487 for (unsigned int j = 0; j < corner_trajectories.size(); j++) {
00488 std::vector<cv::Point2f> features_filtered;
00489
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
00496 }
00497 }
00498 corner_trajectories_filtered.push_back(features_filtered);
00499
00500
00501 }
00502
00503
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
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526 }
00527 corner_trajectories_filtered_and_transposed.push_back(features_trans);
00528
00529
00530 }
00531
00532 printf("corner_trajectories_filtered size %d \n",
00533 corner_trajectories_filtered.size());
00534
00535
00536
00537
00538
00539
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
00564
00565 bool FeatureTracker::selectRandomFeatures(std::vector<int>& features_idx,
00566 const Eigen::VectorXf& mask) {
00567
00568 float variance = 200.0f * 200.0f;
00569
00570
00571
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
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
00589
00590 int idx1 = rand() % num_non_masked_elements;
00591 Eigen::VectorXf prob_dist(num_non_masked_elements);
00592
00593 cv::Point2f current_point =
00594 corner_trajectories_filtered_and_transposed[map_array[idx1]].back();
00595
00596 for (int i = 0; i < num_non_masked_elements; i++) {
00597
00598
00599 if (i == idx1) {
00600 prob_dist[i] = 0.0;
00601 continue;
00602 }
00603
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
00612 prob_dist[i] = exp(-0.5 * dist_sqr_n);
00613
00614 }
00615
00616
00617 cout << "prob_dist\n" << prob_dist << endl;
00618 float normalizer = prob_dist.sum();
00619
00620
00621 if (normalizer < 0.0000000001) {
00622 return false;
00623 }
00624
00625
00626 prob_dist = prob_dist / normalizer;
00627 cout << "prob_dist_n\n" << prob_dist << endl;
00628
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
00643
00644 bool FeatureTracker::generateHypothesis(const Eigen::VectorXf& mask,
00645 std::vector<Eigen::Matrix3f>& RTs) {
00646
00647
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
00658 RTs.reserve(num_tracking_steps);
00659 printf("num_tracking_steps %d\n", num_tracking_steps);
00660
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
00666
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
00679
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
00686 RTs.push_back(RT);
00687 }
00688 cout << "last hyp tf \n" << RTs.back() << endl;
00689 return true;
00690
00691 }
00692
00693
00694
00695
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
00706 for (int i = 0; i < num_samples; i++) {
00707 std::vector<int> feature_assocoation;
00708
00709
00710
00711 scores[i] = sampleHypothesisSet(feature_assocoation);
00712
00713
00714 feature_assocoations.push_back(feature_assocoation);
00715
00716
00717
00718
00719 }
00720
00721
00722
00723
00724 int best_hypthesis_set_idx;
00725 scores.minCoeff(&best_hypthesis_set_idx);
00726
00727
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
00735
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
00745
00746 }
00747 }
00748
00749 return true;
00750
00751 }
00752
00753
00754
00755
00756
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
00767 std::vector<std::vector<Eigen::Matrix3f> > hypothesis;
00768
00769
00770
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
00778 Eigen::VectorXf mask = Eigen::VectorXf::Ones(
00779 corner_trajectories_filtered_and_transposed.size());
00780 bool points_left;
00781 int i = 1;
00782
00783
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
00790 calcResiduals(last_hypothesis,
00791 corner_trajectories_filtered_and_transposed, residuals);
00792
00793
00794 residualMatrix.col(i - 1) = residuals;
00795
00796
00797
00798
00799
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
00810 mask = mask_array.min(mask_array_bin);
00811
00812
00813
00814 std::vector<Eigen::Matrix3f> new_hypothesis;
00815
00816
00817
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
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
00835 residualMatrix.col(residualMatrix.cols() - 1) = residuals;
00836 } else {
00837
00838
00839
00840 Eigen::MatrixXf residualMatrix2 = residualMatrix.block(0, 0,
00841 residualMatrix.rows(), actual_num_hypothesis);
00842 residualMatrix = residualMatrix2;
00843
00844 }
00845
00846 cout << "residuals_mat \n" << residualMatrix << endl;
00847
00848
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
00857
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
00872 if (mask[i] > 0.0f) {
00873 num_outliers++;
00874 best_feature_h_idx[i] = -1;
00875 continue;
00876 }
00877
00878
00879
00880 best_feature_h_idx[i] = idx;
00881
00882 feature_per_hyp_count[idx]++;
00883
00884
00885 summed_residuals_per_h[idx] += residualMatrix(i, idx);
00886
00887
00888
00889
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
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 {
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
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
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212
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
01231
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
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
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
01306
01307
01308
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
01315
01316
01317
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
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
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396 ft.findCorners(img);
01397
01398
01399 cv::imshow("tracker", ft.vis_image);
01400 cv::waitKey();
01401
01402 int c;
01403 for (;;) {
01404
01405
01406
01407 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(
01408 new pcl::PointCloud<pcl::PointXYZ>);
01409
01410
01411
01412
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
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