00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #if !defined(_GEOMETRIC_HASH)
00011 #define _GEOMETRIC_HASH
00012
00013 #include <math.h>
00014
00015 #include <cv.h>
00016 #include <cv.hpp>
00017
00018 #include <vector>
00019 #include <map>
00020 #include <list>
00021 #include <utility>
00022
00023 #include "one_way_descriptor_base.h"
00024 #include "features.h"
00025
00026
00027
00028
00029
00030
00031
00032
00033
00035
00036
00037
00038
00039 #define PI 3.1415926
00040
00041 class AffineBasis
00042 {
00043 protected:
00044 int model_id;
00045 cv::Point2f origin;
00046 cv::Point2f basis[2];
00047
00048 public:
00049 AffineBasis(cv::Point2f _origin, const cv::Point2f* _basis, int _model_id)
00050 {
00051 origin = _origin;
00052 basis[0] = _basis[0];
00053 basis[1] = _basis[1];
00054 model_id = _model_id;
00055 };
00056 AffineBasis(cv::Point2f _origin, cv::Point2f point1, cv::Point2f point2, int _model_id)
00057 {
00058 origin = _origin;
00059 basis[0] = point1 - origin;
00060 basis[1] = point2 - origin;
00061 model_id = _model_id;
00062 };
00063
00064 ~AffineBasis() {};
00065
00066 cv::Point2f getOrigin() const {return origin;};
00067 void getBasis(cv::Point2f* _basis) const
00068 {
00069 _basis[0] = basis[0];
00070 _basis[1] = basis[1];
00071 };
00072
00073 cv::Point2f getCoords(cv::Point2f point) const;
00074 cv::Point2f getPoint(cv::Point2f coords) const;
00075
00076 int getModelID() const {return model_id;};
00077
00078 float getAngle() const {return acos(basis[0].dot(basis[1])/(length(basis[0])*length(basis[1])));};
00079 };
00080
00081 typedef int ModelBasisID;
00082
00083 class GeometricHash
00084 {
00085 protected:
00086 cv::Size size;
00087 cv::Point2f range[2];
00088 std::vector<AffineBasis> bases;
00089 std::vector<std::list<ModelBasisID> > hash;
00090 std::list<ModelBasisID> empty_list;
00091
00092 int getBin(cv::Point2f coords) const;
00093
00094 public:
00095 GeometricHash(cv::Size _size, cv::Point2f range_min, cv::Point2f range_max);
00096 ModelBasisID addBasis(const AffineBasis& basis);
00097 const std::vector<AffineBasis>& getBases() const;
00098 void addEntry(const ModelBasisID& basisID, cv::Point2f point);
00099 const std::list<ModelBasisID>& getEntries(cv::Point2f point) const;
00100
00101 };
00102
00103 class GeometricHash3D
00104 {
00105 protected:
00106 cv::Point3i size;
00107 cv::Point3f range[2];
00108 std::vector<AffineBasis> bases;
00109 std::vector<std::list<ModelBasisID> > hash;
00110 std::list<ModelBasisID> empty_list;
00111
00112 int getBin(cv::Point3f coords) const;
00113
00114 public:
00115 GeometricHash3D(cv::Point3i _size, const cv::Point3f* _range);
00116 ModelBasisID addBasis(const AffineBasis& basis);
00117 const std::vector<AffineBasis>& getBases() const;
00118 void addEntry(const ModelBasisID& basisID, CvSeq* seq, int idx_offset, int idx_point);
00119 const std::list<ModelBasisID>& getEntries(cv::Point3f point) const;
00120 };
00121
00122 class EdgeMatcher
00123 {
00124 protected:
00125 std::vector<CvSeq*> edges;
00126 GeometricHash3D hash;
00127 static const float min_angle;
00128
00129 public:
00130 typedef std::map<int,std::pair<int,int> > ModelVotes;
00131
00132 EdgeMatcher(cv::Point3f _size, const cv::Point3f* _range) : hash(_size, _range) {};
00133
00134 int addModel(CvSeq* edge);
00135 void addModelBasis(CvSeq* edge, int idx_origin, const AffineBasis& basis);
00136 AffineBasis match(CvSeq* edge, std::map<int,std::pair<int,int> >& votes) const;
00137 void aggregateVotes(const std::vector<int>& basis_votes, std::map<int,std::pair<int,int> >& agg_votes) const;
00138 void matchBasis(CvSeq* edge, const AffineBasis& basis, int idx_origin, std::vector<int>& votes) const;
00139 CvSeq* getModel(int modelID) {return edges[modelID];};
00140 CvSeq* getModelByBasisID(int basis_id) const {return edges[hash.getBases()[basis_id].getModelID()];};
00141 const AffineBasis& getBasis(int basis_id) const {return hash.getBases()[basis_id];};
00142 const GeometricHash3D& getHash() const {return hash;};
00143
00144 static bool votes_greater(const std::pair<int,std::pair<int,int> >& elem1, const std::pair<int,std::pair<int,int> >& elem2)
00145 {
00146 return elem1.second.second < elem2.second.second;
00147 }
00148 };
00149
00150 AffineBasis getPointEdgeBasis(cv::Point2f point, CvSeq* edge, int i, int modelID);
00151 float fitEdges(CvSeq* model, const AffineBasis& model_basis, CvSeq* test, const AffineBasis& test_basis);
00152 float fitEdgesSym(CvSeq* model_seq, const AffineBasis& model_basis, CvSeq* test_seq, const AffineBasis& test_basis);
00153 float fitPoints(const std::vector<cv::Point2f>& set1, const std::vector<cv::Point2f>& set2);
00154 float fitPointsSym(const std::vector<cv::Point2f>& set1, const std::vector<cv::Point2f>& set2);
00155 CvSeq* mapContour(CvSeq* contour, AffineBasis src, AffineBasis dst, CvMemStorage* storage);
00156 void mapPoints(const std::vector<cv::Point2f>& src, const AffineBasis& src_basis, const AffineBasis& dst_basis, std::vector<cv::Point2f>& dst);
00157 void mapPoints(const std::vector<KeyPointEx>& src, const AffineBasis& src_basis, const AffineBasis& dst_basis, std::vector<KeyPointEx>& dst);
00158
00159 class PointEdgeMatcher : public EdgeMatcher
00160 {
00161 public:
00162 typedef std::pair<cv::Point2f,CvSeq*> Model;
00163
00164 private:
00165 std::vector<Model> models;
00166
00167 public:
00168 PointEdgeMatcher(cv::Point3f _size, const cv::Point3f* _range) : EdgeMatcher(_size, _range) {};
00169
00170 int addModel(const Model& model);
00171 const Model& getModel(int model_id) {return models[model_id];};
00172 const Model& getModelByBasisID(int basis_id) const {return models[hash.getBases()[basis_id].getModelID()];};
00173 AffineBasis match(cv::Point2f point, CvSeq* edge, std::map<int,std::pair<int, int> >& votes) const;
00174 };
00175
00176 float calcAffineSeqDist(const AffineBasis& basis, CvSeq* seq, int idx1, int idx2, int is_mapped = 0);
00177
00178 class PointMatcher
00179 {
00180 public:
00181 struct PointMatcherParams
00182 {
00183 PointMatcherParams(float _min_angle = 0.5f, float _max_basis_length = 100.0f, float _min_basis_length = 10.0f,
00184 int _min_hash_votes = 3, float _min_validated_votes = 5.0f, float _min_distortion_ratio = 0.8f) :
00185 min_angle(_min_angle), max_basis_length(_max_basis_length), min_basis_length(_min_basis_length),
00186 min_hash_votes(_min_hash_votes), min_validated_votes(_min_validated_votes), min_distortion_ratio(_min_distortion_ratio) {};
00187
00188 float min_angle;
00189 float max_basis_length;
00190 float min_basis_length;
00191 int min_hash_votes;
00192 float min_validated_votes;
00193 float min_distortion_ratio;
00194 };
00195
00196 protected:
00197 GeometricHash hash;
00198 std::vector<KeyPointEx> template_points;
00199 PointMatcherParams params;
00200
00201 public:
00202 typedef std::map<int,std::pair<int,int> > ModelVotes;
00203
00204 PointMatcher(cv::Size _size, cv::Point2f range_min, cv::Point2f range_max,
00205 PointMatcher::PointMatcherParams _params = PointMatcher::PointMatcherParams()) : hash(_size, range_min, range_max), params(_params) {};
00206
00207 int addModel(const std::vector<KeyPointEx>& points);
00208 void addModelBasis(const std::vector<KeyPointEx>& points, const AffineBasis& basis);
00209 int match(const std::vector<KeyPointEx>& points, std::vector<float>& votes,
00210 std::vector<std::pair<AffineBasis,AffineBasis> >& matched_bases) const;
00211 void matchBasis(const std::vector<KeyPointEx>& points, const AffineBasis& basis, std::vector<int>& votes) const;
00212 const AffineBasis& getBasis(int basis_id) const {return hash.getBases()[basis_id];};
00213 const GeometricHash& getHash() const {return hash;};
00214 const std::vector<KeyPointEx>& getTemplatePoints() const {return template_points;};
00215 };
00216
00217 float validatePointMatch(const std::vector<KeyPointEx>& set1, const AffineBasis& basis1,
00218 const std::vector<KeyPointEx>& set2, const AffineBasis& basis2);
00219
00220 void getProximityPoints(const std::vector<KeyPointEx>& points, KeyPointEx point, float max_dist, std::vector<int>& indices);
00221 void findClosestPoint(const std::vector<KeyPointEx>& guess, const std::vector<KeyPointEx>& candidates, std::vector<KeyPointEx>& output, std::vector<bool>& is_detected, float max_dist);
00222 double affineDistortionRatio(const AffineBasis& basis1, const AffineBasis& basis2);
00223
00224
00225 #endif //_GEOMETRIC_HASH