00001 #include <stdio.h>
00002 #include <math.h>
00003
00004 #include <MCOOP.h>
00005
00006 #include "Shared/Config.h"
00007 #include "Shared/mathutils.h"
00008 #include "Events/EventRouter.h"
00009 #include "cmv_region.h"
00010 #include "Vision.h"
00011 #include "Shared/WorldState.h"
00012 #include "Events/VisionEvent.h"
00013 #include "Shared/get_time.h"
00014 #include "Shared/SystemUtility.h"
00015 #include "VisionSerializer.h"
00016 #include "Wireless/Wireless.h"
00017
00018 Vision *vision=NULL;
00019
00020 using namespace mathutils;
00021 using namespace VisionEventNS;
00022
00023 Vision::Vision() : frameTimestamp(0UL), frame_count(0), cmap(NULL), tmap(NULL),
00024 rmap(NULL), rmap2(NULL), reg(NULL), width(0), height(0),
00025 max_width(0), max_height(0), max_runs(0), max_regions(0),
00026 num_colors(0), num_runs(0), num_regions(0), body_angle(0.0),
00027 body_height(100.0), vis_markers(0), obj_info(NULL),
00028 imageLayer(ofbkimageLAYER_H), vser(NULL)
00029 {
00030 initialize();
00031 vser=new VisionSerializer();
00032 }
00033
00034 void Vision::setCameraParams()
00035 {
00036 static OPrimitiveID fbkID = 0;
00037
00038 if(fbkID == 0){
00039 if(OPENR::OpenPrimitive("PRM:/r1/c1/c2/c3/i1-FbkImageSensor:F1", &fbkID) != oSUCCESS){
00040 cout << "Open FbkImageSensor failure." << endl;
00041 }
00042 }
00043
00044 longword wb=config->vision.white_balance;
00045 longword gain=config->vision.gain;
00046 longword shutter=config->vision.shutter_speed;
00047
00048
00049 OPrimitiveControl_CameraParam owb(wb);
00050 if(OPENR::ControlPrimitive(fbkID, oprmreqCAM_SET_WHITE_BALANCE, &owb, sizeof(owb), 0, 0) != oSUCCESS){
00051 cout << "CAM_SET_WHITE_BALANCE : Failed!" << endl;
00052 }
00053
00054
00055 OPrimitiveControl_CameraParam ogain(gain);
00056 if(OPENR::ControlPrimitive(fbkID, oprmreqCAM_SET_GAIN, &ogain, sizeof(ogain), 0, 0) != oSUCCESS){
00057 cout << "CAM_SET_GAIN : Failed!" << endl;
00058 }
00059
00060
00061 OPrimitiveControl_CameraParam oshutter(shutter);
00062 if(OPENR::ControlPrimitive(fbkID,oprmreqCAM_SET_SHUTTER_SPEED, &oshutter, sizeof(oshutter), 0, 0) != oSUCCESS){
00063 cout << "CAM_SET_SHUTTER_SPEED : Failed!" << endl;
00064 }
00065 }
00066
00067 void Vision::setResolution()
00068 {
00069 switch(config->vision.resolution) {
00070 case 2:
00071 width=88;
00072 height=72;
00073 imageLayer=ofbkimageLAYER_M;
00074 break;
00075 case 3:
00076 width=44;
00077 height=36;
00078 imageLayer=ofbkimageLAYER_L;
00079 break;
00080 default:
00081 width=176;
00082 height=144;
00083 imageLayer=ofbkimageLAYER_H;
00084 break;
00085 }
00086
00087 max_width = width;
00088 max_height = height;
00089
00090 int size = width * height;
00091 max_runs = size / MIN_EXP_RUN_LENGTH;
00092 max_regions = size / MIN_EXP_REGION_SIZE;
00093 size = max_width * max_height;
00094
00095 if (cmap!=NULL) { DeleteLarge(cmap); cmap=NULL; }
00096 NewLarge(&cmap,size+1);
00097 if(!cmap) {
00098 cout << "Couldn't allocate cmap\n\xFF" << endl;
00099 *((long *)0xDEADCC44)=1;
00100 }
00101 if (rmap!=NULL) { DeleteLarge(rmap); rmap=NULL; }
00102 NewLarge(&rmap,max_runs);
00103 if(!rmap) {
00104 cout << "Couldn't allocate rmap\n\xFF" << endl;
00105 *((long *)0xDEAD7744)=1;
00106 }
00107 if (rmap2!=NULL) { DeleteLarge(rmap2); rmap2=NULL; }
00108 NewLarge(&rmap2,max_runs);
00109 if(!rmap2) {
00110 cout << "Couldn't allocate rmap2\n\xFF" << endl;
00111 *((long *)0xDEAD7745)=1;
00112 }
00113 if (reg!=NULL) { DeleteLarge(reg); reg=NULL; }
00114 NewLarge(®,max_regions);
00115 if(!reg) {
00116 cout << "Couldn't allocate reg\n" << endl;
00117 *((long *)0xDEAD7E66)=1;
00118 }
00119 }
00120
00121 void Vision::setColors()
00122 {
00123 color_names.clear();
00124 num_colors =
00125 CMVision::LoadColorInformation(color,MAX_COLORS,config->vision.colors,
00126 color_names);
00127 if(num_colors > 0){
00128 printf(" Loaded %d colors.\n",num_colors);
00129 }else{
00130 printf(" ERROR: Could not load colors file:%s\n", config->vision.colors);
00131 }
00132
00133 int num_y,num_u,num_v;
00134 int size = 1 << (bits_y + bits_u + bits_v);
00135 num_y = 1 << bits_y;
00136 num_u = 1 << bits_u;
00137 num_v = 1 << bits_v;
00138
00139 memset(tmap,0,size*sizeof(cmap_t));
00140
00141 if(!CMVision::LoadThresholdFile(tmap,num_y,num_u,num_v,
00142 config->vision.thresh)) {
00143 printf(" ERROR: Could not load threshold file '%s'.\n",
00144 config->vision.thresh);
00145 }
00146 int remapped=CMVision::CheckTMapColors(tmap,num_y,num_u,num_v,num_colors,0);
00147 printf("remapped %d colors in threshold file '%s'\n",
00148 remapped, config->vision.thresh);
00149 }
00150
00151 int Vision::getColor(const char* color) {
00152 hash_map<const char*, int, hash<const char*>, hashcmp_eqstr>::iterator i;
00153 i=color_names.find(color);
00154 if (i==color_names.end()) return -1;
00155 return i->second;
00156 }
00157
00158 void Vision::initialize()
00159 {
00160 int result;
00161 int size = 1 << (bits_y + bits_u + bits_v);
00162
00163 obj_info=new ObjectInfo;
00164
00165 setResolution();
00166
00167
00168
00169 #ifdef PLATFORM_APERIOS
00170 result = NewRegion(size, reinterpret_cast<void**>(&tmap));
00171 if (result != sSUCCESS)
00172 printf("Unable to allocate tmap buffer of size %d\n",size);
00173 #else
00174 tmap = new cmap_t[size];
00175 #endif
00176
00177 setColors();
00178
00179
00180 initializeEventSpecs();
00181 setCameraParams();
00182 }
00183
00184 void Vision::initializeEventSpecs() {
00185 for(int event_idx=0; event_idx<NUM_VEVENTS; event_idx++) {
00186 vevent_spec[event_idx].listeners = 0;
00187 vevent_spec[event_idx].filter = 0;
00188 vevent_spec[event_idx].count = 0;
00189 vevent_spec[event_idx].cx = 0;
00190 vevent_spec[event_idx].cy = 0;
00191 vevent_spec[event_idx].present = false;
00192 }
00193 vevent_spec[RedBallSID].confidence=0.7;
00194 vevent_spec[PinkBallSID].confidence=0.7;
00195 vevent_spec[HandSID].confidence=0.5;
00196 vevent_spec[ThumbsupSID].confidence=0.45;
00197 vevent_spec[ThingSID].confidence=0.5;
00198 vevent_spec[MarkersSID].confidence=1.0001;
00199 }
00200
00201 void Vision::enableEvents(int vevent) {
00202 vevent_spec[vevent].listeners++;
00203 }
00204
00205 void Vision::enableEvents(int vevent, int noise) {
00206 enableEvents(vevent);
00207 setNoiseThreshold(vevent, noise);
00208 }
00209
00210 void Vision::disableEvents(int vevent) {
00211 if (vevent_spec[vevent].listeners>0)
00212 vevent_spec[vevent].listeners--;
00213 }
00214
00215 void Vision::setNoiseThreshold(int vevent, int noise) {
00216 vevent_spec[vevent].filter=noise;
00217 }
00218
00219 bool Vision::generateEvent(int vevent, double conf, int cenX, int cenY) {
00220 float cx, cy;
00221 if (conf>vevent_spec[vevent].confidence) {
00222 cx=(cenX-88.0)/88.0;
00223 cy=(cenY-72.0)/72.0;
00224 vevent_spec[vevent].cx=cx;
00225 vevent_spec[vevent].cy=cy;
00226
00227 if (vevent_spec[vevent].present) {
00228 vevent_spec[vevent].count=0;
00229 createEvent(EventBase::statusETID,vevent,cx,cy);
00230 } else {
00231 vevent_spec[vevent].count++;
00232 if (vevent_spec[vevent].count>vevent_spec[vevent].filter) {
00233 vevent_spec[vevent].count=0;
00234 vevent_spec[vevent].present=true;
00235 createEvent(EventBase::activateETID,vevent,cx,cy);
00236 }
00237 }
00238 return true;
00239 } else {
00240 if (!vevent_spec[vevent].present) {
00241 vevent_spec[vevent].count=0;
00242 } else {
00243 vevent_spec[vevent].count++;
00244 if (vevent_spec[vevent].count>vevent_spec[vevent].filter) {
00245 vevent_spec[vevent].count=0;
00246 vevent_spec[vevent].present=false;
00247 createEvent(EventBase::deactivateETID,vevent,0,0);
00248 } else {
00249 createEvent(EventBase::statusETID,vevent,cx,cy);
00250 }
00251 }
00252 return false;
00253 }
00254 }
00255
00256 bool Vision::close()
00257 {
00258 DeleteLarge(tmap);
00259 DeleteLarge(cmap);
00260 DeleteLarge(rmap);
00261 DeleteLarge(rmap2);
00262 DeleteLarge(reg);
00263
00264 tmap = NULL;
00265 cmap = NULL;
00266 rmap = NULL;
00267 rmap2 = NULL;
00268 reg = NULL;
00269
00270 max_width = 0;
00271 max_height = 0;
00272
00273 return(true);
00274 }
00275
00276 inline double pct_from_mean(double a,double b) {
00277 double s = (a - b) / (a + b);
00278 return fabs(s);
00279 }
00280
00281 int Vision::calcEdgeMask(int x1,int x2,int y1,int y2)
00282 {
00283 static const int boundary_pixel_size=1;
00284
00285 int edge;
00286
00287 edge = 0;
00288 if(x1 <= 0 +boundary_pixel_size) edge |= OFF_EDGE_LEFT ;
00289 if(x2 >= width -1-boundary_pixel_size) edge |= OFF_EDGE_RIGHT ;
00290 if(y1 <= 0 +boundary_pixel_size) edge |= OFF_EDGE_TOP ;
00291 if(y2 >= height-1-boundary_pixel_size) edge |= OFF_EDGE_BOTTOM;
00292
00293 return edge;
00294 }
00295
00296 int Vision::addToHistHorizStrip(int y, int x1, int x2, int *color_cnt)
00297 {
00298 int x;
00299
00300 y = bound(y ,0,height-1);
00301 x1 = bound(x1,0,width -1);
00302 x2 = bound(x2,0,width -1);
00303
00304 for(x=x1; x<=x2; x++) {
00305 color_cnt[getColorUnsafe(x,y)]++;
00306 }
00307
00308 return x2-x1+1;
00309 }
00310
00311 int Vision::addToHistVertStrip(int x, int y1, int y2, int *color_cnt)
00312 {
00313 int y;
00314
00315 x = bound(x ,0,width -1);
00316 y1 = bound(y1,0,height-1);
00317 y2 = bound(y2,0,height-1);
00318
00319 for(y=y1; y<=y2; y++) {
00320 color_cnt[getColorUnsafe(x,y)]++;
00321 }
00322
00323 return y2-y1+1;
00324 }
00325
00326 bool Vision::findHand(VObject *hand, VisionObjectInfo *hand_info)
00327 {
00328 if (vevent_spec[HandSID].listeners==0) return false;
00329
00330 color_class_state *skin;
00331 int n;
00332 double conf;
00333
00334 skin=&color[getColor("skin")];
00335
00336 region *or_reg;
00337
00338 or_reg=skin->list;
00339
00340 hand->confidence = 0.0;
00341
00342 if(!or_reg) return false;
00343
00344 n = 0;
00345 while(or_reg && n<10) {
00346 conf = ((double)or_reg->area/500);
00347
00348 if(conf > 1.0) conf = 1.0;
00349
00350 if(conf > hand->confidence) {
00351 hand->confidence = conf;
00352 hand_info->reg = or_reg;
00353 }
00354
00355 or_reg = or_reg->next;
00356 n++;
00357 }
00358
00359 return generateEvent (HandSID, hand->confidence, hand_info->reg->cen_x, hand_info->reg->cen_y);
00360 }
00361
00362 bool Vision::findBall(int ball_color, VObject *ball,VisionObjectInfo *ball_info) {
00363 if ((ball_color==getColor("red") && vevent_spec[RedBallSID].listeners==0)
00364 ||(ball_color==getColor("pink") && vevent_spec[PinkBallSID].listeners==0)) return false;
00365
00366 static const bool debug_ball = false;
00367 static const bool debug_conf = false;
00368
00369 static int frame_cnt=0;
00370 static const int print_period=1;
00371
00372 if(debug_ball)
00373 frame_cnt = (frame_cnt + 1) % print_period;
00374
00375 color_class_state *pink;
00376 int n;
00377 int w,h;
00378 double conf;
00379 double green_f;
00380
00381 pink=&color[ball_color];
00382
00383 region *or_reg;
00384
00385 or_reg=pink->list;
00386
00387 ball->confidence = 0.0;
00388
00389 if(!or_reg) return false;
00390
00391 n = 0;
00392 while(or_reg && n<10) {
00393 double conf0,conf_square_bbox,conf_area,conf_green,conf_area_bonus;
00394 double conf_red_v_area;
00395 int edge;
00396
00397 w = or_reg->x2 - or_reg->x1 + 1;
00398 h = or_reg->y2 - or_reg->y1 + 1;
00399
00400 edge = calcEdgeMask(or_reg);
00401 conf0 = (w >= 3) * (h >= 3) * (or_reg->area >= 7);
00402 conf_square_bbox =
00403 edge ?
00404 gaussian_with_min(pct_from_mean(w,h) / .6, 1e-3) :
00405 gaussian_with_min(pct_from_mean(w,h) / .2, 1e-3);
00406 conf_area =
00407 edge ?
00408 gaussian_with_min(pct_from_mean(M_PI*w*h/4.0,or_reg->area) / .6, 1e-3) :
00409 gaussian_with_min(pct_from_mean(M_PI*w*h/4.0,or_reg->area) / .2, 1e-3);
00410 conf_red_v_area = 1.0;
00411 conf_green = 1.0;
00412 conf_area_bonus = ((double)or_reg->area / 1000);
00413
00414 conf =
00415 conf0 *
00416 conf_square_bbox *
00417 conf_area *
00418 conf_red_v_area *
00419 conf_green +
00420 conf_area_bonus;
00421
00422 if(conf > 1.0) conf = 1.0;
00423
00424 if(debug_conf &&
00425 frame_cnt == 0) {
00426 printf("conf0 %g conf_square_bbox %g conf_area %g conf_area_bonus %g final %g\n",
00427 conf0,conf_square_bbox,conf_area,conf_area_bonus,conf);
00428 }
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503 if(conf > ball->confidence) {
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537 ball->confidence = conf;
00538
00539
00540
00541
00542
00543
00544
00545 ball_info->reg = or_reg;
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556 }
00557
00558 or_reg = or_reg->next;
00559 n++;
00560 }
00561 return (ball_color==getColor("red"))?generateEvent (RedBallSID, ball->confidence, ball_info->reg->cen_x, ball_info->reg->cen_y):generateEvent(PinkBallSID,ball->confidence,ball_info->reg->cen_x,ball_info->reg->cen_y);
00562 }
00563
00564 bool Vision::findThing(VObject *thing, VisionObjectInfo *thing_info) {
00565 if (vevent_spec[ThingSID].listeners==0) return false;
00566 thing->confidence=0;
00567 return generateEvent (ThingSID, thing->confidence, thing_info->reg->cen_x, thing_info->reg->cen_y);
00568 }
00569
00570 int Vision::isIn(region *r1, region *r2) {
00571 int r1w=r1->x2-r1->x1;
00572 int r1h=r1->y2-r1->y1;
00573
00574 if ((((r2->x1 < r1->x1) && (r2->x2 > r1->x1+r1w*0.75)) ||
00575 ((r2->x2 > r1->x2) && (r2->x1 < r1->x2-r1w*0.75)))
00576 && (((r2->y1 < r1->y1) && (r2->y2 > r1->y1+r1h*0.75)) ||
00577 ((r2->y2 > r1->y2) && (r2->y1 < r1->y2-r1h*0.75))))
00578 return 1;
00579 return 0;
00580 }
00581
00582 int Vision::isAdjacent(region *r1, region *r2) {
00583
00584 if (r1->x1 < r2->x1)
00585 return r1->x2>(r2->x1-2);
00586 else if (r1->x2 > r2->x2)
00587 return r1->x1<(r2->x2+2);
00588 return 0;
00589 }
00590
00591 int Vision::identifyMarker(int color1, int color2, int color3) {
00592 static const int marker_colors[27]={
00593 -1, -1, -1, MARKER_GOG, -1, MARKER_GOP, MARKER_GPG, MARKER_GPO, -1,
00594 -1, MARKER_OGO, MARKER_OGP, -1, -1, -1, MARKER_OPG, MARKER_OPO, -1,
00595 -1, MARKER_PGO, MARKER_PGP, MARKER_POG, -1, MARKER_POP, -1, -1, -1 };
00596 int markeridx=0;
00597 switch (color1) {
00598 case COLOR_ORANGE:
00599 markeridx+=9;
00600 break;
00601 case COLOR_PURPLE:
00602 markeridx+=18;
00603 break;
00604 }
00605 switch (color2) {
00606 case COLOR_ORANGE:
00607 markeridx+=3;
00608 break;
00609 case COLOR_PURPLE:
00610 markeridx+=6;
00611 break;
00612 }
00613 switch (color3) {
00614 case COLOR_ORANGE:
00615 markeridx+=1;
00616 break;
00617 case COLOR_PURPLE:
00618 markeridx+=2;
00619 break;
00620 }
00621 return marker_colors[markeridx];
00622 }
00623
00624 bool Vision::findMarkers() {
00625 if (vevent_spec[MarkersSID].listeners==0) return false;
00626
00627 const bool debug_markers = false;
00628 static int frame_cnt=0;
00629
00630 static const int print_period=30;
00631
00632 if(debug_markers)
00633 frame_cnt = (frame_cnt + 1) % print_period;
00634
00635 region *or_reg, *gr_reg, *pu_reg;
00636
00637 or_reg = color[getColor("orange")].list;
00638 gr_reg = color[getColor("bgreen")].list;
00639 pu_reg = color[getColor("purple")].list;
00640
00641 region* marker_regs[9];
00642 int num_regs=0;
00643
00644 for (int i=0; i<9; i++) marker_regs[i]=NULL;
00645
00646 while (num_regs<9) {
00647 int rarea=0;
00648
00649 if (or_reg) {
00650 marker_regs[num_regs]=or_reg;
00651 rarea=or_reg->area;
00652 }
00653 if (gr_reg && gr_reg->area>rarea) {
00654 marker_regs[num_regs]=gr_reg;
00655 rarea=gr_reg->area;
00656 }
00657 if (pu_reg && pu_reg->area>rarea) {
00658 marker_regs[num_regs]=pu_reg;
00659 rarea=pu_reg->area;
00660 }
00661 if (rarea<30) break;
00662
00663 switch(marker_regs[num_regs]->color) {
00664 case COLOR_ORANGE:
00665 or_reg=or_reg->next;
00666 break;
00667 case COLOR_BGREEN:
00668 gr_reg=gr_reg->next;
00669 break;
00670 case COLOR_PURPLE:
00671 pu_reg=pu_reg->next;
00672 break;
00673 }
00674 num_regs++;
00675 }
00676
00677 vis_markers=0;
00678
00679 for (int i=0; i<num_regs/3; i++) {
00680 int j;
00681 for (j=0; j<3; j++) markers[vis_markers].regs[j]=NULL;
00682 for (j=i; j<num_regs; j++)
00683 if (marker_regs[j]) break;
00684 markers[vis_markers].regs[0]=marker_regs[j];
00685 marker_regs[j]=NULL;
00686 for (j++; j<num_regs; j++) {
00687 if (marker_regs[j]) {
00688 if (isAdjacent(markers[vis_markers].regs[0],marker_regs[j])) {
00689 markers[vis_markers].regs[1]=marker_regs[j];
00690 marker_regs[j]=NULL;
00691 break;
00692 }
00693 }
00694 }
00695 if (!markers[vis_markers].regs[1]) continue;
00696 for (j=i+1; j<num_regs; j++) {
00697 if (marker_regs[j]) {
00698 if (isAdjacent(markers[vis_markers].regs[0],marker_regs[j])
00699 && isAdjacent(markers[vis_markers].regs[1],marker_regs[j])) {
00700 markers[vis_markers].regs[2]=markers[vis_markers].regs[1];
00701 markers[vis_markers].regs[1]=marker_regs[j];
00702 marker_regs[j]=NULL;
00703 break;
00704 } else if (isAdjacent(markers[vis_markers].regs[0],marker_regs[j])) {
00705 markers[vis_markers].regs[2]=markers[vis_markers].regs[1];
00706 markers[vis_markers].regs[1]=markers[vis_markers].regs[0];
00707 markers[vis_markers].regs[0]=marker_regs[j];
00708 marker_regs[j]=NULL;
00709 break;
00710 } else if (isAdjacent(markers[vis_markers].regs[1],marker_regs[j])) {
00711 markers[vis_markers].regs[2]=marker_regs[j];
00712 marker_regs[j]=NULL;
00713 break;
00714 }
00715 }
00716 }
00717 if (!markers[vis_markers].regs[2]) continue;
00718 if (markers[vis_markers].regs[0]->cen_x>markers[vis_markers].regs[2]->cen_x) {
00719 region* t_marker=markers[vis_markers].regs[0];
00720 markers[vis_markers].regs[0]=markers[vis_markers].regs[2];
00721 markers[vis_markers].regs[2]=t_marker;
00722 }
00723 markers[vis_markers].cen_x=markers[vis_markers].regs[1]->cen_x;
00724 markers[vis_markers].cen_y=markers[vis_markers].regs[1]->cen_y;
00725 markers[vis_markers].marker=identifyMarker(markers[vis_markers].regs[0]->color, markers[vis_markers].regs[1]->color,markers[vis_markers].regs[2]->color);
00726 if (markers[vis_markers].marker<0) continue;
00727
00728 if (debug_markers && frame_cnt==0)
00729 printf("marker colors: %d%d%d, id: %d\n",markers[vis_markers].regs[0]->color, markers[vis_markers].regs[1]->color, markers[vis_markers].regs[2]->color,markers[vis_markers].marker);
00730 vis_markers++;
00731 }
00732 for (int i=0; i<vis_markers; i++) {
00733 #ifdef PLATFORM_APERIOS
00734 VisionEvent *mevent=new VisionEvent(EventBase::statusETID,MarkersSID,
00735 markers[i].cen_x, markers[i].cen_y);
00736 mevent->setProperty(markers[i].marker);
00737 erouter->postEvent(mevent);
00738 #endif
00739 }
00740 return (vis_markers>0);
00741 }
00742
00743 bool Vision::findGesture(VisionObjectInfo *hand_info) {
00744 if (vevent_spec[ThumbsupSID].listeners==0) return false;
00745 if (hand_info->reg->cen_y>=144) return false;
00746
00747 int thumbsup=0, thumbx=0;
00748 int idx=hand_info->reg->run_start;
00749 int parent=rmap[idx].parent;
00750
00751 int i=0, y=0;
00752
00753 while (y<=hand_info->reg->cen_y) {
00754 int r=0;
00755 int xl=0;
00756 while (rmap[i].y<=y) {
00757 if (r>0) {
00758 if (rmap[i].parent==parent
00759 && rmap[i].width>5
00760 && rmap[i].x > xl+10) {
00761 thumbsup++;
00762 thumbx+=xl+(rmap[i].x-xl)/2;
00763 } else {
00764 xl=rmap[i].x+rmap[i].width;
00765 }
00766 } else if (r==0) {
00767 if (rmap[i].parent==parent
00768 && rmap[i].width>5) {
00769 r=i;
00770 xl=rmap[i].x+rmap[i].width;
00771 }
00772 }
00773 i++;
00774 if (i>=num_runs) break;
00775 }
00776 if (i>=num_runs) break;
00777 y=rmap[i].y;
00778 }
00779
00780 return generateEvent (ThumbsupSID, limitRange(thumbsup/20.00,0.0,1.0), hand_info->reg->cen_x, hand_info->reg->cen_y);
00781 }
00782
00783 void Vision::createEvent(unsigned int tid, unsigned int sid,
00784 float cenX, float cenY) {
00785 #ifdef PLATFORM_APERIOS
00786 erouter->postEvent(new VisionEvent((EventBase::EventTypeID_t)tid,sid,cenX,cenY));
00787 #endif
00788 }
00789
00790 bool Vision::runHighLevelVision(ObjectInfo *obj_info) {
00791 for(int obj_idx=0; obj_idx<NUM_VISION_OBJECTS; obj_idx++) {
00792 vobj_info[obj_idx].reg = NULL;
00793 }
00794
00795
00796
00797
00798 if (getColor("red")>=0)
00799 bool pball_exist=findBall(getColor("red"),&obj_info->pball,&vobj_info[PBALL]);
00800
00801
00802
00803
00804
00805
00806
00807 return true;
00808 }
00809
00810 bool Vision::thresholdImage(CMVision::image_idx<rgb> &img) {
00811 static rgb rgb_colors[MAX_COLORS];
00812 static bool initted=false;
00813
00814 if(!initted) {
00815 for(int color_idx=0; color_idx<MAX_COLORS; color_idx++)
00816 rgb_colors[color_idx]=color[color_idx].color;
00817 initted=true;
00818 }
00819
00820 CMVision::RgbToIndex(cmap,img.buf,width,height,rgb_colors,MAX_COLORS);
00821
00822 return true;
00823 }
00824
00825 bool Vision::thresholdImage(CMVision::image_yuv<const uchar> &img) {
00826 CMVision::ThresholdImageYUVPlanar<cmap_t,CMVision::image_yuv<const uchar>,const uchar,bits_y,bits_u,bits_v>(cmap,img,tmap);
00827
00828 return true;
00829 }
00830
00831
00832
00833 #ifdef ENABLE_JOIN_NEARBY
00834
00835
00836
00837 #endif
00838
00839
00840
00841 template<class image>
00842 bool Vision::runLowLevelVision(image &img)
00843 {
00844 static int frame_cnt=-1;
00845 frame_cnt++;
00846
00847 #ifdef ENABLE_JOIN_NEARBY
00848 int num_runs_old;
00849 #endif
00850 int max_area;
00851
00852 width = img.width;
00853 height = img.height;
00854
00855 thresholdImage(img);
00856 num_runs = CMVision::EncodeRuns(rmap,cmap,img.width,img.height,max_runs);
00857
00858 #ifdef ENABLE_JOIN_NEARBY
00859 num_runs_old = num_runs;
00860 #endif
00861
00862 #ifdef ENABLE_JOIN_NEARBY
00863 num_runs = CMVision::JoinNearbyRuns(rmap,rmap2,num_runs,width,height);
00864 #ifdef DEBUG_JOIN_PARANOID
00865 {
00866 bool ok=CMVision::CheckRuns(rmap2+1,num_runs-2,width,height);
00867 if(!ok) {
00868 printf("error in run data, consistency check failed\n");
00869 }
00870 }
00871 #endif
00872 #endif
00873
00874 #ifdef ENABLE_JOIN_NEARBY
00875 memcpy(rmap,rmap2,sizeof(*rmap2)*max_runs);
00876 #endif
00877
00878 #ifdef DEBUG_JOIN
00879 {
00880 bool ok=CMVision::CheckRuns(rmap+1,num_runs-2,width,height);
00881 if(!ok) {
00882 printf("error in run data, consistency check failed\n");
00883 }
00884 }
00885 #endif
00886
00887 CMVision::ConnectComponents(rmap,num_runs);
00888
00889 num_regions = CMVision::ExtractRegions(reg,max_regions,rmap,num_runs);
00890
00891
00892
00893
00894
00895 max_area = CMVision::SeparateRegions(color,num_colors,reg,num_regions);
00896 CMVision::SortRegions(color,num_colors,max_area);
00897
00898 CMVision::MergeRegions(color,num_colors,rmap);
00899
00900 for(int i=0; i<num_colors; i++)
00901 color[i].total_area = -1;
00902
00903 #ifdef CHECK_REGIONS
00904 {
00905 bool ok=CMVision::CheckRegions(color,num_colors,rmap);
00906 if(!ok) {
00907 printf("CheckRegions failed\n");
00908 }
00909 }
00910 #endif
00911
00912
00913 return(true);
00914 }
00915
00916 bool Vision::processFrame(const uchar *data_y, const uchar *data_u, const uchar *data_v, int width, int height, int skip) {
00917 frameTimestamp = get_time();
00918 frame_count++;
00919
00920 img.buf_y=data_y;
00921 img.buf_u=data_u;
00922 img.buf_v=data_v;
00923
00924 img.width=width;
00925 img.height=height;
00926
00927 img.row_stride=skip+width;
00928
00929 bool ok=true;
00930
00931 if(ok) ok=runLowLevelVision(img);
00932 if(ok) ok=runHighLevelVision(obj_info);
00933
00934 vser->serialize();
00935
00936 return ok;
00937 }
00938
00939 int WritePPM(char *filename,rgb *img,int width,int height)
00940 {
00941 FILE *out;
00942 int wrote;
00943
00944 out = fopen(filename,"wb");
00945 if(!out) return(0);
00946
00947 fprintf(out,"P6\n%d %d\n%d\n",width,height,255);
00948 wrote = fwrite(img,sizeof(rgb),width*height,out);
00949 fclose(out);
00950
00951 return(wrote);
00952 }
00953
00954 bool Vision::saveThresholdImage(char *filename)
00955 {
00956 rgb *buf;
00957 int wrote;
00958
00959 buf = new rgb[width * height];
00960 if(!buf) return(false);
00961
00962 CMVision::IndexToRgb<cmap_t,color_class_state>(buf,cmap,width,height,color,num_colors);
00963 wrote = WritePPM(filename,buf,width,height);
00964 delete(buf);
00965
00966 return(wrote > 0);
00967 }
00968
00969 vector3d Vision::getPixelDirection(double x, double y) {
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983 }
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997