Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

PyramidData.cc

Go to the documentation of this file.
00001 //-*-c++-*-
00002 
00003 #include <iostream>
00004 #include <vector>
00005 
00006 #include "BaseData.h"    // superclass
00007 #include "Point.h"       // Point data member
00008 #include "ShapeTypes.h"  // pyramidDataType
00009 
00010 #include "SketchSpace.h"
00011 #include "Sketch.h"
00012 #include "visops.h"
00013 
00014 #include "ShapeSpace.h"  // required by DATASTUFF_CC
00015 #include "ShapeRoot.h"   // required by DATASTUFF_CC
00016 
00017 #include "PyramidData.h"
00018 #include "ShapePyramid.h"
00019 #include "ShapePoint.h"
00020 #include "Region.h"
00021 
00022 using namespace std;
00023 
00024 namespace DualCoding {
00025 
00026   PyramidData::PyramidData(ShapeSpace& _space,
00027          const EndPoint &_FL, const EndPoint &_FR, 
00028          const EndPoint &_BL, const EndPoint &_BR, 
00029          const EndPoint &_Top)
00030     : BaseData(_space,pyramidDataType), 
00031       FL(_FL), FR(_FR), BL(_BL), BR(_BR), Top(_Top),
00032       centroid((FL + FR + BL + BR + Top) / 5)
00033   {
00034   }
00035 
00036   
00037   DATASTUFF_CC(PyramidData);
00038 
00039   bool PyramidData::isMatchFor(const ShapeRoot& other) const {
00040     if (!(isSameTypeAs(other) && isSameColorAs(other)))
00041       return false;
00042 
00043     // needs implementation
00044     float dist = 0;
00045     return dist < 20; 
00046   }
00047   
00048   void PyramidData::mergeWith(const ShapeRoot& other) {
00049     const Shape<PyramidData>& other_pyramid = ShapeRootTypeConst(other,PyramidData);
00050     if (other_pyramid->confidence <= 0)
00051       return;
00052   }
00053 
00054   bool PyramidData::updateParams(const ShapeRoot& other, bool) {
00055     const Shape<PyramidData>& other_pyramid = *static_cast<const Shape<PyramidData>*>(&other);
00056     //  ++confidence;
00057     FL = (FL*(confidence-1) + other_pyramid->getFL())/confidence;
00058     FR = (FR*(confidence-1) + other_pyramid->getFR())/confidence;
00059     BL = (BL*(confidence-1) + other_pyramid->getBL())/confidence;
00060     BR = (BR*(confidence-1) + other_pyramid->getBR())/confidence;
00061     Top = (Top*(confidence-1) + other_pyramid->getTop())/confidence;
00062     deleteRendering();
00063     return true;
00064   }
00065 
00066   //! Print information about this shape. (Virtual in BaseData.)
00067   void PyramidData::printParams() const {
00068     cout << "Type = " << getTypeName();
00069     cout << "Shape ID = " << getId() << endl;
00070     cout << "Parent ID = " << getParentId() << endl;
00071   
00072     printf("color = %d %d %d\n",getColor().red,getColor().green,getColor().blue);
00073     cout << "viewable = " << isViewable() << endl;
00074   }
00075 
00076 
00077   //! Transformations. (Virtual in BaseData.)
00078   void PyramidData::applyTransform(const fmat::Transform& Tmat, const ReferenceFrameType_t newref) {
00079     FL.applyTransform(Tmat,newref);
00080     FR.applyTransform(Tmat,newref);
00081     BL.applyTransform(Tmat,newref);
00082     BR.applyTransform(Tmat,newref);
00083     Top.applyTransform(Tmat,newref);
00084   }
00085 
00086   /*void PyramidData::projectToGround(const fmat::Column<4>& groundplane) {
00087     FL.projectToGround(groundplane);
00088     FR.projectToGround(groundplane);
00089     BL.projectToGround(groundplane);
00090     BR.projectToGround(groundplane);
00091 
00092     Point bottomCenter = (FL + FR + BL + BR) / 4.0;
00093     float height;
00094     Top.projectToGround(groundplane);
00095     height = Top.getHeightAbovePoint(bottomCenter, groundplane);
00096     Top.setCoords(bottomCenter.coordX(), bottomCenter.coordY(), bottomCenter.coordZ() + height);
00097     centroid = bottomCenter;
00098     centroid.setCoords(centroid.coordX(), centroid.coordY(), centroid.coordZ() + height/5);
00099     std::cout<<"New centroid: ("<<centroid.coordX()<<","<<centroid.coordY()<<","<<centroid.coordZ()<<")\n";
00100     }*/
00101 
00102   void PyramidData::projectToGround(const fmat::Transform & camToBase, const PlaneEquation& groundplane) {
00103     FL.projectToGround(camToBase, groundplane);
00104     FR.projectToGround(camToBase, groundplane);
00105     BL.projectToGround(camToBase, groundplane);
00106     BR.projectToGround(camToBase, groundplane);
00107 
00108     Point bottomCenter = (FL + FR + BL + BR) / 4.f;
00109     bottomCenter.setRefFrameType(egocentric);
00110     float height;
00111     Top.projectToGround(camToBase, groundplane);
00112     height = Top.getHeightAbovePoint(bottomCenter, groundplane);
00113     Top.setCoords(bottomCenter.coordX(), bottomCenter.coordY(), bottomCenter.coordZ() + height);
00114     centroid = bottomCenter;
00115     centroid.setCoords(centroid.coordX(), centroid.coordY(), centroid.coordZ() + height/5);
00116     std::cout << "New centroid: " << centroid << endl;
00117   }
00118 
00119   // =====================================================
00120   // BEGIN SKETCH MANIPULATION AND PYRAMID EXTRACTION CODE
00121   // =====================================================
00122 
00123 
00124   //! Pyramid extraction.
00125 
00126 
00127   //! Render into a sketch space and return reference. (Private.)
00128   Sketch<bool>* PyramidData::render() const {
00129     SketchSpace &renderspace = space->getDualSpace();
00130     //int const width = renderspace.getWidth();
00131     //int const height = renderspace.getHeight();
00132     //float x1,y1,x2,y2;
00133     Sketch<bool>* draw_result = 
00134       new Sketch<bool>(renderspace, "render("+getName()+")");
00135     (*draw_result)->setParentId(getViewableId());
00136     (*draw_result)->setColor(getColor());
00137     *draw_result = 0;
00138     LineData F(*space, FL, FR);
00139     *draw_result = *draw_result & F.getRendering();
00140     LineData L(*space, FL, BL);
00141     *draw_result = *draw_result & L.getRendering();
00142     LineData B(*space, BL, BR);
00143     *draw_result = *draw_result & B.getRendering();
00144     LineData R(*space, BR, FR);
00145     *draw_result = *draw_result & R.getRendering();
00146     LineData FT(*space, FL, Top);
00147     *draw_result = *draw_result & FT.getRendering();
00148     LineData LT(*space, FR, Top);
00149     *draw_result = *draw_result & LT.getRendering();
00150     LineData BT(*space, BL, Top);
00151     *draw_result = *draw_result & BT.getRendering();
00152     LineData RT(*space, BR, Top);
00153     *draw_result = *draw_result & RT.getRendering();
00154   
00155     return draw_result;
00156   }
00157 
00158 
00159 
00160 
00161   /* Same idea as extractBrick, but simpler
00162    */
00163   Shape<PyramidData> PyramidData::extractPyramid(ShapeSpace& space, vector<Shape<BlobData> > &blobs)
00164   {
00165     unsigned int nblobs = blobs.size();
00166     std::vector<Point> centroids;
00167 
00168     ShapeRoot invalid;
00169     if (nblobs != 2) {
00170       return ShapeRootType(invalid,PyramidData);
00171     }
00172 
00173     for (unsigned int i=0; i<nblobs; i++) {
00174       centroids.push_back(blobs[i]->getCentroid());
00175     }
00176   
00177     // Check inter-blob distance
00178     if (centroids[0].distanceFrom(centroids[1]) >= 
00179   blobs[0]->topLeft.distanceFrom(centroids[0]) + 
00180   blobs[1]->topLeft.distanceFrom(centroids[1])){
00181       return ShapeRootType(invalid,PyramidData);  
00182     }
00183 
00184     int left=-1, right=-1;
00185   
00186     if (centroids[0].isLeftOf(centroids[1], camcentric)) {
00187       left = 0;
00188       right = 1;
00189     }
00190     else {
00191       left = 1;
00192       right = 0;
00193     }
00194 
00195     const int INTERSECT_DIST = 5, MIN_REQUIRED_DIST = 2;
00196     NEW_SKETCH_N(leftEdist, uchar, visops::mdist(blobs[left]->getRendering()));
00197     NEW_SKETCH_N(rightEdist, uchar, visops::mdist(blobs[right]->getRendering()));
00198     NEW_SKETCH(small, bool, (leftEdist<MIN_REQUIRED_DIST) & (rightEdist<MIN_REQUIRED_DIST));
00199     if (!small->max()){
00200       return ShapeRootType(invalid,PyramidData);  
00201     }
00202     NEW_SKETCH(boundary, bool, (leftEdist<INTERSECT_DIST) & (rightEdist<INTERSECT_DIST));
00203     rgb green_rgb(0, 255, 0);
00204     boundary->setColor(green_rgb);
00205 
00206     // Extract candidate points
00207     std::vector<std::vector<Point> > points(5);
00208 
00209     /*
00210      *          0
00211      *         /|\ 
00212      *        / | \  
00213      *       /  |  \ 
00214      *      / L | R \ 
00215      *     /    |    \ <--- 4
00216      *    1-----2-----3
00217      */
00218 
00219 
00220     NEW_SHAPE(boundaryline, LineData, LineData::extractLine(boundary));
00221 
00222     if (boundaryline.isValid()) {
00223       points[0].push_back(boundaryline->topPt());
00224       points[2].push_back(boundaryline->bottomPt());
00225     }
00226 
00227 
00228     // Find the corners for each face individually
00229     // blobData::findCorners takes the number of corners you expect, so this 
00230     // uses the same method as extractBrick
00231 
00232     std::vector<Point> candidates; 
00233 
00234     candidates = findBoundingTriangle(space, blobs[left], 
00235               centroids[left], boundaryline);
00236 
00237     float cornerValue;
00238 
00239     std::vector<Point> lcorners = blobs[left]->findCorners(3, candidates, cornerValue);
00240 
00241     if (lcorners.size() == 3) {
00242 
00243       unsigned int leftCorner = 0;
00244       for (unsigned int i=1; i<3; i++){
00245   if (lcorners[i].isLeftOf(lcorners[leftCorner], camcentric)) {
00246     leftCorner = i;
00247   }
00248       }
00249 
00250       points[1].push_back(lcorners[leftCorner]);
00251       points[2].push_back(lcorners[(leftCorner+1)%3]);
00252       points[0].push_back(lcorners[(leftCorner+2)%3]);
00253     
00254     }
00255     else {
00256       return ShapeRootType(invalid,PyramidData);
00257     }
00258 
00259 
00260     // find the corners of the right face.
00261 
00262     candidates.clear();
00263     candidates = findBoundingTriangle(space, blobs[right], 
00264               centroids[right], boundaryline);
00265 
00266     std::vector<Point> rcorners = blobs[right]->findCorners(3, candidates, cornerValue);
00267 
00268     if (rcorners.size() == 3) {
00269 
00270       unsigned int rightCorner = 0;
00271       for (unsigned int i=1; i<3; i++){
00272   if (rcorners[i].isRightOf(rcorners[rightCorner], camcentric)) {
00273     rightCorner = i;
00274   }
00275       }
00276 
00277       points[3].push_back(rcorners[rightCorner]);
00278       points[0].push_back(rcorners[(rightCorner+1)%3]);
00279       points[2].push_back(rcorners[(rightCorner+2)%3]);
00280     
00281     }
00282     else {
00283       return ShapeRootType(invalid,PyramidData);
00284     }
00285 
00286     // debug output
00287     for (unsigned int i=0; i<5; i++){
00288       for (unsigned int j=0; j<points[i].size(); j++) {
00289   NEW_SHAPE(corner, PointData, PointData(space, points[i][j]));
00290   char name[10];
00291   sprintf(name, "corner%d%d",i,j);
00292   corner->setName(name);
00293       }
00294     }
00295 
00296 
00297     vector<Point> finalCorners(5);
00298 
00299     Point empty(0,0);
00300 
00301     for (unsigned int i=0; i<5; i++) {
00302       finalCorners[i] = empty;
00303       for (unsigned int j=0; j<points[i].size(); j++) {
00304   finalCorners[i]+=points[i][j];
00305       }
00306       if (points[i].size() > 0) {
00307   finalCorners[i]/=points[i].size();
00308       }
00309     }
00310 
00311 
00312 
00313 
00314     finalCorners[4] = finalCorners[1] + finalCorners[3] - finalCorners[2];
00315 
00316 
00317     NEW_SHAPE(returnPyramid, PyramidData, new PyramidData(space,
00318                 finalCorners[1],
00319                 finalCorners[2],
00320                 finalCorners[4],
00321                 finalCorners[3],
00322                 finalCorners[0]));
00323   
00324     return returnPyramid;
00325   }
00326 
00327 
00328 
00329   // A bounding triangle with room around it
00330   // contracted in quadrilateral (polygon) fitting
00331   vector<Point> PyramidData::findBoundingTriangle(ShapeSpace& space, Shape<BlobData> blob, 
00332               Point /*centroid*/, Shape<LineData> parallel)
00333   {
00334 
00335     const float PARALLEL_EXTEND_FACTOR = .4f, ORTHO_EXTEND_FACTOR = .4f;
00336     
00337     vector<Point> candidates;
00338     
00339     Point thirdPoint = (Region::extractRegion(blob->getRendering())).mostDistantPtFrom(parallel.getData());
00340     
00341     LineData perpendicular(space, thirdPoint, parallel->getThetaNorm());
00342 
00343     Point isect(perpendicular.intersectionWithLine(parallel));
00344     
00345     Point orthoExtend((thirdPoint - isect)*ORTHO_EXTEND_FACTOR);
00346     Point parallelExtend((parallel->end2Pt() - parallel->end1Pt())*PARALLEL_EXTEND_FACTOR);
00347 
00348     Point pt1(parallel->end1Pt() - parallelExtend - orthoExtend);
00349     Point pt2(parallel->end2Pt() + parallelExtend - orthoExtend);
00350 
00351     if ((pt1.isAbove(pt2, camcentric) && thirdPoint.isLeftOf(pt1, camcentric)) || 
00352   (!pt1.isAbove(pt2, camcentric) && !thirdPoint.isLeftOf(pt1, camcentric))){
00353       candidates.push_back(pt2);
00354       candidates.push_back(pt1);
00355     }
00356     else {
00357       candidates.push_back(pt1);
00358       candidates.push_back(pt2);
00359     }
00360     candidates.push_back(thirdPoint + orthoExtend);
00361 
00362     // debug output
00363     NEW_SHAPE(candidate31, PointData, PointData(space, candidates[0]));
00364     NEW_SHAPE(candidate32, PointData, PointData(space, candidates[1]));
00365     NEW_SHAPE(candidate33, PointData, PointData(space, candidates[2]));
00366     candidate31->setParentId(blob->getViewableId());
00367     candidate32->setParentId(blob->getViewableId());
00368     candidate33->setParentId(blob->getViewableId());
00369 
00370     return candidates;
00371   }
00372 
00373 
00374 } // namespace

DualCoding 5.1CVS
Generated Mon May 9 04:56:27 2016 by Doxygen 1.6.3