/******************************************************************** ** Image Component Library (ICL) ** ** ** ** Copyright (C) 2006-2013 CITEC, University of Bielefeld ** ** Neuroinformatics Group ** ** Website: www.iclcv.org and ** ** http://opensource.cit-ec.de/projects/icl ** ** ** ** File : ICLCV/demos/vector-tracker/vector-tracker.cpp ** ** Module : ICLCV ** ** Authors: Christof Elbrechter ** ** ** ** ** ** GNU LESSER GENERAL PUBLIC LICENSE ** ** This file may be used under the terms of the GNU Lesser General ** ** Public License version 3.0 as published by the ** ** ** ** Free Software Foundation and appearing in the file LICENSE.LGPL ** ** included in the packaging of this file. Please review the ** ** following information to ensure the license requirements will ** ** be met: http://www.gnu.org/licenses/lgpl-3.0.txt ** ** ** ** The development of this software was supported by the ** ** Excellence Cluster EXC 277 Cognitive Interaction Technology. ** ** The Excellence Cluster EXC 277 is a grant of the Deutsche ** ** Forschungsgemeinschaft (DFG) in the context of the German ** ** Excellence Initiative. ** ** ** ********************************************************************/ #include #include #include #include #include #include int error_counter = 0; int error_frames = 0; int frame_counter = 0; int error_counter_save = 0; void update_error_frames_A(){ error_counter_save = error_counter; } void update_error_frames_B(){ if(error_counter_save != error_counter){ error_frames++; } } struct InputGrabber : public MouseHandler, public Grabber, public Lockable { struct Blob{ unsigned int x; unsigned int y; unsigned int r; float vx; float vy; icl8u color[3]; int id; void set_new_id(int new_id){ if(id != new_id && id != -1){ error_counter++; } id = new_id; } void show(int idx=-1){ printf("Blob idx=%d pos=(%d,%d) r=%d vx=%f vy=%f color=(%d,%d,%d)\n", idx,x,y,r,vx,vy,color[0],color[1],color[2]); } }; static inline unsigned int distance(int x1, int y1, int x2, int y2){ return (unsigned int)round(::sqrt(pow(float(x1-x2),2)+pow(float(y1-y2),2))); } static inline void memline(icl8u *p, icl8u v, int len){ for(icl8u *c = p+len-1; c >= p; --c){ *c = v; } } template static inline void draw_blob(Img8u &image, Blob &b){ Channel8u c[N]; image.extractChannels(c); b.r +=2; { int rr = b.r*b.r; int h = image.getHeight(); int w = image.getWidth(); int ystart = iclMax(-b.r,-b.y); int yend = iclMin(b.r,h-b.y-1); for(int dy = ystart;dy<=yend;++dy){ int y = dy+b.y; int dx = (int)round(::sqrt(rr-dy*dy)); int xstart = iclMax((unsigned int)(0),b.x-dx); int xend = iclMin(b.x+dx,(unsigned int)(w-1)); for(unsigned int i=0;i= maxtrys){ throw(ICLException("Max trys reached!")); } }while(!ok(b)); b.id = -1; return b; } void setBlobCount(unsigned int nBlobs){ if(nBlobs < blobs.size()){ blobs.resize(nBlobs); }else{ try{ for(unsigned int i=blobs.size();i= image.getWidth()-b.r){ b.vx*=-1; cont = true; } if(b.y < b.r || b.y >= image.getHeight()-b.r){ b.vy*=-1; cont = true; } if(cont) continue; if(!ok(b,i)){ if(++t > maxtrys){ break; }else{ b = bSave; if(random(1.0) > 0.5){ b.vx*=-1; }else{ b.vy*=-1; } continue; } }else{ b.vx = clip(b.vx+(float)random(-maxdv,maxdv),-maxv, maxv); b.vy = clip(b.vy+(float)random(-maxdv,maxdv),-maxv, maxv); break; } } } } virtual const ImgBase *acquireImage(){ Mutex::Locker l(this); ICLASSERT_RETURN_VAL(getDesired() == depth8u,0); image.setSize(getDesired()); image.setFormat(getDesired()); image.clear(); iterate(); if(image.getChannels() == 1){ for(unsigned int i=0;i(image,blobs[i]); } }else if(image.getChannels() == 3){ for(unsigned int i=0;i(image,blobs[i]); } }else{ ERROR_LOG("invalid channel count! (allowed is 1 or 3 but found " << image.getChannels() << ")"); } return ℑ } private: Img8u image; vector blobs; unsigned int mingap; unsigned int minr; unsigned int maxr; float maxv; float maxdv; unsigned int maxtrys; icl8u blobcolor[3]; }; typedef std::vector vec; GUI gui; InputGrabber *grabber = 0; static std::vector > getCentersAndSizes(const Img8u &image){ static RegionDetector rd; rd.setConstraints(10,100000,1,255); const std::vector &bd = rd.detect(&image); std::vector > v; for(unsigned int i=0;i(x,x+3)); } return v; } void init(){ grabber = new InputGrabber(pa("-n").as()); grabber->useDesired(Size::VGA); grabber->useDesired(depth8u); grabber->useDesired(formatGray); gui << Draw().handle("image").minSize(32,24); gui << ( HBox() << Slider(0,100,pa("-sleeptime")).handle("Hsl").out("Vsl").label("sleeptime") << Button("off","on",true).out("Vlo").label("Show labels") ) << Show(); gui["image"].install(grabber); } void run(){ static ICLDrawWidget *w = *gui.get("image"); const ImgBase *image = grabber->grab(); std::vector > vVT = getCentersAndSizes(*(image->asImg())); w->setImage(image); if(vVT.size()){ std::vector normFactors(3); normFactors[0] = pa("-norm",0); normFactors[1] = pa("-norm",1); normFactors[2] = pa("-norm",2); static VectorTracker vt(3, // dim (x,y,size) 10000, // a large distance normFactors, // weights, *pa("-iam") == "new" ? VectorTracker::brandNew : VectorTracker::firstFree, pa("-thresh"), // threshold for optimized trivial assignment pa("-thresh") // whether to try trivial assignment ); vt.pushData(vVT); w->color(255,0,0); update_error_frames_A(); for(unsigned int i=0;isym(curr_x,curr_y,ICLDrawWidget::symCross); static bool &labelsOnFlag = gui.get("Vlo"); int blob_list_idx = ((InputGrabber*)grabber)->find_blob(curr_x,curr_y); if(blob_list_idx == -1){ ERROR_LOG("no blob at location found ???"); }else{ InputGrabber::Blob &b=((InputGrabber*)grabber)->get_blob((unsigned int)blob_list_idx); b.set_new_id(curr_id); } if(labelsOnFlag){ static char buf[100]; w->text(toStr(curr_id,buf),curr_x,curr_y,10); } } update_error_frames_B(); } frame_counter++; static FPSEstimator fps(10); w->color(255,255,255); char buf[400]; sprintf(buf,"blobs:%4d frames:%6d Error-frames:%4d Errors:%4d ",(unsigned int)vVT.size(),frame_counter,error_frames,error_counter); w->text(string(buf)+" "+fps.getFPSString().c_str(),5,5,-1,-1,8); w->render(); static int &sleepTime = gui.get("Vsl"); Thread::msleep(sleepTime); } int main(int n, char **ppc){ pa_explain ("-nblobs","number of blobs to use") ("-sleeptime","initial sleeptime value") ("-mingap","minimal distance between two blobs") ("-minr","minimal radius of blobs") ("-maxr","maxinal radius of blobs") ("-maxv","maxinal speed of blobs (in pixles per frame)") ("-maxdv","maximal acceleration of blobs") ("-thresh","position tracker threshold for trivial association step") ("-iam","one of {new,or free}") ("-norm","give norm factors for x and y distances and for the region size"); return ICLApp(n,ppc,"-norm(x-norm=1,y-norm=1,size-norm=1000) " "-id-generation-mode|-iam(mode=free) -nblobs|-n(int=30) -sleeptime|-s(msec=20) " "-mingap(int=3) -minr(int=10) -maxr(int=20) -maxv(int=10) -maxdv(int=2) " "-thresh(int=5)",init,run).exec(); }