00001 #include "BallDetectionGenerator.h"
00002 #include "Events/EventRouter.h"
00003 #include "Shared/Util.h"
00004 #include "Wireless/Wireless.h"
00005 #include "Shared/Config.h"
00006 #include "Events/VisionObjectEvent.h"
00007 #include "Shared/Profiler.h"
00008
00009 #include "Vision/SegmentedColorGenerator.h"
00010 #include "Vision/RegionGenerator.h"
00011 typedef RegionGenerator::region region;
00012 typedef SegmentedColorGenerator::color_class_state color_class_state;
00013
00014 BallDetectionGenerator::BallDetectionGenerator(unsigned int mysid, const RegionGenerator * rg, unsigned int colorIdx, unsigned int threshmapChan, unsigned int noiseFiltering, float confidence)
00015 : EventGeneratorBase("BallDetectionGenerator",EventBase::visObjEGID,mysid,rg->getGeneratorID(),rg->getSourceID(),EventBase::statusETID), clrIdx(colorIdx), tmIdx(threshmapChan), ball(), present(false), count(0), noiseThreshold(noiseFiltering), confidenceThreshold(confidence)
00016 {}
00017
00018 void
00019 BallDetectionGenerator::doEvent() {
00020 PROFSECTION("BallDetection::doEvent()",*mainProfiler);
00021 EventGeneratorBase::doEvent();
00022 if(event->getGeneratorID()!=getListenGeneratorID() || event->getSourceID()!=getListenSourceID())
00023 return;
00024
00025 const SegmentedColorFilterBankEvent * segev=dynamic_cast<const SegmentedColorFilterBankEvent*>(event);
00026 if(NULL==segev) {
00027 serr->printf("BallDetectionGenerator's event %s was not a SegmentedColorFilterBankEvent",event->getName().c_str());
00028 return;
00029 }
00030
00031 static const bool debug_ball = false;
00032 static const bool debug_conf = false;
00033
00034 static int frame_cnt=0;
00035 static const int print_period=1;
00036
00037 if(debug_ball)
00038 frame_cnt = (frame_cnt + 1) % print_period;
00039
00040 unsigned int layer=segev->getNumLayers()-config->vision.resolution-1;
00041 if(segev->getNumColors()<=clrIdx) {
00042 serr->printf("BallDetectionGenerator::clrIdx %d is invalid (only %d available)\n",clrIdx,segev->getNumColors());
00043 return;
00044 }
00045 if(segev->getNumChannels()<=tmIdx) {
00046 serr->printf("BallDetectionGenerator::tmIdx %d is invalid (only %d available)\n",tmIdx,segev->getNumChannels());
00047 return;
00048 }
00049 if(segev->getNumLayers()<=layer) {
00050 serr->printf("BallDetectionGenerator's selected layer %d is invalid (only %d available)\n",layer,segev->getNumLayers());
00051 return;
00052 }
00053 if(segev->getImage(layer,tmIdx)==NULL) {
00054 serr->printf("BallDetectionGenerator source's getImage returned NULL!\n");
00055 return;
00056 }
00057 const color_class_state& ballCCS=reinterpret_cast<const color_class_state*>(segev->getImage(layer,tmIdx))[clrIdx];
00058
00059 ball.confidence = 0;
00060 region * ball_region=NULL;
00061
00062 region * or_reg=ballCCS.list;
00063 if(!or_reg){
00064 count++;
00065
00066 float dim=segev->getWidth(layer);
00067
00068 float cw=segev->getWidth(layer)/dim;
00069 float ch=segev->getHeight(layer)/dim;
00070 unsigned int frame_number=segev->getFrameNumber();
00071 if (present && count>noiseThreshold) {
00072 count=0;
00073 present=false;
00074 createEvent(EventBase::deactivateETID,0,0,0,0,0,cw,ch,frame_number);
00075 }
00076 return;
00077 }
00078
00079 unsigned int n = 0;
00080 while(or_reg && n<NUM_CHECK) {
00081
00082
00083
00084
00085 int w = or_reg->x2 - or_reg->x1 + 1;
00086 int h = or_reg->y2 - or_reg->y1 + 1;
00087
00088 int edge = calcEdgeMask(or_reg->x1,or_reg->x2,or_reg->y1,or_reg->y2,segev->getWidth(layer),segev->getHeight(layer));
00089 float conf0 = (w >= 3) * (h >= 3) * (or_reg->area >= 7);
00090 float conf_square_bbox =
00091 edge ?
00092 gaussian_with_min(pct_from_mean(w,h) / .6f, 1e-3f) :
00093 gaussian_with_min(pct_from_mean(w,h) / .2f, 1e-3f);
00094 float conf_area =
00095 edge ?
00096 gaussian_with_min(pct_from_mean(((float)M_PI)*w*h/4.0f,or_reg->area) / .6f, 1e-3f) :
00097 gaussian_with_min(pct_from_mean(((float)M_PI)*w*h/4.0f,or_reg->area) / .2f, 1e-3f);
00098 float conf_area_bonus = or_reg->area / 1000.0f;
00099
00100 float conf = conf0*conf_square_bbox*conf_area + conf_area_bonus;
00101
00102 if(conf > 1.0) conf = 1.0f;
00103
00104 if(debug_conf && frame_cnt == 0) {
00105 printf("conf0 %g conf_square_bbox %g conf_area %g conf_area_bonus %g final %g\n",
00106 conf0,conf_square_bbox,conf_area,conf_area_bonus,conf);
00107 }
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183 if(conf > ball.confidence) {
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218 ball.confidence = conf;
00219
00220
00221
00222
00223
00224
00225
00226 ball_region = or_reg;
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237 }
00238
00239 or_reg = or_reg->next;
00240 n++;
00241 }
00242
00243
00244 testSendEvent(*segev,(float)ball.confidence,(int)ball_region->x1,(int)ball_region->x2,(int)ball_region->y1,(int)ball_region->y2,(int)ball_region->area);
00245 }
00246
00247 void
00248 BallDetectionGenerator::testSendEvent(const FilterBankEvent& ev, float conf, int regX1,int regX2,int regY1,int regY2, int area) {
00249 unsigned int layer=ev.getNumLayers()-config->vision.resolution-1;
00250
00251
00252 float dim=ev.getWidth(layer);
00253
00254
00255 float cw=config->vision.x_range;
00256 float ch=config->vision.y_range;
00257
00258
00259 float cx1=2.0f*regX1/dim - cw;
00260 float cx2=2.0f*(regX2+1)/dim - cw;
00261 float cy1=2.0f*regY1/dim - ch;
00262 float cy2=2.0f*(regY2+1)/dim - ch;
00263 float carea=4.0f*area/(dim*dim);
00264 unsigned int frame_number=ev.getFrameNumber();
00265
00266 if (conf>confidenceThreshold) {
00267 if (present) {
00268 count=0;
00269 createEvent(EventBase::statusETID,cx1,cx2,cy1,cy2,carea,cw,ch,frame_number);
00270 } else {
00271 count++;
00272 if (count>noiseThreshold) {
00273 count=0;
00274 present=true;
00275 createEvent(EventBase::activateETID,cx1,cx2,cy1,cy2,carea,cw,ch,frame_number);
00276 }
00277 }
00278 } else {
00279 if (!present) {
00280 count=0;
00281 } else {
00282 count++;
00283 if (count>noiseThreshold) {
00284 count=0;
00285 present=false;
00286 createEvent(EventBase::deactivateETID,0,0,0,0,carea,cw,ch,frame_number);
00287 } else {
00288 createEvent(EventBase::statusETID,cx1,cx2,cy1,cy2,carea,cw,ch,frame_number);
00289 }
00290 }
00291 }
00292 }
00293
00294 void
00295 BallDetectionGenerator::createEvent(EventBase::EventTypeID_t etid, float bbX1,float bbX2,float bbY1,float bbY2,float area,float rx,float ry,unsigned int frame) const {
00296 VisionObjectEvent vo(mySourceID,etid,bbX1,bbX2,bbY1,bbY2,area,rx,ry,frame);
00297 vo.setName(getName());
00298 erouter->postEvent(vo);
00299 }
00300
00301 int
00302 BallDetectionGenerator::calcEdgeMask(int x1,int x2,int y1,int y2, int width, int height) {
00303 static const int boundary_pixel_size=1;
00304
00305 int edge = 0;
00306 if(x1 <= 0 +boundary_pixel_size) edge |= OFF_EDGE_LEFT ;
00307 if(x2 >= width -1-boundary_pixel_size) edge |= OFF_EDGE_RIGHT ;
00308 if(y1 <= 0 +boundary_pixel_size) edge |= OFF_EDGE_TOP ;
00309 if(y2 >= height-1-boundary_pixel_size) edge |= OFF_EDGE_BOTTOM;
00310
00311 return edge;
00312 }
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326