Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

CylinderData.cc

Go to the documentation of this file.
00001 #include <DualCoding/CylinderData.h>
00002 #include <DualCoding/ShapeCylinder.h>
00003 #include "SketchSpace.h"
00004 #include "Sketch.h"
00005 #include "ShapeSpace.h"
00006 #include "ShapeRoot.h"
00007 
00008 #include "ShapeBlob.h" //To extract pillar blobs before extracting cylinders
00009 using namespace std;
00010 
00011 namespace DualCoding {
00012 
00013 DATASTUFF_CC(CylinderData);
00014 
00015 CylinderData::CylinderData(ShapeSpace& _space, Point _centroid, float _height, float _radius, fmat::Quaternion _orientation) :
00016   BaseData(_space, getStaticType()), centroid(_centroid), height(_height), radius(_radius), orientation(_orientation) {
00017   centroid.setRefFrameType(getRefFrameType());
00018   mobile = true;
00019 }
00020 
00021 bool CylinderData::isMatchFor(const ShapeRoot& other) const {
00022   if (!(isSameTypeAs(other) && isSameColorAs(other)))
00023     return false;
00024   
00025   const Shape<CylinderData>& otherCyl = ShapeRootTypeConst(other,CylinderData);
00026   
00027   float diff = (centroid - otherCyl->centroid).xyzNorm();
00028   //if (diff < 2*radius && fabs(radius - otherCyl->radius) < radius/2)
00029   if (diff < 3*radius && fabs(radius - otherCyl->radius) < radius*0.8) // *** quick fix for Tapia
00030     return true;
00031   else
00032     return false;
00033 }
00034 
00035 //! return the centroid of the shape in point format
00036 Point CylinderData::getCentroid() const { return centroid; }
00037 
00038 bool CylinderData::updateParams(const ShapeRoot&, bool) { return true; }
00039 
00040 BoundingBox2D CylinderData::getBoundingBox() const {
00041   BoundingBox2D b;
00042   b.expand(fmat::pack(centroid.coordX()-radius, centroid.coordY()+height/2));
00043   b.expand(fmat::pack(centroid.coordX()+radius, centroid.coordY()-height/2));
00044   return b;
00045 }
00046 
00047 void CylinderData::printParams() const {
00048   cout << "Type = " << getTypeName() << "  ID=" << getId() << "  ParentID=" << getParentId() << endl;
00049   printf("  color = %d %d %d\n",getColor().red,getColor().green,getColor().blue);
00050   cout << "  centroid = " << centroid << endl;
00051   cout << "  radius = " << radius << endl;
00052   cout << "  height = " << height << endl;
00053   cout << "  orientation = " << orientation << endl;
00054 }
00055 
00056 void CylinderData::applyTransform(const fmat::Transform& Tmat, const ReferenceFrameType_t newref) {
00057   centroid.applyTransform(Tmat,newref);
00058 }
00059 
00060 void CylinderData::projectToGround(const fmat::Transform& camToBase, const PlaneEquation& groundplane) {
00061   float camRadius = radius;
00062   float camHeight = height;
00063   float assumedHalfHeight = centroid.coordZ(); // we stored the assumed half-height as the z coord in camera space
00064   Point bottomCenterPt = Point (centroid.coordX(), centroid.coordY()+height/2, 0, camcentric);
00065   Point bottomLeftPt = Point (centroid.coordX()-radius, centroid.coordY()+height/2, 0, camcentric);
00066   bottomLeftPt.projectToGround(camToBase,groundplane);
00067   bottomCenterPt.projectToGround(camToBase,groundplane);
00068   float diff = (bottomCenterPt - bottomLeftPt).xyNorm();
00069   radius = diff;
00070   float theta = std::atan2(bottomCenterPt.coordY(), bottomCenterPt.coordX());
00071   float xcenter = bottomCenterPt.coordX() + radius * cos(theta);
00072   float ycenter = bottomCenterPt.coordY() + radius * sin(theta);
00073   if ( assumedHalfHeight > 0 )
00074     height = assumedHalfHeight * 2;   // use assumed height if provided
00075   else
00076     height = radius/camRadius * camHeight;  // else infer height from cam shape's aspect ratio
00077   centroid = Point(xcenter, ycenter, height/2, egocentric);
00078 }
00079 
00080 Sketch<bool>* CylinderData::render() const {
00081     SketchSpace &SkS = space->getDualSpace();
00082     Sketch<bool>* result = new Sketch<bool>(SkS, "render("+getName()+")");
00083     *result = false;
00084     const float semimajor = radius;
00085     const float semiminor = semimajor;
00086     fmat::Column<3> ctr;
00087     ctr[0] = getCentroid().coordX();
00088     ctr[1] = getCentroid().coordY();
00089     ctr[2] = getCentroid().coordZ();
00090     SkS.applyTmat(ctr);
00091     const float &cx = ctr[0];
00092     const float &cy = ctr[1];
00093     const fmat::Transform &Tmat = SkS.getTmat();
00094     const float orient = M_PI / 2;
00095     fmat::Column<2> ori;
00096     ori[0] = cos(orient);
00097     ori[1] = sin(orient);
00098     fmat::Matrix<2,2> rot;
00099     rot(0,0) = Tmat(0,0);
00100     rot(0,1) = Tmat(0,1);
00101     rot(1,0) = Tmat(1,0);
00102     rot(1,1) = Tmat(1,1);
00103     ori = rot * ori;
00104     const float &cosT = ori[0];
00105     const float &sinT = ori[1];
00106     const float xRange = semimajor;  // don't scale this because cosT and sinT are scaled
00107     const float majorSq = xRange*xRange;
00108     const float mnrDevMjr = semiminor/semimajor;
00109     for (float xDist = -xRange; xDist <= xRange; xDist+=0.2f) {
00110       const float yRange = sqrt(max((float)0, majorSq - xDist*xDist)) * mnrDevMjr;
00111       for (float yDist = -yRange; yDist <= yRange; yDist+=0.2f) {
00112         int const px = round(cx+xDist*cosT-yDist*sinT);
00113         int const py = round(cy+yDist*cosT+xDist*sinT);
00114         if ( px >= 0 && px < result->width &&
00115         py >= 0 && py < result->height )
00116         (*result)(px,py) = true;
00117       }
00118     }
00119     return result;
00120 }
00121 
00122 std::vector<Shape<CylinderData> >
00123 CylinderData::extractCylinders(const Sketch<uchar> &sketch, 
00124                                const std::set<color_index>& colors,
00125                                const std::map<color_index,coordinate_t>& assumedHeights,
00126                                const std::map<color_index,int>& minCylinderAreas,
00127                                int maxcylinders,
00128                                std::vector<GazePoint> &addGazePts) {
00129 
00130   //const std::map<color_index, coordinate_t> heights;
00131   std::map<color_index, BlobData::BlobOrientation_t> orients;
00132   for (std::map<color_index, BlobData::BlobOrientation_t>::iterator it = orients.begin(); it != orients.end(); ++it) {
00133     it->second = BlobData::pillar;
00134   }
00135 
00136   std::vector<Shape<BlobData> > blobs = BlobData::extractBlobs(sketch, colors, minCylinderAreas, orients, assumedHeights, maxcylinders);
00137   std::vector<Shape<CylinderData> > resultingCylinders;
00138 
00139   ShapeSpace &shs = sketch->getSpace().getDualSpace();
00140   for (std::vector<Shape<BlobData> >::const_iterator it = blobs.begin(); it != blobs.end(); it++) {
00141     const Shape<BlobData> &blob = *it;
00142     Point centroid = blob->getCentroid();
00143     if ( blob->bottomValid && blob->leftValid && blob->rightValid ) {   // topValid not needed since we have assumed height
00144       //height and radius are calculated from the corner points of the blob
00145       float Ydist = blob->bottomLeft.coordY() - blob->topLeft.coordY();
00146       float height = blob->topValid ? Ydist : 0;
00147       float diameter = blob->topRight.coordX() - blob->topLeft.coordX();
00148       float radius = diameter / 2;
00149       //std::cout << "Cylinder blob: height=" << height << " diameter=" << diameter << " area=" << blob->getArea() << std::endl;
00150       if ( blob->getArea() > height*diameter/3 ) { // not a hollow blob
00151         fmat::Quaternion orientation = fmat::Quaternion(); //=?
00152         std::map<color_index,coordinate_t>::const_iterator it_h = assumedHeights.find(ProjectInterface::getColorIndex(blob->getColor()));
00153         coordinate_t assumedHeight = (it_h != assumedHeights.end()) ? it_h->second : 0;
00154         (centroid.getCoords())[2] = assumedHeight/2;  // cache the assumed half-height in the centroid z coordinate
00155         CylinderData *cylinder = new CylinderData(shs, centroid, height, radius, orientation);
00156         cylinder->setColor(blob->getColor());
00157         cylinder->setParentId(blob->getParentId());
00158         resultingCylinders.push_back(Shape<CylinderData>(cylinder));
00159       }
00160     }
00161     else {
00162       // add gaze points to get a better look at the blob
00163       addGazePts.push_back(GazePoint(GazePoint::centered,centroid));
00164     }
00165     shs.deleteShape(const_cast<Shape<BlobData>&>(blob));
00166   }
00167   return resultingCylinders;
00168 } 
00169 
00170 } // namespace

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