From f1e12c6afbc0da3c1eb0b23319a971397c7c1630 Mon Sep 17 00:00:00 2001 From: "N.N." Date: Tue, 2 Jun 2009 19:35:21 +0000 Subject: identify objects more precisely svn path=/trunk/externals/pdp_opencv/; revision=11623 --- pdp_opencv_haarcascade-help.pd | 100 ++++++++++++++++++------------- pdp_opencv_haarcascade.c | 130 ++++++++++++++++++++++++++++++++++++----- 2 files changed, 174 insertions(+), 56 deletions(-) diff --git a/pdp_opencv_haarcascade-help.pd b/pdp_opencv_haarcascade-help.pd index 4fc5ed1..af0cbf9 100644 --- a/pdp_opencv_haarcascade-help.pd +++ b/pdp_opencv_haarcascade-help.pd @@ -1,4 +1,4 @@ -#N canvas 25 49 1247 801 10; +#N canvas 30 49 1247 801 10; #X obj -158 12 cnv 15 621 250 empty empty empty 20 12 0 14 -260097 -66577 0; #X obj 82 52 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1 @@ -29,59 +29,68 @@ #X obj -14 108 loadbang; #X text -85 41 playing a video file; #X text 112 50 Camera input; -#X obj -156 266 cnv 15 621 300 empty empty empty 20 12 0 14 -258113 +#X obj -158 272 cnv 15 621 350 empty empty empty 20 12 0 14 -258113 -66577 0; -#X obj -129 591 pdp_xv; -#X floatatom 25 511 5 0 0 0 - - -; -#X floatatom 74 512 5 0 0 0 - - -; -#X floatatom 121 510 5 0 0 0 - - -; -#X obj 21 465 route 0 1 2 3 4; -#X obj -129 418 pdp_opencv_haarcascade; -#X text 123 469 For each object detected; -#X obj 24 489 unpack 0 0 0; -#X floatatom 174 512 5 0 0 0 - - -; -#X floatatom 213 512 5 0 0 0 - - -; -#X floatatom 251 513 5 0 0 0 - - -; -#X obj 172 491 unpack 0 0 0; +#X obj -130 661 pdp_xv; +#X floatatom 25 583 5 0 0 0 - - -; +#X floatatom 74 584 5 0 0 0 - - -; +#X floatatom 121 582 5 0 0 0 - - -; +#X obj 21 537 route 0 1 2 3 4; +#X obj -129 490 pdp_opencv_haarcascade; +#X text 123 541 For each object detected; +#X obj 24 561 unpack 0 0 0; +#X floatatom 174 584 5 0 0 0 - - -; +#X floatatom 213 584 5 0 0 0 - - -; +#X floatatom 251 585 5 0 0 0 - - -; +#X obj 172 563 unpack 0 0 0; #X text -158 -62 pdp_opencv_haarscasccade : object recognition based on Haar's algorithm ( decision tree algorithm ); #X text -159 -37 used for face detection by default; -#X floatatom -56 443 5 0 0 0 - - -; -#X text -17 443 number of objects detected; -#X msg 6 282 load \$1; -#X obj 70 282 openpanel; -#X obj 138 281 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 +#X floatatom -56 515 5 0 0 0 - - -; +#X text -17 515 number of objects detected; +#X msg -27 309 load \$1; +#X obj 37 309 openpanel; +#X obj 105 308 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1 -1; #X text -162 -25 ( load haarscascase_frontalface_alt.xml ); -#X text 161 292 ( default haarscascase_frontalface_alt.xml ); -#X text 470 288 don't forget this step; -#X text 471 274 <-- WARNING : if you don't see any object detected +#X text 128 319 ( default haarscascase_frontalface_alt.xml ); +#X text 471 294 don't forget this step; +#X text 472 280 <-- WARNING : if you don't see any object detected ; -#X text 163 280 load an haar's decision tree; -#X msg 25 311 mode \$1; -#X obj 83 311 hradio 15 1 0 2 empty empty empty 0 -8 0 10 -262144 -1 +#X text 130 307 load an haar's decision tree; +#X msg -8 338 mode \$1; +#X obj 50 338 hradio 15 1 0 2 empty empty empty 0 -8 0 10 -262144 -1 -1 0; -#X msg 34 338 min_size \$1; -#X floatatom 114 340 5 0 0 0 - - -; -#X floatatom 317 512 5 0 0 0 - - -; -#X floatatom 356 512 5 0 0 0 - - -; -#X floatatom 394 513 5 0 0 0 - - -; -#X obj 315 491 unpack 0 0 0; -#X text 124 311 mode 0 or 1 ( default 0 ); -#X text 154 338 minimum size of object ( default 30 ); -#X floatatom 152 363 5 0 0 0 - - -; -#X text 190 362 minimum neighbours of object ( default 2 ); -#X msg 46 362 min_neighbors \$1; -#X floatatom 160 389 5 0 0 0 - - -; -#X text 198 388 scale used for recognition ( default 1.1 ); -#X text 315 527 Xcenter Ycenter Radius; -#X text 171 527 Xcenter Ycenter Radius; -#X text 25 527 Xcenter Ycenter Radius; -#X msg 54 388 scale_factor \$1; +#X msg 1 365 min_size \$1; +#X floatatom 81 367 5 0 0 0 - - -; +#X floatatom 317 584 5 0 0 0 - - -; +#X floatatom 356 584 5 0 0 0 - - -; +#X floatatom 394 585 5 0 0 0 - - -; +#X obj 315 563 unpack 0 0 0; +#X text 91 338 mode 0 or 1 ( default 0 ); +#X text 121 365 minimum size of object ( default 30 ); +#X floatatom 119 390 5 0 0 0 - - -; +#X text 157 389 minimum neighbours of object ( default 2 ); +#X msg 13 389 min_neighbors \$1; +#X floatatom 127 416 5 0 0 0 - - -; +#X text 165 415 scale used for recognition ( default 1.1 ); +#X text 315 599 Xcenter Ycenter Radius; +#X text 171 599 Xcenter Ycenter Radius; +#X text 25 599 Xcenter Ycenter Radius; +#X msg 21 415 scale_factor \$1; #X obj -68 228 hsl 128 15 0 500 0 0 empty empty empty -2 -8 0 10 -262144 -1 -1 0 1; #X text -158 -9 Written by Lluis Gomez i Bigorda ( lluisgomez@hangar.org ); +#X obj -129 687 route press; +#X msg -79 661 cursor 1; +#X msg 40 439 ftolerance \$1; +#X floatatom 130 440 5 0 0 0 - - -; +#X msg -58 209 162; +#X msg 45 463 clear; +#X text 90 464 clear history; +#X text 171 447 temporarily ( default 5 ); +#X text 171 435 number of frames where an object can disappear; #X connect 1 0 2 0; #X connect 2 0 4 0; #X connect 3 0 4 0; @@ -105,10 +114,12 @@ on Haar's algorithm ( decision tree algorithm ); #X connect 21 0 20 0; #X connect 22 0 21 0; #X connect 22 0 15 0; +#X connect 26 0 71 0; #X connect 30 0 33 0; #X connect 30 1 37 0; #X connect 30 2 57 0; #X connect 31 0 26 0; +#X connect 31 0 72 0; #X connect 31 1 40 0; #X connect 31 2 30 0; #X connect 33 0 27 0; @@ -132,3 +143,8 @@ on Haar's algorithm ( decision tree algorithm ); #X connect 63 0 68 0; #X connect 68 0 31 0; #X connect 69 0 13 1; +#X connect 72 0 26 0; +#X connect 73 0 31 0; +#X connect 74 0 73 0; +#X connect 75 0 69 0; +#X connect 76 0 31 0; diff --git a/pdp_opencv_haarcascade.c b/pdp_opencv_haarcascade.c index 48382a7..1c1edc6 100644 --- a/pdp_opencv_haarcascade.c +++ b/pdp_opencv_haarcascade.c @@ -34,6 +34,8 @@ #include "cv.h" #endif +#define MAX_MARKERS 50 + const char* default_cascade ="./haarcascade_frontalface_alt.xml"; typedef struct pdp_opencv_haarcascade_struct @@ -45,6 +47,11 @@ typedef struct pdp_opencv_haarcascade_struct t_outlet *x_outlet1; t_outlet *x_dataout; t_atom rlist[4]; + int x_xmark[MAX_MARKERS]; + int x_ymark[MAX_MARKERS]; + int x_found[MAX_MARKERS]; + int x_ftolerance; + int x_packet0; int x_packet1; int x_dropped; @@ -68,7 +75,30 @@ typedef struct pdp_opencv_haarcascade_struct } t_pdp_opencv_haarcascade; +static int pdp_opencv_haarcascade_mark(t_pdp_opencv_haarcascade *x, t_floatarg fx, t_floatarg fy ) +{ + int i; + + if ( ( fx < 0.0 ) || ( fx > x->x_width ) || ( fy < 0 ) || ( fy > x->x_height ) ) + { + return -1; + } + for ( i=0; ix_xmark[i] == -1 ) + { + x->x_xmark[i] = (int)fx; + x->x_ymark[i] = (int)fy; + x->x_found[i] = x->x_ftolerance; + post( "pdp_opencv_haarcascade : inserted point %d (%d,%d)", i, x->x_xmark[i], x->x_ymark[i] ); + return i; + } + } + + post( "pdp_opencv_haarcascade : max markers reached" ); + return -1; +} static void pdp_opencv_haarcascade_process_rgb(t_pdp_opencv_haarcascade *x) { @@ -76,7 +106,7 @@ static void pdp_opencv_haarcascade_process_rgb(t_pdp_opencv_haarcascade *x) short int *data = (short int *)pdp_packet_data(x->x_packet0); t_pdp *newheader = pdp_packet_header(x->x_packet1); short int *newdata = (short int *)pdp_packet_data(x->x_packet1); - int i; + int i, im; if ((x->x_width != (t_int)header->info.image.width) || (x->x_height != (t_int)header->info.image.height)) @@ -148,25 +178,67 @@ static void pdp_opencv_haarcascade_process_rgb(t_pdp_opencv_haarcascade *x) else outlet_float(x->x_outlet1, 0.0); + for ( im=0; imx_xmark[im] != -1.0 ) + { + x->x_found[im]--; + } + } + for( i = 0; i < (faces ? faces->total : 0); i++ ) { + int oi, found; + CvRect* r = (CvRect*)cvGetSeqElem( faces, i ); CvPoint center; int radius; center.x = cvRound((r->x + r->width*0.5)*scale); center.y = cvRound((r->y + r->height*0.5)*scale); radius = cvRound((r->width + r->height)*0.25*scale); - cvCircle( x->img, center, radius, colors[i%8], 3, 8, 0 ); + + found = 0; + oi = -1; + for ( im=0; imx_xmark[im], 2 ) + pow(center.y - x->x_ymark[im], 2 ) ) <= radius ) + { + oi=im; + found=1; + x->x_found[im] = x->x_ftolerance; + x->x_xmark[im] = center.x; + x->x_ymark[im] = center.y; + break; + } + } + // new object detected + if ( !found ) + { + oi = pdp_opencv_haarcascade_mark(x, center.x, center.y ); + } char tindex[4]; - sprintf( tindex, "%d", i ); + sprintf( tindex, "%d", oi ); + cvCircle( x->img, center, radius, colors[oi%8], 3, 8, 0 ); cvPutText( x->img, tindex, center, &x->font, CV_RGB(255,255,255)); - SETFLOAT(&x->rlist[0], i); + SETFLOAT(&x->rlist[0], oi); SETFLOAT(&x->rlist[1], center.x); SETFLOAT(&x->rlist[2], center.y); SETFLOAT(&x->rlist[3], radius); outlet_list( x->x_dataout, 0, 4, x->rlist ); } + // delete lost objects + for ( im=0; imx_found[im] < 0 ) + { + x->x_xmark[im] = -1.0; + x->x_ymark[im] = -1,0; + x->x_found[im] = x->x_ftolerance; + post( "deleted point %d", im ); + } + } } cvReleaseImage( &gray ); @@ -198,6 +270,36 @@ static void pdp_opencv_haarcascade_min_neighbors(t_pdp_opencv_haarcascade *x, t_ if (f>=1) x->min_neighbors = (int)f; } +static void pdp_opencv_haarcascade_ftolerance(t_pdp_opencv_haarcascade *x, t_floatarg f) +{ + if (f>=1) x->x_ftolerance = (int)f; +} + +static void pdp_opencv_haarcascade_delete(t_pdp_opencv_haarcascade *x, t_floatarg findex ) +{ + int i; + + if ( ( findex < 1.0 ) || ( findex > 10 ) ) + { + return; + } + + x->x_xmark[(int)findex-1] = -1; + x->x_ymark[(int)findex-1] = -1; +} + +static void pdp_opencv_haarcascade_clear(t_pdp_opencv_haarcascade *x ) +{ + int i; + + for ( i=0; ix_xmark[i] = -1; + x->x_ymark[i] = -1; + x->x_found[i] = x->x_ftolerance; + } +} + static void pdp_opencv_haarcascade_load(t_pdp_opencv_haarcascade *x, t_symbol *filename) { x->cascade = (CvHaarClassifierCascade*)cvLoad( filename->s_name, 0, 0, 0 ); @@ -221,13 +323,6 @@ static void pdp_opencv_haarcascade_process(t_pdp_opencv_haarcascade *x) { int encoding; t_pdp *header = 0; - char *parname; - unsigned pi; - int partype; - float pardefault; - t_atom plist[2]; - t_atom tlist[2]; - t_atom vlist[2]; /* check if image data packets are compatible */ if ( (header = pdp_packet_header(x->x_packet0)) @@ -282,7 +377,7 @@ t_class *pdp_opencv_haarcascade_class; void *pdp_opencv_haarcascade_new(t_floatarg f) { - int i; + int i; t_pdp_opencv_haarcascade *x = (t_pdp_opencv_haarcascade *)pd_new(pdp_opencv_haarcascade_class); @@ -304,6 +399,13 @@ void *pdp_opencv_haarcascade_new(t_floatarg f) x->min_neighbors = 2; x->mode = 0; x->min_size = 30; + x->x_ftolerance = 5; + + for ( i=0; ix_xmark[i] = -1; + x->x_ymark[i] = -1; + } x->cascade = (CvHaarClassifierCascade*)cvLoad( default_cascade, 0, 0, 0 ); if( !x->cascade ) @@ -341,8 +443,8 @@ void pdp_opencv_haarcascade_setup(void) class_addmethod(pdp_opencv_haarcascade_class, (t_method)pdp_opencv_haarcascade_min_neighbors, gensym("min_neighbors"), A_FLOAT, A_NULL ); class_addmethod(pdp_opencv_haarcascade_class, (t_method)pdp_opencv_haarcascade_mode, gensym("mode"), A_FLOAT, A_NULL ); class_addmethod(pdp_opencv_haarcascade_class, (t_method)pdp_opencv_haarcascade_min_size, gensym("min_size"), A_FLOAT, A_NULL ); - - + class_addmethod(pdp_opencv_haarcascade_class, (t_method)pdp_opencv_haarcascade_ftolerance, gensym("ftolerance"), A_FLOAT, A_NULL ); + class_addmethod(pdp_opencv_haarcascade_class, (t_method)pdp_opencv_haarcascade_clear, gensym("clear"), A_NULL ); } #ifdef __cplusplus -- cgit v1.2.1