stereo_frame.cpp
Go to the documentation of this file.
00001 #include "stereo_frame.hpp"
00002 
00003 #include <stdio.h>
00004 
00005 #include <iostream>
00006 
00007 #include "visual_odometry.hpp"
00008 #include "internal_utils.hpp"
00009 #include "gauss_pyramid.h"
00010 #include "fast.hpp"
00011 #include "tictoc.hpp"
00012 #include "rectification.hpp"
00013 #include "normalize_image.hpp"
00014 
00015 #ifndef ALIGNMENT
00016 #define ALIGNMENT 16
00017 #endif
00018 
00019 namespace fovis
00020 {
00021 
00022 static bool
00023 keypoint_rect_v_comparator(const KeypointData& a,
00024                            const KeypointData& b) {
00025     return (a.rect_base_uv(1) < b.rect_base_uv(1));
00026 }
00027 
00028 StereoFrame::StereoFrame(int width, int height,
00029                 const Rectification* rectify_map,
00030                 const VisualOdometryOptions& options) :
00031     _base_width(width), _base_height(height)
00032 {
00033 
00034   const VisualOdometryOptions& defaults(VisualOdometry::getDefaultOptions());
00035 
00036   _num_levels = optionsGetIntOrFromDefault(options, "max-pyramid-level", defaults);
00037   _feature_window_size = optionsGetIntOrFromDefault(options, "feature-window-size", defaults);
00038   _use_bucketing = optionsGetBoolOrFromDefault(options, "use-bucketing", defaults);
00039   _use_image_normalization = optionsGetBoolOrFromDefault(options, "use-image-normalization", defaults);
00040 
00041   int bucket_width = optionsGetIntOrFromDefault(options, "bucket-width", defaults);
00042   int bucket_height = optionsGetIntOrFromDefault(options, "bucket-height", defaults);
00043   int max_keypoints_per_bucket = optionsGetIntOrFromDefault(options, "max-keypoints-per-bucket", defaults);
00044 
00045   _rectify_map = rectify_map->makeCopy();
00046   initialize(bucket_width, bucket_height, max_keypoints_per_bucket);
00047 }
00048 
00049 StereoFrame::~StereoFrame() {
00050   for (std::vector<PyramidLevel *>::iterator itr = _levels.begin();
00051        itr != _levels.end();
00052        ++itr) {
00053     delete *itr;
00054   }
00055   delete _rectify_map;
00056 }
00057 
00058 void
00059 StereoFrame::initialize(int bucket_width,
00060                         int bucket_height,
00061                         int max_keypoints_per_bucket) {
00062   for(int level_num=0; level_num < _num_levels; ++level_num) {
00063 
00064     int level_width = _base_width >> level_num;
00065     int level_height = _base_height >> level_num;
00066 
00067     GridKeyPointFilter grid_filter(level_width, level_height, bucket_width,
00068                                    bucket_height, max_keypoints_per_bucket);
00069 
00070     PyramidLevel* level = new PyramidLevel(level_width, level_height,
00071                                            level_num, _feature_window_size,
00072                                            grid_filter);
00073     _levels.push_back(level);
00074   }
00075 }
00076 
00077 void
00078 StereoFrame::prepareFrame(const uint8_t* raw_gray, int fast_threshold) {
00079 
00080   // copy raw image to first pyramid level
00081   assert(_num_levels);
00082   PyramidLevel* first_level = _levels[0];
00083   int src_stride = _base_width;
00084   for(int row=0; row<_base_height; row++) {
00085     memcpy(first_level->_raw_gray + row * first_level->_raw_gray_stride,
00086         raw_gray + row * src_stride, _base_width);
00087   }
00088 
00089   if (_use_image_normalization) {
00090     normalize_image(first_level->_raw_gray, first_level->_raw_gray_stride,
00091                     _base_width, _base_height);
00092   }
00093 
00094   // compute image pyramid and detect initial features
00095   for(int level_num=0; level_num<_num_levels; ++level_num) {
00096     PyramidLevel* level = _levels[level_num];
00097     if(level_num > 0) {
00098       // resize the image from the previous level
00099       PyramidLevel* prev_level = _levels[level_num-1];
00100       int prev_width = prev_level->getWidth();
00101       int prev_height = prev_level->getHeight();
00102       gauss_pyr_down_8u_C1R(prev_level->_raw_gray, prev_level->_raw_gray_stride,
00103           prev_width, prev_height, level->_raw_gray, level->_raw_gray_stride,
00104           prev_level->_pyrbuf);
00105     }
00106 
00107     level->_initial_keypoints.clear();
00108     FAST(level->_raw_gray, level->_width, level->_height, level->_raw_gray_stride,
00109         &level->_initial_keypoints, fast_threshold, 1);
00110 
00111     // Keep track of this number before filtering out keyoints with the
00112     // grid bucketing, to use it as a signal for FAST threshold adjustment.
00113     level->_num_detected_keypoints = static_cast<int>(level->_initial_keypoints.size());
00114 
00115     if (_use_bucketing) {
00116       tictoc("bucketing");
00117       level->_grid_filter.filter(&level->_initial_keypoints);
00118       tictoc("bucketing");
00119     }
00120 
00121     level->_num_keypoints = 0;
00122 
00123     int num_kp_candidates = level->_initial_keypoints.size();
00124 
00125     // increase buffer size if needed
00126     if(num_kp_candidates > level->_keypoints_capacity) {
00127       level->increase_capacity((int)(num_kp_candidates * 1.2));
00128     }
00129 
00130     int num_features = 0;
00131     for(int kp_ind=0; kp_ind<num_kp_candidates; ++kp_ind) {
00132 
00133       KeyPoint& kp_cand = level->_initial_keypoints[kp_ind];
00134 
00135       if (!level->isLegalKeypointCoordinate(kp_cand.u, kp_cand.v)) {
00136         continue;
00137       }
00138 
00139       // Fill in keypoint data
00140       KeypointData kpdata;
00141       kpdata.kp = kp_cand;
00142       kpdata.base_uv(0) = kp_cand.u * (1 << level_num);
00143       kpdata.base_uv(1) = kp_cand.v * (1 << level_num);
00144       // lookup rectified pixel coordinates
00145       int pixel_index = (int)(kpdata.base_uv(1) * _base_width + kpdata.base_uv(0));
00146       _rectify_map->rectifyLookupByIndex(pixel_index, &kpdata.rect_base_uv);
00147       if(kpdata.rect_base_uv(0) < 0 || kpdata.rect_base_uv(0) >= _base_width ||
00148          kpdata.rect_base_uv(1) < 0 || kpdata.rect_base_uv(1) >= _base_height) {
00149         continue;
00150       }
00151       kpdata.pyramid_level = level_num;
00152       kpdata.has_depth = false;
00153       kpdata.xyzw = Eigen::Vector4d(NAN, NAN, NAN, NAN);
00154       kpdata.keypoint_index = num_features;
00155       kpdata.track_id = -1;
00156 
00157       num_features++;
00158 
00159       level->_keypoints[level->_num_keypoints] = kpdata;
00160       level->_num_keypoints++;
00161     }
00162 
00163     // keep sorted by v-coordinate, helps for filtering by epipolar line
00164     std::sort(&(level->_keypoints[0]),
00165               &(level->_keypoints[level->_num_keypoints]),
00166               keypoint_rect_v_comparator);
00167 
00168     // extract features
00169     level->populateDescriptorsAligned(level->_keypoints, level->_num_keypoints,
00170                                       level->_descriptors);
00171 
00172   }
00173 }
00174 
00175 }


libfovis
Author(s): Albert Huang, Maurice Fallon
autogenerated on Thu Jun 6 2019 20:16:12