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

DualCoding 3.0beta
Generated Wed Oct 4 00:01:54 2006 by Doxygen 1.4.7