00001
00007 #ifndef __RETINALOBJS_H__
00008 #define __RETINALOBJS_H__
00009
00010 #include <vector>
00011 #include <algorithm>
00012 #include <string>
00013
00014 #include "matrix.h"
00015
00016 #include "genericalgs.h"
00017 #include "valuegen.h"
00018 #include "valuegenmap.h"
00019 #include "pnm_io.h"
00020 #include "boundingbox.h"
00021 #include "robj.h"
00022
00023
00024
00025
00026
00027
00028
00051 class Retinal_Object : public Retinal_Obj {
00052 protected:
00054 typedef AARBoundingBox<Coordinate> BBox;
00055
00056 public:
00058 typedef double Variable;
00060 typedef ValueGenerator<Variable> VarGen;
00062 typedef ValueGeneratorMap<Variable> VarMap;
00063
00066 Retinal_Object(const string& name_val, const VarMap& init_vars=VarMap())
00067 : bounding_box(), active(true), name(name_val), default_act(0.0) {
00068 vars.merge(init_vars);
00069 set_var_default("scale",1.0);
00070 }
00071
00072 Retinal_Object(const Retinal_Object& b)
00073 : Retinal_Obj(b), bounding_box(b.bounding_box), vars(b.vars),
00074 active(b.active), name(b.name), default_act(b.default_act) { }
00075
00076 virtual ~Retinal_Object() { }
00078
00079
00086 virtual bool next() { return vars.next(); }
00087 virtual void reset() { vars.reset(); }
00088 virtual bool update() const {
00089
00090 theta = get_var("theta");
00091 cx = get_var("cx");
00092 cy = get_var("cy");
00093 scale = get_var("scale");
00094 offset = get_var("offset");
00095 default_act = default_activ();
00096
00097 return true;
00098 }
00099
00105 virtual Activity activation(Coordinate x, Coordinate y) const {
00106 return offset + scale *
00107 ((!active || !bounding_box.inside(x,y)) ? default_act : activ(x,y));
00108 }
00110
00111
00114
00115 virtual string stringrep() const;
00116
00118 virtual Retinal_Object* clone() const =0;
00119
00121 virtual void relink (const Retinal_Object* master)
00122 { if (master) vars.relink(&(master->vars)); }
00123
00125 bool get_active() const { return active; }
00127 void set_active(bool whether_active) { active=whether_active; }
00128
00130 const string& get_name() const { return name; }
00132 void set_name(const string& newname) { name=newname; }
00133
00135 const Variable get_var(const string& varname) const { return vars.get(varname); }
00136
00138 Variable* get_varptr(const string& varname) { return vars.getptr(varname); }
00139
00141 virtual Angle angle() const { return get_var("theta"); }
00142
00144 virtual Retinal_Object* find(const string& othername)
00145 { return (othername=="" || othername==name ? this : 0); }
00146
00148 void merge_vars(const VarMap& init_vars) { vars.merge(init_vars); }
00150
00151
00165 virtual Activity default_activation() const
00166 { return get_var("offset") + get_var("scale") * default_act; }
00167
00169 mutable BBox bounding_box;
00171
00172
00173 protected:
00174 friend class DefaultActivityAccumulator;
00175
00177 const void set_var_default(const string& varname, Variable val)
00178 { vars.set_default(varname,val); }
00179
00180 private:
00181 VarMap vars;
00182 bool active;
00183 string name;
00184 mutable Variable default_act,theta,cx,cy,scale,offset;
00185
00192 virtual Activity activ(Coordinate x, Coordinate y) const =0;
00193
00201 virtual Activity default_activ() const { return 0.0; }
00202
00203
00205 void operator= (const Retinal_Object &) { abort(); }
00206 };
00207
00208
00209
00210
00211 #ifndef NO_VALGEN_STRINGS
00212
00213 class RetinalObjectStringArgs {
00214 public:
00216 typedef std::map<string,string> DefaultsMap;
00218 typedef std::vector<string> ParamList;
00219
00226 RetinalObjectStringArgs( StringArgs arglist,
00227 VGenFactory<Retinal_Object::Variable>& vgf,
00228 DefaultsMap dm=DefaultsMap(),
00229 Retinal_Object* m=0)
00230 : args(arglist), defaults(dm), master(m), f(vgf), parser(args.p) { }
00231
00238 Retinal_Object::VarMap vars(const ParamList& params);
00239
00240
00244
00250 string get_default(const string& name) const {
00251 map<string,string>::const_iterator existing = defaults.find(name);
00252 return (existing == defaults.end() ? "" : (*existing).second);
00253 }
00254
00256 void set_default(const string& name, const string& value)
00257 { defaults[name]=value; }
00258
00260 void error(const string& s) const { parser.error(s); }
00261
00263 const string parsed_get_default(const string& name) const
00264 { return parser.parse(get_default(name)); }
00265
00267 const string parsed_next(const string& name)
00268 { return parser.parse(args.next(get_default(name))); }
00269
00271 Retinal_Object::Variable& parse(const string& s, Retinal_Object::Variable& x) const
00272 { return parser.parse(s,x); }
00274
00275
00276 private:
00278 inline void set_linked(const string& name, const string& value,
00279 Retinal_Object::VarMap& vars) {
00280 vars.set(name, f.create(StringArgs(parser,parser.parse(value)),
00281 (!master ? 0 : master->get_varptr(name)) ) );
00282 }
00283
00284 friend class RetinalObjectFactory;
00285
00286 StringArgs args;
00287 DefaultsMap defaults;
00288 Retinal_Object* master;
00289 VGenFactory<Retinal_Object::Variable>& f;
00290 const StringParser& parser;
00291 };
00292 #endif
00293
00294
00295
00296
00297
00298
00299
00309 class Retinal_Composite : public Retinal_Object {
00310 public:
00312 enum AccumulationType { Max, Min, Add, OneHot };
00313
00316 Retinal_Composite( const string& name_val, AccumulationType accum_type_i=Max,
00317 const VarMap& init_vars=VarMap())
00318 : Retinal_Object(name_val,init_vars),
00319 accum_type(accum_type_i), dominant_child(0) {
00320 set_var_default("size_scale",1.0);
00321 }
00322
00323 #ifndef NO_VALGEN_STRINGS
00324 RetinalObjectStringArgs::ParamList paramlist();
00325 Retinal_Composite( const string& name_val, RetinalObjectStringArgs& sa)
00326 : Retinal_Object(name_val), dominant_child(0) {
00327 sa.set_default("size_scale","1.0");
00328 merge_vars(sa.vars(paramlist()));
00329 accum_type = Retinal_Composite::AccumulationType(get_var("accum_type"));
00330 }
00331 #endif
00332
00333 Retinal_Composite(const Retinal_Composite& b)
00334 : Retinal_Object(b), children(b.children), accum_type(b.accum_type), dominant_child(0) {
00335 std::transform(ISEQ(children),children.begin(),mem_fun(&Retinal_Object::clone));
00336 }
00337
00338 virtual ~Retinal_Composite() { remove_all(); };
00340
00341
00344 virtual bool next();
00345 virtual void reset();
00346 virtual bool update() const;
00348
00349
00352
00354 virtual void add(Retinal_Object* obj) { children.push_back(obj); }
00355
00357 virtual bool is_empty() const { return (children.empty()); }
00358
00364 virtual Retinal_Object* find(const string& othername) {
00365 if (Retinal_Object::find(othername)) return this;
00366 for (iterator i=children.begin(); i!=children.end(); i++) {
00367 Retinal_Object* child_ptr = (*i)->find(othername);
00368 if (child_ptr) return child_ptr;
00369 }
00370 return 0;
00371 }
00372
00374 virtual void remove(const string& name="") {
00375 for (iterator i=children.begin(); i!=children.end(); i++)
00376 if (name=="" || ((*i)->get_name() == name)) {
00377 delete *i;
00378 children.erase(i);
00379 i--;
00380 }
00381 }
00382
00384 virtual void remove_all() { Generic::delete_contents(children); }
00385
00388 virtual const Retinal_Object& mostactive(Coordinate x, Coordinate y) const;
00389
00390
00392 Retinal_Object* operator[] (unsigned int idx) const { return children[idx]; }
00393 size_t size() const { return children.size(); }
00395
00396
00399 virtual string stringrep() const;
00400 virtual Retinal_Object* clone() const
00401 { return new Retinal_Composite(*this); };
00403
00404 protected:
00406 typedef std::vector<Retinal_Object*> ChildrenContainer;
00408 typedef ChildrenContainer::iterator iterator;
00410 typedef ChildrenContainer::const_iterator const_iterator;
00412 ChildrenContainer children;
00413
00415 AccumulationType accum_type;
00417 Activity accum_base() const;
00419 mutable Variable cosmt,sinmt,cx,cy,div_size;
00421 mutable Retinal_Object* dominant_child;
00422
00423 private:
00424 virtual Activity activ(Coordinate x, Coordinate y) const;
00425 virtual Activity default_activ() const;
00426 };
00427
00428
00429
00439 class Retinal_ManagedComposite : public Retinal_Composite {
00440 public:
00441 Retinal_ManagedComposite
00442 ( const string& name_val,
00443 int* min_distance_enforce, double* min_distance,
00444 int* max_distance_enforce, double* max_distance,
00445 AccumulationType accum_type_i=Max, const VarMap& init_vars=VarMap())
00446 : Retinal_Composite(name_val,accum_type_i,init_vars),
00447 min_dist_enforce(min_distance_enforce), min_dist(min_distance),
00448 max_dist_enforce(max_distance_enforce), max_dist(max_distance) { }
00449
00450 Retinal_ManagedComposite(const Retinal_ManagedComposite& b)
00451 : Retinal_Composite(b),
00452 min_dist_enforce(b.min_dist_enforce), min_dist(b.min_dist),
00453 max_dist_enforce(b.max_dist_enforce), max_dist(b.max_dist) { }
00454
00455 virtual bool next();
00456
00457 virtual Retinal_Object* clone() const
00458 { return new Retinal_ManagedComposite(*this); };
00459
00460 private:
00461 int* min_dist_enforce; double* min_dist;
00462 int* max_dist_enforce; double* max_dist;
00463
00464 bool distance_valid(const Retinal_Object& obj1, const Retinal_Object& obj2);
00465 bool accumulate_managed_next(bool val, Retinal_Object* r);
00466 };
00467
00468
00469
00476 class Retinal_AnchoredManagedComposite : public Retinal_ManagedComposite {
00477 public:
00478 Retinal_AnchoredManagedComposite
00479 ( const string& name_val,
00480 int* min_distance_enforce, double* min_distance,
00481 int* max_distance_enforce, double* max_distance,
00482 AccumulationType accum_type_i=Add, const VarMap& init_vars=VarMap() )
00483 : Retinal_ManagedComposite(name_val,
00484 min_distance_enforce, min_distance,
00485 max_distance_enforce, max_distance,
00486 accum_type_i, init_vars) { }
00487
00488 virtual string stringrep() const;
00489
00490 virtual Retinal_Object* clone() const
00491 { return new Retinal_AnchoredManagedComposite(*this); };
00492
00493 virtual Angle angle() const {
00494
00495 return ( (children.begin()==children.end()) ? 0 :
00496 children.back()->angle() );
00497 }
00498
00499 private:
00500 virtual Activity activ(Coordinate x, Coordinate y) const;
00501 };
00502
00503
00504
00505
00506
00507
00508
00510 template<randomgen_fnPtr random_fn=uniform_distribution>
00511 class Retinal_RandomNoise : public Retinal_Object {
00512 public:
00513 Retinal_RandomNoise( const string& name_val, const VarMap& init_vars=VarMap())
00514 : Retinal_Object(name_val, init_vars) { }
00515
00516 #ifndef NO_VALGEN_STRINGS
00517 RetinalObjectStringArgs::ParamList paramlist() {
00518 RetinalObjectStringArgs::ParamList p;
00519 p.push_back("scale");
00520 p.push_back("offset");
00521 return p;
00522 }
00523 Retinal_RandomNoise( const string& name_val, RetinalObjectStringArgs& sa)
00524 : Retinal_Object(name_val,sa.vars(paramlist())) { }
00525 #endif
00526
00527 virtual Activity activation(Coordinate, Coordinate) const {
00528 const Activity rad=scale*0.5;
00529 return random_fn(offset+rad,rad);
00530 }
00531
00532 virtual bool update() const {
00533 scale = get_var("scale");
00534 offset = get_var("offset");
00535
00536 return Retinal_Object::update();
00537 }
00538
00539 virtual Retinal_Object* clone() const
00540 { return new Retinal_RandomNoise(*this); }
00541
00542 private:
00543 mutable Variable scale,offset;
00544 virtual Activity activ(Coordinate, Coordinate) const { return 0; }
00545 };
00546
00547 typedef Retinal_RandomNoise<> Retinal_UniformRandomNoise;
00548
00549
00551 class Retinal_CircularGaussian : public Retinal_Object {
00552 public:
00553 Retinal_CircularGaussian( const string& name_val, const VarMap& init_vars=VarMap(),
00554 const Coordinate bound_multiplier=2.5)
00555 : Retinal_Object(name_val,init_vars), bound_mult(bound_multiplier) { }
00556
00557 #ifndef NO_VALGEN_STRINGS
00558 RetinalObjectStringArgs::ParamList paramlist();
00559 Retinal_CircularGaussian( const string& name_val, RetinalObjectStringArgs& sa,
00560 const Coordinate bound_multiplier=2.5)
00561 : Retinal_Object(name_val,sa.vars(paramlist())), bound_mult(bound_multiplier) { }
00562 #endif
00563
00564 Retinal_CircularGaussian(const Retinal_CircularGaussian& b)
00565 : Retinal_Object(b), bound_mult(b.bound_mult) { }
00566
00567 virtual bool update() const;
00568
00569 virtual Retinal_Object* clone() const
00570 { return new Retinal_CircularGaussian(*this); };
00571
00572 private:
00573 const Coordinate bound_mult;
00574 mutable Variable cx,cy,div_sigmasq;
00575 virtual Activity activ(Coordinate x, Coordinate y) const;
00576 };
00577
00578
00579
00581 class Retinal_Gaussian : public Retinal_Object {
00582 public:
00583 Retinal_Gaussian( const string& name_val, const VarMap& init_vars=VarMap(),
00584 const Coordinate bound_multiplier=2.5)
00585 : Retinal_Object(name_val,init_vars), bound_mult(bound_multiplier) { }
00586
00587 #ifndef NO_VALGEN_STRINGS
00588 RetinalObjectStringArgs::ParamList paramlist();
00589 Retinal_Gaussian( const string& name_val, RetinalObjectStringArgs& sa,
00590 const Coordinate bound_multiplier=2.5)
00591 : Retinal_Object(name_val,sa.vars(paramlist())), bound_mult(bound_multiplier) { }
00592 #endif
00593
00594 Retinal_Gaussian(const Retinal_Gaussian& b)
00595 : Retinal_Object(b), bound_mult(b.bound_mult) { }
00596
00597 virtual bool update() const;
00598
00599 virtual Retinal_Object* clone() const
00600 { return new Retinal_Gaussian(*this); };
00601
00602 private:
00603 const Coordinate bound_mult;
00604 mutable Variable cx,cy,cost,sint,div_xsigma,div_ysigma;
00605 virtual Activity activ(Coordinate x, Coordinate y) const;
00606 };
00607
00608
00609
00611 class Retinal_Rectangle : public Retinal_Object {
00612 public:
00613 Retinal_Rectangle( const string& name_val, const VarMap& init_vars=VarMap())
00614 : Retinal_Object(name_val,init_vars) { }
00615
00616 #ifndef NO_VALGEN_STRINGS
00617 RetinalObjectStringArgs::ParamList paramlist();
00618 Retinal_Rectangle( const string& name_val, RetinalObjectStringArgs& sa)
00619 : Retinal_Object(name_val,sa.vars(paramlist())) { }
00620 #endif
00621
00622 virtual bool update() const;
00623
00624 virtual Retinal_Object* clone() const
00625 { return new Retinal_Rectangle(*this); };
00626
00627 private:
00628 virtual Activity activ(Coordinate, Coordinate) const
00629 { return 1.0; }
00630 };
00631
00632
00633
00635 class Retinal_SineGrating : public Retinal_Object {
00636 public:
00637 Retinal_SineGrating( const string& name_val, const VarMap& init_vars=VarMap())
00638 : Retinal_Object(name_val,init_vars) { }
00639
00640 #ifndef NO_VALGEN_STRINGS
00641 RetinalObjectStringArgs::ParamList paramlist();
00642 Retinal_SineGrating( const string& name_val, RetinalObjectStringArgs& sa)
00643 : Retinal_Object(name_val,sa.vars(paramlist())) { }
00644 #endif
00645
00646 virtual bool update() const;
00647
00648 virtual Retinal_Object* clone() const
00649 { return new Retinal_SineGrating(*this); };
00650
00651 private:
00652 mutable Variable cost,sint,phase,freq;
00653 virtual Activity activ(Coordinate x, Coordinate y) const;
00654 };
00655
00656
00663 class Retinal_Gabor : public Retinal_Object {
00664 public:
00665 Retinal_Gabor( const string& name_val, const VarMap& init_vars=VarMap(),
00666 const Coordinate bound_multiplier=2.5)
00667 : Retinal_Object(name_val,init_vars), bound_mult(bound_multiplier) { }
00668
00669 #ifndef NO_VALGEN_STRINGS
00670 RetinalObjectStringArgs::ParamList paramlist();
00671 Retinal_Gabor( const string& name_val, RetinalObjectStringArgs& sa,
00672 const Coordinate bound_multiplier=2.5)
00673 : Retinal_Object(name_val), bound_mult(bound_multiplier) {
00674
00675 sa.set_default("ysigma", sa.get_default("xsigma"));
00676 sa.set_default("freq", "1.0");
00677 sa.set_default("phase", "0");
00678 merge_vars(sa.vars(paramlist()));
00679 }
00680 #endif
00681
00682 Retinal_Gabor(const Retinal_Gabor& b)
00683 : Retinal_Object(b), bound_mult(b.bound_mult) { }
00684
00685 virtual bool update() const;
00686
00687 virtual Retinal_Object* clone() const
00688 { return new Retinal_Gabor(*this); };
00689
00690 private:
00691 const Coordinate bound_mult;
00692 mutable Variable cx,cy,cost,sint,div_xsigmasq,div_ysigmasq,freq,phase;
00693 virtual Activity activ(Coordinate x, Coordinate y) const;
00694 };
00695
00696
00698 class Retinal_FuzzyLine : public Retinal_Object {
00699 public:
00700 Retinal_FuzzyLine( const string& name_val, const VarMap& init_vars=VarMap() )
00701 : Retinal_Object(name_val,init_vars) { }
00702
00703 #ifndef NO_VALGEN_STRINGS
00704 RetinalObjectStringArgs::ParamList paramlist();
00705 Retinal_FuzzyLine( const string& name_val, RetinalObjectStringArgs& sa)
00706 : Retinal_Object(name_val,sa.vars(paramlist())) { }
00707 #endif
00708
00709 virtual bool update() const;
00710
00711 virtual Retinal_Object* clone() const
00712 { return new Retinal_FuzzyLine(*this); };
00713
00714 private:
00715 mutable Variable cx,cy,centerw,cost,sint,div_ysigmasq;
00716 virtual Activity activ(Coordinate x, Coordinate y) const;
00717 };
00718
00719
00721 class Retinal_FuzzyRing : public Retinal_Object {
00722 public:
00723 Retinal_FuzzyRing( const string& name_val, const VarMap& init_vars=VarMap() )
00724 : Retinal_Object(name_val,init_vars) { }
00725
00726 #ifndef NO_VALGEN_STRINGS
00727 RetinalObjectStringArgs::ParamList paramlist();
00728 Retinal_FuzzyRing( const string& name_val, RetinalObjectStringArgs& sa)
00729 : Retinal_Object(name_val,sa.vars(paramlist())) { }
00730 #endif
00731
00732 virtual bool update() const;
00733
00734 virtual Retinal_Object* clone() const
00735 { return new Retinal_FuzzyRing(*this); };
00736
00737 private:
00738 mutable Variable cx,cy,centerw,div_ysigmasq,radius;
00739 virtual Activity activ(Coordinate x, Coordinate y) const;
00740 };
00741
00742
00744 class Retinal_PGM : public Retinal_Object {
00745 public:
00746 Retinal_PGM(const string& name_val, const string& filename_base,
00747 const VarMap& init_vars=VarMap() )
00748 : Retinal_Object(name_val,init_vars), basename(filename_base)
00749 { set_active(pgm_read(basename,image)); border=mat::edge_average(image); }
00750
00751 #ifndef NO_VALGEN_STRINGS
00752 RetinalObjectStringArgs::ParamList paramlist();
00753 Retinal_PGM( const string& name_val, RetinalObjectStringArgs& sa,
00754 Coordinate visible_width, Coordinate visible_height);
00755 #endif
00756
00757 Retinal_PGM(const Retinal_PGM& b)
00758 : Retinal_Object(b), basename(b.basename), image(b.image), border(b.border) { }
00759
00760 virtual bool update() const;
00761
00762 virtual Retinal_Object* clone() const
00763 { return new Retinal_PGM(*this); };
00764
00765 private:
00766 string basename;
00767 typedef MatrixType<Activity>::rectangular image_type;
00768 image_type image;
00769 mutable Variable border,cx,cy,cosmt,sinmt,div_size,xoff,yoff;
00770 virtual Activity activ(Coordinate x, Coordinate y) const;
00771 virtual Activity default_activ() const { return border; }
00772
00773 };
00774
00775
00776
00777
00778
00779
00780
00788 #ifndef NO_VALGEN_STRINGS
00789 class RetinalObjectFactory {
00790 public:
00791 virtual ~RetinalObjectFactory() { }
00792
00794 virtual Retinal_Object* create(const string& name,
00795 RetinalObjectStringArgs sa,
00796 Retinal_Composite* basecomposite,
00797 int eyewidth, int eyeheight) const {
00798 const string typenam = sa.parsed_next("type");
00799
00800 if (typenam=="Input_CircularGaussian" ) return new Retinal_CircularGaussian (name,sa);
00801 else if (typenam=="Input_Composite" ) return new Retinal_Composite (name,sa);
00802 else if (typenam=="Input_FuzzyLine" ) return new Retinal_FuzzyLine (name,sa);
00803 else if (typenam=="Input_FuzzyRing" ) return new Retinal_FuzzyRing (name,sa);
00804 else if (typenam=="Input_Gabor" ) return new Retinal_Gabor (name,sa);
00805 else if (typenam=="Input_Gaussian" ) return new Retinal_Gaussian (name,sa);
00806 else if (typenam=="Input_Rectangle" ) return new Retinal_Rectangle (name,sa);
00807 else if (typenam=="Input_PGM" ) return new Retinal_PGM (name,sa,eyewidth,eyeheight);
00808 else if (typenam=="Input_SineGrating" ) return new Retinal_SineGrating (name,sa);
00809 else if (typenam=="Input_UniformRandomNoise" ) return new Retinal_UniformRandomNoise (name,sa);
00810 else if (typenam=="Input_Clone" ) return new_Retinal_Clone (name,sa,basecomposite);
00811 else {
00812 sa.error("Unknown retinal object type: `"+typenam+"'");
00813 return 0;
00814 }
00815 }
00816
00817 private:
00820 Retinal_Object* new_Retinal_Clone( const string& name_val,
00821 RetinalObjectStringArgs& sa,
00822 Retinal_Composite* basecomposite) const {
00823 const string oldname = sa.parsed_next("clone_name");
00824 Retinal_Object* oldobj = basecomposite->find(oldname);
00825 if (!oldobj) return 0;
00826
00827
00828 Retinal_Object* newobj = oldobj->clone();
00829 if (name_val!="") newobj->set_name(name_val);
00830 if (sa.master) newobj->relink(sa.master);
00831
00832 newobj->merge_vars(sa.vars(RetinalObjectStringArgs::ParamList()));
00833 newobj->reset();
00834
00835 return newobj;
00836 }
00837 };
00838 #endif
00839
00840
00841 #endif