$search
00001 /* 00002 * geometric_hash.h 00003 * edge_matcher 00004 * 00005 * Created by Victor Eruhimov on 11/1/09. 00006 * Copyright 2009 Argus Corp. All rights reserved. 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 /*class AffineBasis 00027 { 00028 public: 00029 virtual cv::Point2f getOrigin() const = 0; 00030 virtual void getBasis(cv::Point2f* basis) const = 0; 00031 virtual cv::Point2f getCoords(cv::Point2f point) const = 0; 00032 };*/ 00033 00035 /*{ 00036 return sqrt(float(p.x*p.x) + p.y*p.y); 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]; // 0 is minimum, 1 is maximum 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]; // 0 is minimum, 1 is maximum 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