aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorN.N. <sevyves@users.sourceforge.net>2009-06-02 19:35:21 +0000
committerN.N. <sevyves@users.sourceforge.net>2009-06-02 19:35:21 +0000
commitf1e12c6afbc0da3c1eb0b23319a971397c7c1630 (patch)
tree05b0cca401d5624c0f44a4daa988ad59606c8b42
parent9ba3548adf6df82ce6569949e33983c97ecaa098 (diff)
identify objects more precisely
svn path=/trunk/externals/pdp_opencv/; revision=11623
-rw-r--r--pdp_opencv_haarcascade-help.pd100
-rw-r--r--pdp_opencv_haarcascade.c130
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; i<MAX_MARKERS; i++)
+ {
+ if ( x->x_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; im<MAX_MARKERS; im++ )
+ {
+ if ( x->x_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; im<MAX_MARKERS; im++ )
+ {
+ // check if the object is already known
+ if ( sqrt( pow(center.x - x->x_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; im<MAX_MARKERS; im++ )
+ {
+ if ( x->x_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; i<MAX_MARKERS; i++)
+ {
+ x->x_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; i<MAX_MARKERS; i++ )
+ {
+ x->x_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