02/06/08 15-494 Cognitive Robotics 1Shape Predicates15-494 Cognitive RoboticsDavid S. Touretzky &Ethan Tira-ThompsonCarnegie MellonSpring 200802/06/08 15-494 Cognitive Robotics 2The World is Full of Shapes●When we extract shapes from camera images, we may get a lot of objects.●We needs ways of selecting and comparing shapes.●“Find all the orange things.”“Find all the lines longer than this line.”●Tekkotsu provides shape predicates for testing shapes. These can be composed to form complex tests.●To use these, you need to understand C++ functors.02/06/08 15-494 Cognitive Robotics 3Function Objects (Functors)#include <iostream>using namespace std;class MyFunctor { public: void operator() () const { cout << "Foo!" << endl; }};int main() { MyFunctor fluffy; fluffy();}02/06/08 15-494 Cognitive Robotics 4Functors Can Store Valuesclass BiggerThan { private: int value; public: BiggerThan(int val) : value(val) {} bool operator() (int x) const { return x > value; }};Private comparison valueConstructor initializes the private valueFunction call operatorcompares x against the value02/06/08 15-494 Cognitive Robotics 5Testing BiggerThanint main() { BiggerThan bigtest(5); for (int i = 3; i < 8; i++ ) cout << i << (bigtest(i) ? " passes" : " fails" ) << endl;}3 fails4 fails5 fails6 passes7 passes02/06/08 15-494 Cognitive Robotics 6Function Conjunctionclass AndBigSmall { private: BiggerThan bigtest; SmallerThan smalltest; public: AndBigSmall(BiggerThan b, SmallerThan s) : bigtest(b), smalltest(s) {} bool operator() (int x) { return bigtest(x) && smalltest(x); }};int main() { AndBigSmall myconj(BiggerThan(0),SmallerThan(100)); for ( int i = -10; i < 150; i+=40 ) cout << i << " gives " << myconj(i) << endl;}-10 gives 030 gives 170 gives 1110 gives 002/06/08 15-494 Cognitive Robotics 7STL functional.h●The STL (Standard Template Library) provides classes called unary_function and binary_function from which functors can be composed.●These user-defined functor classes can then be used with STL functions for searching, etc.●But they're kind of awkward.class BiggerThan : unary_function<int,bool> { private: int value; public: BiggerThan(int val) : value(val) {} bool operator() (int x) { return x > value; }};02/06/08 15-494 Cognitive Robotics 8Shape Predicates●The Shape classes provide their own functor mechanism for defining shape predicates.●Easier to use than the generic STL.●Some predicates for common shape tests are built in, e.g.,–Comparing the positions of two shapes (left/right or above/below)–Comparing the lengths of two lines–Comparing line orientations●New predicates are easy to define.02/06/08 15-494 Cognitive Robotics 9Shape<LineData> Functors●Compare the lengths of all the pink lines in the image against that of the third line.NEW_SKETCH(camFrame, uchar, sketchFromSeg());NEW_SKETCH(pink_stuff, bool, visops::colormask(camFrame,"pink"));NEW_SHAPEVEC(lines, LineData,LineData::extractLines(pink_stuff));SHAPEVEC_ITERATE(lines, LineData, ln) if ( LineData::LengthLessThan()(ln,lines[2]) ) cout << "Shorter: " << ln->getId() << endl; else cout << "Longer: " << ln->getId() << endl;END_ITERATE;02/06/08 15-494 Cognitive Robotics 10LineData::LengthLessThan●Class-specific shape predicates are defined with the respective shape, e.g., in LineData.h and LineData.cc.In LineData.h:class LengthLessThan : public BinaryShapePred<LineData> { public: bool operator() (const Shape<LineData> &ln1, const Shape<LineData> &ln2) const;};In LineData.cc:void LineData::LengthLessThan::operator() (const Shape<LineData> &line1, const Shape<LineData> &line2) const { return line1->getLength() < line2->getLength(); }02/06/08 15-494 Cognitive Robotics 11Generic Shape Predicates●Some predicates work for shapes of any type. They are defined on class ShapeRoot. Example: IsColor.NEW_SHAPEVEC(blobs, BlobData,BlobData::extractBlobs(camFrame,50));IsColor orangetest("orange");SHAPEVEC_ITERATE(blobs, BlobData, b) if ( orangetest(b) )cout << "Orange: " << b->getId() << endl; elsecout << "Not orange: " << b->getId() << endl;END_ITERATE;02/06/08 15-494 Cognitive Robotics 12Subclasses of BaseData:Subclasses of ShapeRoot:02/06/08 15-494 Cognitive Robotics 13Generic IsColor Predicateclass IsColor : public UnaryShapeRootPred { private: rgb color; public: IsColor(rgb col) : UnaryShapeRootPred(), color(col) {} IsColor(std::string const &colorname) : UnaryShapeRootPred(), color(ProjectInterface::getColorRGB(colorname)) {} bool operator() (const ShapeRoot &shape) const { return shape->getColor() == color; }};Note: the colorname string is looked up once, by the constructor, and the result is stored in the private variable color. When the functor is invoked on a ShapeRoot, no lookup is necessary.02/06/08 15-494 Cognitive Robotics 14IsLeftOf / IsLeftOfThis●IsLeftOf()–This is a BinaryShapeRootPred that requires two arguments,and compares their centroids:IsLeftOf() (line2,blob6)●IsLeftOfThis(x)–This is a UnaryShapeRootPred that requires one argument:IsLeftofThis(line2) (blob6)constructor argument02/06/08 15-494 Cognitive Robotics 15Using IsLeftOfThis●An instance of IsLeftOfThis stores a ShapeRoot inside it, and uses it for comparison tests.IsLeftOfThis mytest(lines[4]);SHAPEVEC_ITERATE(lines, LineData, ln) if ( mytest(ln) )cout << "This is left of me: " << ln->getId() << endl;END_ITERATE;02/06/08 15-494 Cognitive Robotics 16Built-In Shape PredicatesShapeRoot:IsColorIsTypeIsNameIsLeftOf / IsRightOfIsAbove / IsBelowIsLeftOfThis ...IsAboveThis ...Shape<LineData>:LengthLessThanIsHorizontalIsVerticalParallelTestPerpendicularTestColinearTest02/06/08 15-494 Cognitive Robotics 17AndPred / OrPred●Because shape predicates are classes, we can compose them using the functors AndPred and OrPred.●We are composing two unary predicates, so theresult is also a unary predicate: it takes one argument.SHAPEVEC_ITERATE(lines, LineData, ln) if ( AndPred(IsColor("pink"), IsLeftOfThis(lines[3])) (ln) ) cout << "winner: " << ln->getId() << endl; else cout << "loser: " << ln->getId() << endl;END_ITERATE;02/06/08 15-494 Cognitive Robotics 18Vectors of ShapeRoots●camShS.allShapes() returns all the shapes in the shape space, as a vector<ShapeRoot>.●camShS will be automatically coerced to vector<ShapeRoot> by an implicit call to allShapes()●Use SHAPEROOTVEC_ITERATE(vec,var) to iterate:●Shape type constants like blobDataType are defined in ShapeTypes.hSHAPEROOTVEC_ITERATE(camShS, s) if (
View Full Document