00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054 #pragma once
00055
00056 #include "cob_3d_features/invariant_surface_feature.h"
00057 #include <unsupported/Eigen/FFT>
00058 #include <unsupported/Eigen/Polynomials>
00059
00060 template<typename TSurface, typename Scalar, typename Real, typename TAffine>
00061 void cob_3d_features::InvariantSurfaceFeature<TSurface,Scalar,Real,TAffine>::compute() {
00062 result_.reset(new Result);
00063
00064
00065 std::vector<TVector> keypoints;
00066 generateKeypoints(keypoints);
00067 std::cout<<"got "<<keypoints.size()<<" keypoints"<<std::endl;
00068
00069 result_->resize(keypoints.size());
00070 for(size_t j=0; j<radii_.size(); j++) {
00071 for(size_t i=0; i<keypoints.size(); i++) {
00072
00073 std::vector<Triangle> submap;
00074 subsample(keypoints[i], radii_[j], submap);
00075
00076
00077 sr_.clear();
00078
00079 for(size_t s=0; s<submap.size(); s++) {
00080 std::cout<<s<<std::endl;
00081 sr_ += submap[s];
00082 }
00083
00084 sr_.finish((*result_)[j]);
00085 }
00086 }
00087 }
00088
00089 template<typename TSurface, typename Scalar, typename Real, typename TAffine>
00090 void cob_3d_features::InvariantSurfaceFeature<TSurface,Scalar,Real,TAffine>::Triangle::compute(const typename S::Samples &samples) {
00091 for(int i=0; i<3; i++) {
00092 this->p3_[i](0) = p_[i](0);
00093 this->p3_[i](1) = p_[i](1);
00094 this->p3_[i](2) = model_->model(p_[i](0), p_[i](1));
00095 }
00096
00097
00098 if(area<TSurface::DEGREE>()>0.0001) {
00099 std::cout<<"subdivide "<<area<TSurface::DEGREE>()<<std::endl;
00100 Eigen::Matrix<Scalar, 2, 1> ps[3];
00101 for(int i=0; i<3; i++)
00102 ps[i] = ((p_[i])+(p_[(i+1)%3]))/2;
00103
00104 Triangle tris[4];
00105 for(int i=0; i<3; i++) {
00106 tris[i].p_[i] = p_[i];
00107 tris[i].p_[(i+1)%3] = ps[i];
00108 tris[i].p_[(i+2)%3] = ps[(i+2)%3];
00109 tris[3].p_[i] = ps[i];
00110 }
00111 for(int i=0; i<4; i++) {
00112 tris[i].model_ = model_;
00113 tris[i].compute(samples);
00114 for(size_t j=0; j<this->f_.size(); j++)
00115 for(size_t k=0; k<this->f_[j].size(); k++)
00116 this->f_[j][k] += ((typename S::Values)tris[i])[j][k];
00117 }
00118 } else
00119 cob_3d_features::invariant_surface_feature::SingleTriangle<Scalar, typename S::Samples, typename S::Values>::compute(samples);
00120 }
00121
00122 template<typename TSurface, typename Scalar, typename Real, typename TAffine>
00123 void cob_3d_features::InvariantSurfaceFeature<TSurface,Scalar,Real,TAffine>::generateKeypoints(std::vector<TVector> &keypoints) const {
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139 for(size_t i=0; i<input_->size(); i++) {
00140 if((*input_)[i].segments_.size()<1) continue;
00141 for(size_t k=0; k<(*input_)[i].segments_[0].size(); k+=20) {
00142 TVector v;
00143 v(0) = (*input_)[i].segments_[0][k](0);
00144 v(1) = (*input_)[i].segments_[0][k](1);
00145 v(2) = (*input_)[i].model_.model( v(0), v(1) );
00146 keypoints.push_back(v);
00147 break;
00148 }
00149 }
00150 }
00151
00152 template<typename TSurface, typename Scalar, typename Real, typename TAffine>
00153 Eigen::Matrix<Scalar, 2, 1>
00154 cob_3d_features::InvariantSurfaceFeature<TSurface,Scalar,Real,TAffine>::Triangle::intersection_on_line(const TVector &at, const Scalar r2, const Eigen::Matrix<Scalar, 2, 1> &a, const Eigen::Matrix<Scalar, 2, 1> &b) const {
00155
00156 assert((this->at(a)-at).squaredNorm()>r2 || (this->at(b)-at).squaredNorm()>r2);
00157
00158 Eigen::PolynomialSolver<typename TSurface::Model::VectorU1D::Scalar, 2*TSurface::DEGREE> solver;
00159 typename TSurface::Model::VectorU1D p = model_->transformation_1D( (b-a).template cast<typename TSurface::Model::VectorU1D::Scalar>(), a.template cast<typename TSurface::Model::VectorU1D::Scalar>(), at.template cast<typename TSurface::Model::VectorU1D::Scalar>());
00160 p(0) -= r2;
00161 solver.compute(p);
00162
00163
00164
00165 std::vector<typename TSurface::Model::VectorU1D::Scalar> r;
00166 solver.realRoots(r);
00167 assert(r.size()>0);
00168
00169 const typename TSurface::Model::VectorU1D::Scalar mid = 0.5f;
00170 size_t best=0;
00171 for(size_t i=1;i<r.size();++i)
00172 {
00173 if( (r[best]-mid)*(r[best]-mid)>(r[i]-mid)*(r[i]-mid))
00174 best=i;
00175 }
00176
00177 assert(r[best]>=0 && r[best]<=1);
00178
00179 Eigen::Matrix<Scalar, 2, 1> v;
00180 v(0) = (b(0)-a(0))*r[best]+a(0);
00181 v(1) = (b(1)-a(1))*r[best]+a(1);
00182
00183 return v;
00184 }
00185
00186 template<typename TSurface, typename Scalar, typename Real, typename TAffine>
00187 void cob_3d_features::InvariantSurfaceFeature<TSurface,Scalar,Real,TAffine>::Triangle::subsample(const typename S::Samples &samples, const TVector &at, const Scalar r2, std::vector<Triangle> &res) const {
00188
00189 bool b[3];
00190 int n=0;
00191 for(int j=0; j<3; j++)
00192 n+= (b[j] = ( (this->p3_[j]-at).squaredNorm()<=r2))?1:0;
00193
00194 if(n==0)
00195 return;
00196 else if(n==3)
00197 res.push_back(*this);
00198 else if(n==2) {
00199 Triangle tr1 = *this;
00200 Triangle tr2 = *this;
00201 const int ind = !b[0]?0:(!b[1]?1:2);
00202
00203
00204
00205
00206
00207 tr1.p_[ind] = intersection_on_line(at, r2, p_[ind], p_[ (ind+2)%3 ]);
00208 tr2.p_[(ind+1)%3] = intersection_on_line(at, r2, p_[ind], p_[ (ind+1)%3 ]);
00209 tr2.p_[ind] = tr1.p_[ind];
00210
00211 tr1.compute(samples);
00212 tr2.compute(samples);
00213 res.push_back(tr1);
00214 res.push_back(tr2);
00215 }
00216 else if(n==1) {
00217 Triangle tr = *this;
00218 const int ind = b[0]?0:(b[1]?1:2);
00219
00220 tr.p_[(ind+1)%3] = intersection_on_line(at, r2, tr.p_[ind], tr.p_[ (ind+1)%3 ]);
00221 tr.p_[(ind+2)%3] = intersection_on_line(at, r2, tr.p_[ind], tr.p_[ (ind+2)%3 ]);
00222
00223 tr.compute(samples);
00224 res.push_back(tr);
00225 }
00226 }
00227
00228 template<typename TSurface, typename Scalar, typename Real, typename TAffine>
00229 void cob_3d_features::InvariantSurfaceFeature<TSurface,Scalar,Real,TAffine>::subsample(const TVector &at, const Scalar r2, std::vector<Triangle> &res) const {
00230 res.clear();
00231 for(size_t i=0; i<triangulated_input_.size(); i++)
00232 triangulated_input_[i].subsample(samples_, at, r2, res);
00233 }
00234
00235 template<typename TSurface, typename Scalar, typename Real, typename TAffine>
00236 void cob_3d_features::InvariantSurfaceFeature<TSurface,Scalar,Real,TAffine>::setInput(PTSurfaceList surfs) {
00237 input_=surfs;
00238 triangulated_input_.clear();
00239
00240 for(size_t indx=0; indx<input_->size(); indx++) {
00241 TPPLPartition pp;
00242 list<TPPLPoly> polys,result;
00243
00244
00245 for(size_t i=0; i<(*input_)[indx].segments_.size(); i++) {
00246 std::cout<<"S "<<indx<<" "<<i<<" "<<(*input_)[indx].segments_[i].size()<<std::endl;
00247 TPPLPoly poly;
00248 poly.Init((*input_)[indx].segments_[i].size());
00249 poly.SetHole(i!=0);
00250 poly.SetOrientation(i!=0?TPPL_CW:TPPL_CCW);
00251
00252 for(size_t j=0; j<(*input_)[indx].segments_[i].size(); j++) {
00253 poly[j].x = (*input_)[indx].segments_[i][j](0);
00254 poly[j].y = (*input_)[indx].segments_[i][j](1);
00255 }
00256
00257 polys.push_back(poly);
00258 break;
00259 }
00260
00261 pp.Triangulate_EC(&polys,&result);
00262
00263 std::cout<<"triangles "<<result.size()<<std::endl;
00264 Eigen::Vector3f v1,v2,v3;
00265 for(std::list<TPPLPoly>::iterator it=result.begin(); it!=result.end(); it++) {
00266 if(it->GetNumPoints()!=3) continue;
00267
00268 Triangle tr;
00269 tr.model_ = &(*input_)[indx].model_;
00270 for(int j=0; j<3; j++)
00271 Triangle::set(tr.p_[j], it->GetPoint(j));
00272 tr.compute(samples_);
00273
00274 triangulated_input_.push_back(tr);
00275 }
00276 }
00277 }
00278
00279