SVO-3-Feature.h–2021.1.16
Feature.h
#ifndef SVO_FEATURE_H_
#define SVO_FEATURE_H_
#include <frame.h>
namespace svo{
struct Feature{
EIGEN_MAKE_ALGINED_OPERATOR_NEW
enum FeatureType{
CORNER,
ENGELET
};
FeatureType type;
Frame* frame;
Vector2d px;
Vector3d f;
int level;
Point* point;
Vector2d grad;
Feature(Frame* _frame,const Vector2d& _px, int _level):
type(CORNER),
frame(_frame),
px(_px),
f(frame -> cam_ -> cam2world(px)),
level(_level),
point(NULL),
grad(1.0,0.0)
{}
Feature(Frame* _frame,const Vector2d& _px, const Vector3d& _f,int _level):
type(CORNER),
frame(_frame),
px(_px),
f(_f),
level(_level),
point(NULL),
grad(1.0,0.0)
{}
Feature(Frame* _frame,Point* _point, const Vector2d& _px, const Vector3d& _f,int _level):
type(CORNER),
frame(_frame),
px(_px),
f(frame -> cam_ -> cam2world(px)),
level(_level),
point(_point),
grad(1.0,0.0)
{}
};
}
#endif
Feature_detection.h
#ifndef SVO_FEATURE_DETECTION_H_
#define SVO_FEATURE_DETECTION_H_
#include <svo/global.h>
#include <svo_practice/frame.h>
namespace svo{
namespace feature_detection{
struct Corner{
int x;
int y;
int level;
float score;
float angle;
Corner(int x,int y,float score,int level,float angle):x(x),y(y),level(level),score(score),angle(angle){}
};
typedef vector<Corner> Corner;
class AbstractDetector{
public:
AbstractDetector(const int img_width,
const int img_height,
const int cell_size,
const int n_pyr_levels);
virtual ~AbstractDetector(){};
virtual void detect(Frame* frame,
const ImgPyr& img_pyr,
const double detection_threshold,
Features& fts) = 0;
void setGridOccpuancy(const Vector2d& px);
void setExistFeatures(const Feature& fts);
protected:
static const int border_ = 8;
const int cell_size_;
const int n_pyr_levels_;
const int grid_n_cols_;
const int grid_n_rows_;
vector<bool> grid_occupancy_;
void resetGrid();
inline int getCellIndex(int x,int y,int level){
const int scale = (1 << level);
return (scale * y) / cell_size_ * grid_n_cols_ + (scale * x) / cell_size_;
}
};
typedef boost::shared_ptr<AbstractDetector> DetectorPtr;
class FastDetector : public AbstractDetector{
public:
FastDetector(const int img_width,
const int img_height,
const int cell_size,
const int n_pyr_levels);
virtual ~FastDetector(){}
virtual void detect(Frame* frame,
const ImgPyr& img_pyr,
const double detection_threshold,
Features& fts);
};
}
}
#endif
Feature_detection.cpp
#include <svo/global.h>
#include <svo_practice/frame.h>
#include <svo_practice/feature.h>
#include <fast/fast.h>
#include <vikit/vision.h>
namespace svo{
namespace feature_detection{
AbstractDetector::AbstractDetector(const int img_width,
const int img_height,
const int cell_size,
const int n_pyr_levels):
cell_size_(cell_size),
n_pyr_levels_(n_pyr_levels),
grid_n_cols_(ceil(static_cast<double>(img_width) / cell_size_)),
grid_n_rows_(ceil(static_cast<double>(img_height / cell_size_)),
grid_occopancy_(grid_n_cols_ * grid_n_rows_,false)
{}
void AbstractDetector::resetGrid(){
std::fill(grid_occopancy_.begin(),grid_occopancy_.end(),false);
}
void AbstractDetector::setExistingFeatures(const Features& fts){
std::for_each(fts.begin(),fts.end(),[&](Feature* i)){
grid_occopancy_.at(static_cast<int>(i -> px[1]/cell_size_)*grid_n_cols_
+ static_cast<int>(i -> px[0]/cell_size_)) = true;
});
}
void AbstractDetector::setGridOccpuancy(const Vector2d& px){
grid_occopancy_.at(static_cast<int>(px[1] / cell_size_) * grid_n_cols_ +
static_cast<int>(px[0] / cell_size_)) = true;
}
void FastDetector::detect(Frame* frame,
const ImhPyr& img_pyr,
const double detection_threhold,
Features& fts){
Corner corners(grid_n_cols_ * grid_n_rows_,Corner(0,0,detection_threhold,0,0.0f));
for(int L = 0;L < n_pyr_levels_;++i){
const int scale = (1 << L);
vector<fast::fast_xy> fast_corners;
#if __SSE2__
fast::fast_corner_detect_10_sse2(
(fast::fast_byte*) img_pyr[L].data, img_pyr[L].cols,
img_pyr[L].rows, img_pyr[L].cols, 20, fast_corners);
#elif HAVE_FAST_NEON
fast::fast_corner_detect_9_neon(
(fast::fast_byte*) img_pyr[L].data, img_pyr[L].cols,
img_pyr[L].rows, img_pyr[L].cols, 20, fast_corners);
#else
fast::fast_corner_detect_10(
(fast::fast_byte*) img_pyr[L].data, img_pyr[L].cols,
img_pyr[L].rows, img_pyr[L].cols, 20, fast_corners);
#endif
vector<int> scores, nm_corners;
fast::fast_corner_detect_10((fast::fast_byte*) img_pyr[L].data,
img_pyr[L].cols,fast_corners,20,scores);
fast::fast_nonmax_3x3(fast_corners,scores,nm_corners);
for(auto it = nm_corners.begin(),ite = nm_corners.end();it != ite;++it){
fast::fast_xy& xy = fast_corners.at(*it);
const int k = static_cast<int>((xy.y * scale) / cell_size_)* grid_n_cols_ +
static_cast<int>((xy.x * scale) / cell_size_);
if(grid_occopancy_[k]) continue;
const float score = vk::shiTomasiScore(img_pyr[L],xy.x,xy.y);
if(score > corners.at(k).score)
corners.at(k) = Corner(xy.x*scale,xy.y*scale,score,L,0.0f);
}
}
std::for_each(corners.begin(),corners.end(),[&](Corner& c)){
if(c.score > detection_threhold)
fts.push_back(new Feature(frame,Vector2d(c.x,c.y),c.level));
});
resetGrid();
}
}
}