diff options
author | N.N. <sevyves@users.sourceforge.net> | 2009-08-29 21:43:37 +0000 |
---|---|---|
committer | N.N. <sevyves@users.sourceforge.net> | 2009-08-29 21:43:37 +0000 |
commit | 5f48da1ffe239dc989c4561668c86a1852f7e0cf (patch) | |
tree | 53ba6ddb52ce93dbdf8cfd9a2a932d3330e3f85f | |
parent | 9ccaf6ebab9d445e5b8ed04f58956cacb7ac7467 (diff) |
updated opencv_lk with delaunay
svn path=/trunk/externals/pix_opencv/; revision=12139
-rw-r--r-- | INSTALL | 33 | ||||
-rwxr-xr-x | pix_opencv_lk-help.pd | 93 | ||||
-rwxr-xr-x | pix_opencv_lk.cc | 487 | ||||
-rwxr-xr-x | pix_opencv_lk.h | 18 |
4 files changed, 551 insertions, 80 deletions
@@ -7,23 +7,25 @@ Download the package here : [[http://hangar.org/wikis/lab/pd/pdp_opencv-0.1a.tar (actually only tested in GNU/Linux Ubuntu) -unpack it :: +first install opencv development packages, +on ubuntu : - tar xzvf pix_opencv-0.1a.tar.gz +apt-get install libcv-dev +apt-get install libcvaux-dev +apt-get install libhighgui-dev -cd into the library folder :: +get the _SOURCES_ of the pd you are using +and of the GEM that you are loading +( it might not work if the version +is different ) - cd pix_opencv - -or +cd into the package folder :: - cd pdp_opencv + cd pix_opencv edit the Makefile to fit your system and sources folders: -for pix_opencv edit the Makefile and change the values for PD_DIR and GEM_DIR variables - -for pdp_opencv edit the Makefile.config and change the values for OPENCV_CPPFLAGS, PD_CPPFLAGS, PDP_CFLAGS variables +edit the Makefile and change the values for PD_DIR and GEM_DIR variables then, compile it :: @@ -38,20 +40,23 @@ and copy the .pd_linux to your externals folder :: ===== MAC OSX (intel and powerPC) ===== -(This is only for pix_opencv Actually there is no MACOSX makefile for pdp_opencv.) - first install openCV MacOS framework download openCV private framework from http://www.ient.rwth-aachen.de/cms/software/opencv/ copy the provided OpenCV.framework folder in your /System/Library/Frameworks/ directory :: cp -Rf /Volumes/OpenCV\ Private\ Framework/OpenCV.framework /System/Library/Frameworks/ -cd into the library folder :: +get the _SOURCES_ of the pd you are using +and of the GEM that you are loading +( it might not work if the version +is different ) + +cd into the package folder :: cd pix_opencv edit the Makefile to fit your system and sources folders: -for pix_opencv edit the Makefile and change the values for PD_DIR and GEM_DIR variables +edit the Makefile and change the values for PD_DIR and GEM_DIR variables then, compile it :: diff --git a/pix_opencv_lk-help.pd b/pix_opencv_lk-help.pd index 4b67d7c..f77ff9b 100755 --- a/pix_opencv_lk-help.pd +++ b/pix_opencv_lk-help.pd @@ -1,4 +1,4 @@ -#N canvas 288 90 1192 685 10; +#N canvas 3 105 1192 685 10; #X obj 396 -37 gemhead; #X obj 212 501 pix_texture; #X obj 212 529 square 2; @@ -37,7 +37,7 @@ #X obj 213 432 square 2; #X obj 325 71 translateXYZ -2 0 0; #X obj 326 100 separator; -#X obj 340 179 cnv 15 600 400 empty empty empty 20 12 0 14 -24198 -66577 +#X obj 340 180 cnv 15 600 450 empty empty empty 20 12 0 14 -24198 -66577 0; #X obj 511 -66 bng 25 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 -1; @@ -57,8 +57,8 @@ #X obj 326 126 translateXYZ 4 0 0; #X obj 580 26 loadbang; #X msg 528 50 colorspace RGBA; -#X floatatom 488 416 5 0 0 0 - - -; -#X text 523 415 window size; +#X floatatom 488 520 5 0 0 0 - - -; +#X text 523 519 window size; #X obj 553 262 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1; #X msg 468 260 nightmode \$1; @@ -72,38 +72,54 @@ #X text 511 181 init point detections; #X floatatom 631 235 5 0 0 0 - - -; #X obj 576 233 / 1000; -#X msg 481 285 mark \$1 \$2; -#X msg 492 311 delete \$1; -#X text 563 311 delete a marker; -#X msg 503 337 clear; -#X text 551 338 delete all markers; -#X msg 510 364 maxmove \$1; -#X text 624 364 max movement of a marker ( default 5 pisels ); -#X floatatom 586 366 5 0 0 0 - - -; +#X msg 494 328 mark \$1 \$2; +#X msg 508 349 delete \$1; +#X text 579 349 delete a marker; +#X msg 516 369 clear; +#X text 564 370 delete all markers; +#X msg 522 389 maxmove \$1; +#X text 636 389 max movement of a marker ( default 5 pisels ); +#X floatatom 598 391 5 0 0 0 - - -; #X text 763 234 set quality ( default 100 ); #X msg 671 233 100; #X obj 704 233 loadbang; -#X obj 480 504 unpack f f; -#X floatatom 481 529 5 0 0 0 - - -; -#X floatatom 539 530 5 0 0 0 - - -; -#X text 482 545 X; -#X text 537 546 Y; -#X obj 479 478 route 1 2 3 4 5 6 7 8 9 10; -#X text 651 479 position of each marked point; -#X obj 377 428 pix_opencv_lk; -#X text 23 21 written by Lluis Gomez i Bigorda ( lluisgomez@hangar.org -) and Yves Degoyon ( ydegoyon@gmail.com ); -#X text 23 9 pix_opencv_lk : contour most significant points detection -; +#X obj 485 575 unpack f f; +#X floatatom 486 600 5 0 0 0 - - -; +#X floatatom 544 601 5 0 0 0 - - -; +#X text 487 616 X; +#X text 542 617 Y; +#X obj 484 549 route 1 2 3 4 5 6 7 8 9 10; +#X text 650 498 position of each marked point; +#X obj 378 538 pix_opencv_lk; #X obj 952 123 gemmouse; #X obj 1008 230 f; #X obj 978 229 f; #X obj 1022 201 t b b; #X obj 978 257 pack f f; -#X text 560 286 mark x y : mark a point to track ( max points : 10 +#X text 573 329 mark x y : mark a point to track ( max points : 10 ); #X obj 998 151 route 1; #X msg 1019 176 bang; +#X msg 477 283 mark all; +#X msg 487 304 mark none; +#X text 540 284 mark all points; +#X text 557 305 reset all markers; +#X text 622 433 make a delaunay with all points; +#X msg 542 433 delaunay on; +#X msg 550 453 delaunay off; +#X text 651 466 make a delaunay with point 1 and a tolerance of 50 +( all points which color is in that range will be included in the delaunay) +; +#X msg 552 478 pdelaunay 1 50; +#X msg 533 409 ftolerance \$1; +#X floatatom 625 409 5 0 0 0 - - -; +#X text 665 409 frame tolerance for point identification ( default +: 5 ); +#X text 44 11 written by Lluis Gomez i Bigorda ( lluisgomez@hangar.org +) and Yves Degoyon ( ydegoyon@gmail.com ); +#X text 43 -1 Corner points detection based on Shi and Tomasi; +#X text 43 -13 pix_opencv_lk : Lukas-Kanade corner points tracking +; #X connect 0 0 21 0; #X connect 1 0 2 0; #X connect 4 0 5 0; @@ -150,13 +166,20 @@ #X connect 57 0 52 0; #X connect 59 0 1 0; #X connect 59 1 57 0; -#X connect 62 0 64 1; -#X connect 62 1 63 1; -#X connect 62 2 68 0; -#X connect 63 0 66 1; -#X connect 64 0 66 0; -#X connect 65 0 64 0; -#X connect 65 1 63 0; -#X connect 66 0 41 0; -#X connect 68 0 69 0; -#X connect 69 0 65 0; +#X connect 60 0 62 1; +#X connect 60 1 61 1; +#X connect 60 2 66 0; +#X connect 61 0 64 1; +#X connect 62 0 64 0; +#X connect 63 0 62 0; +#X connect 63 1 61 0; +#X connect 64 0 41 0; +#X connect 66 0 67 0; +#X connect 67 0 63 0; +#X connect 68 0 59 0; +#X connect 69 0 59 0; +#X connect 73 0 59 0; +#X connect 74 0 59 0; +#X connect 76 0 59 0; +#X connect 77 0 59 0; +#X connect 78 0 77 0; diff --git a/pix_opencv_lk.cc b/pix_opencv_lk.cc index 3217dcb..65daa24 100755 --- a/pix_opencv_lk.cc +++ b/pix_opencv_lk.cc @@ -1,4 +1,4 @@ -//////////////////////////////////////////////////////// + // // GEM - Graphics Environment for Multimedia // @@ -52,6 +52,10 @@ pix_opencv_lk :: pix_opencv_lk() quality = 0.1; min_distance = 10; maxmove = 8; + markall = 0; + ftolerance = 5; + delaunay = -1; + threshold = -1; for ( i=0; i<MAX_MARKERS; i++ ) { @@ -97,6 +101,7 @@ void pix_opencv_lk :: processRGBAImage(imageStruct &image) { int i, k; int im; + int marked; if ((this->comp_xsize!=image.xsize)&&(this->comp_ysize!=image.ysize)) { @@ -124,7 +129,23 @@ void pix_opencv_lk :: processRGBAImage(imageStruct &image) for ( im=0; im<MAX_MARKERS; im++ ) { - x_found[im] = 0; + x_found[im]--; + } + + if ( delaunay >= 0 ) + { + // init data structures for the delaunay + x_fullrect.x = -comp_xsize/2; + x_fullrect.y = -comp_ysize/2; + x_fullrect.width = 2*comp_xsize; + x_fullrect.height = 2*comp_ysize; + + x_storage = cvCreateMemStorage(0); + x_subdiv = cvCreateSubdiv2D( CV_SEQ_KIND_SUBDIV2D, sizeof(*x_subdiv), + sizeof(CvSubdiv2DPoint), + sizeof(CvQuadEdge2D), + x_storage ); + cvInitSubdivDelaunay2D( x_subdiv, x_fullrect ); } if( need_to_init ) @@ -168,8 +189,50 @@ void pix_opencv_lk :: processRGBAImage(imageStruct &image) continue; points[1][k++] = points[1][i]; + if ( delaunay == 0 ) // add all the points + { + cvSubdivDelaunay2DInsert( x_subdiv, points[1][i] ); + cvCalcSubdivVoronoi2D( x_subdiv ); + } + // only add points included in (color-threshold)<p<(color+treshold) + if ( ( delaunay > 0 ) && ( x_xmark[delaunay-1] != -1 ) ) + { + int px = cvPointFrom32f(points[1][i]).x; + int py = cvPointFrom32f(points[1][i]).y; + int ppx, ppy; + + // eight connected pixels + for ( ppx=px-1; ppx<=px+1; ppx++ ) + { + for ( ppy=py-1; ppy<=py+1; ppy++ ) + { + if ( ( ppx < 0 ) || ( ppx >= comp_xsize ) ) continue; + if ( ( ppy < 0 ) || ( ppy >= comp_ysize ) ) continue; + + uchar red = ((uchar*)(rgba->imageData + rgba->widthStep*ppx))[ppy*4]; + uchar green = ((uchar*)(rgba->imageData + rgba->widthStep*ppx))[ppy*4+1]; + uchar blue = ((uchar*)(rgba->imageData + rgba->widthStep*ppx))[ppy*4+2]; + + uchar pred = ((uchar*)(rgba->imageData + rgba->widthStep*x_xmark[delaunay-1]))[x_ymark[delaunay-1]*4]; + uchar pgreen = ((uchar*)(rgba->imageData + rgba->widthStep*x_xmark[delaunay-1]))[x_ymark[delaunay-1]*4+1]; + uchar pblue = ((uchar*)(rgba->imageData + rgba->widthStep*x_xmark[delaunay-1]))[x_ymark[delaunay-1]*4+2]; + + int diff = abs(red-pred) + abs(green-pgreen) + abs(blue-pblue); + + // post( "pix_opencv_lk : point (%d,%d,%d) : diff : %d", blue, green, red, diff ); + + if ( diff < threshold ) + { + cvSubdivDelaunay2DInsert( x_subdiv, points[1][i] ); + cvCalcSubdivVoronoi2D( x_subdiv ); + } + } + } + } + cvCircle( rgba, cvPointFrom32f(points[1][i]), 3, CV_RGB(0,255,0), -1, 8,0); + marked=0; for ( im=0; im<MAX_MARKERS; im++ ) { // first marking @@ -182,7 +245,8 @@ void pix_opencv_lk :: processRGBAImage(imageStruct &image) cvPutText( rgba, tindex, cvPointFrom32f(points[1][i]), &font, CV_RGB(255,255,255)); x_xmark[im]=points[1][i].x; x_ymark[im]=points[1][i].y; - x_found[im]=1; + x_found[im]=ftolerance; + marked=1; SETFLOAT(&x_list[0], im+1); SETFLOAT(&x_list[1], x_xmark[im]); SETFLOAT(&x_list[2], x_ymark[im]); @@ -190,6 +254,20 @@ void pix_opencv_lk :: processRGBAImage(imageStruct &image) } } } + + if ( markall && !marked ) + { + for ( im=0; im<MAX_MARKERS; im++) + { + if ( x_xmark[im] == -1 ) + { + x_xmark[im]=points[1][i].x; + x_ymark[im]=points[1][i].y; + x_found[im]=ftolerance; + break; + } + } + } } count = k; } @@ -218,6 +296,49 @@ void pix_opencv_lk :: processRGBAImage(imageStruct &image) add_remove_pt = 0; } + // draw the delaunay + if ( delaunay >= 0 ) + { + CvSeqReader reader; + int i, total = x_subdiv->edges->total; + int elem_size = x_subdiv->edges->elem_size; + + cvStartReadSeq( (CvSeq*)(x_subdiv->edges), &reader, 0 ); + + for( i = 0; i < total; i++ ) + { + CvQuadEdge2D* edge = (CvQuadEdge2D*)(reader.ptr); + CvSubdiv2DPoint* org_pt; + CvSubdiv2DPoint* dst_pt; + CvPoint2D32f org; + CvPoint2D32f dst; + CvPoint iorg, idst; + + if( CV_IS_SET_ELEM( edge )) + { + org_pt = cvSubdiv2DEdgeOrg((CvSubdiv2DEdge)edge); + dst_pt = cvSubdiv2DEdgeDst((CvSubdiv2DEdge)edge); + + if( org_pt && dst_pt ) + { + org = org_pt->pt; + dst = dst_pt->pt; + + iorg = cvPoint( cvRound( org.x ), cvRound( org.y )); + idst = cvPoint( cvRound( dst.x ), cvRound( dst.y )); + + if ( ( org.x > 0 ) && ( org.x < comp_xsize ) && + ( dst.x > 0 ) && ( dst.x < comp_xsize ) && + ( org.y > 0 ) && ( org.y < comp_ysize ) && + ( dst.y > 0 ) && ( dst.y < comp_ysize ) ) + cvLine( rgba, iorg, idst, CV_RGB(255,0,0), 1, CV_AA, 0 ); + } + } + + CV_NEXT_SEQ_ELEM( elem_size, reader ); + } + } + CV_SWAP( prev_grey, grey, swap_temp ); CV_SWAP( prev_pyramid, pyramid, swap_temp ); CV_SWAP( points[0], points[1], swap_points ); @@ -230,6 +351,7 @@ void pix_opencv_lk :: processRGBImage(imageStruct &image) { int i, k; int im; + int marked; if ((this->comp_xsize!=image.xsize)&&(this->comp_ysize!=image.ysize)) { @@ -257,7 +379,23 @@ void pix_opencv_lk :: processRGBImage(imageStruct &image) for ( im=0; im<MAX_MARKERS; im++ ) { - x_found[im] = 0; + x_found[im]--; + } + + if ( delaunay >= 0 ) + { + // init data structures for the delaunay + x_fullrect.x = -comp_xsize/2; + x_fullrect.y = -comp_ysize/2; + x_fullrect.width = 2*comp_xsize; + x_fullrect.height = 2*comp_ysize; + + x_storage = cvCreateMemStorage(0); + x_subdiv = cvCreateSubdiv2D( CV_SEQ_KIND_SUBDIV2D, sizeof(*x_subdiv), + sizeof(CvSubdiv2DPoint), + sizeof(CvQuadEdge2D), + x_storage ); + cvInitSubdivDelaunay2D( x_subdiv, x_fullrect ); } if( need_to_init ) @@ -301,8 +439,50 @@ void pix_opencv_lk :: processRGBImage(imageStruct &image) continue; points[1][k++] = points[1][i]; + if ( delaunay == 0 ) // add all the points + { + cvSubdivDelaunay2DInsert( x_subdiv, points[1][i] ); + cvCalcSubdivVoronoi2D( x_subdiv ); + } + // only add points included in (color-threshold)<p<(color+treshold) + if ( ( delaunay > 0 ) && ( x_xmark[delaunay-1] != -1 ) ) + { + int px = cvPointFrom32f(points[1][i]).x; + int py = cvPointFrom32f(points[1][i]).y; + int ppx, ppy; + + // eight connected pixels + for ( ppx=px-1; ppx<=px+1; ppx++ ) + { + for ( ppy=py-1; ppy<=py+1; ppy++ ) + { + if ( ( ppx < 0 ) || ( ppx >= comp_xsize ) ) continue; + if ( ( ppy < 0 ) || ( ppy >= comp_ysize ) ) continue; + + uchar red = ((uchar*)(rgb->imageData + rgb->widthStep*ppx))[ppy*3]; + uchar green = ((uchar*)(rgb->imageData + rgb->widthStep*ppx))[ppy*3+1]; + uchar blue = ((uchar*)(rgb->imageData + rgb->widthStep*ppx))[ppy*3+2]; + + uchar pred = ((uchar*)(rgb->imageData + rgb->widthStep*x_xmark[delaunay-1]))[x_ymark[delaunay-1]*3]; + uchar pgreen = ((uchar*)(rgb->imageData + rgb->widthStep*x_xmark[delaunay-1]))[x_ymark[delaunay-1]*3+1]; + uchar pblue = ((uchar*)(rgb->imageData + rgb->widthStep*x_xmark[delaunay-1]))[x_ymark[delaunay-1]*3+2]; + + int diff = abs(red-pred) + abs(green-pgreen) + abs(blue-pblue); + + // post( "pix_opencv_lk : point (%d,%d,%d) : diff : %d", blue, green, red, diff ); + + if ( diff < threshold ) + { + cvSubdivDelaunay2DInsert( x_subdiv, points[1][i] ); + cvCalcSubdivVoronoi2D( x_subdiv ); + } + } + } + } + cvCircle( rgb, cvPointFrom32f(points[1][i]), 3, CV_RGB(0,255,0), -1, 8,0); + marked=0; for ( im=0; im<MAX_MARKERS; im++ ) { // first marking @@ -315,7 +495,8 @@ void pix_opencv_lk :: processRGBImage(imageStruct &image) cvPutText( rgb, tindex, cvPointFrom32f(points[1][i]), &font, CV_RGB(255,255,255)); x_xmark[im]=points[1][i].x; x_ymark[im]=points[1][i].y; - x_found[im]=1; + x_found[im]=ftolerance; + marked=1; SETFLOAT(&x_list[0], im+1); SETFLOAT(&x_list[1], x_xmark[im]); SETFLOAT(&x_list[2], x_ymark[im]); @@ -323,6 +504,20 @@ void pix_opencv_lk :: processRGBImage(imageStruct &image) } } } + + if ( markall && !marked ) + { + for ( im=0; im<MAX_MARKERS; im++) + { + if ( x_xmark[im] == -1 ) + { + x_xmark[im]=points[1][i].x; + x_ymark[im]=points[1][i].y; + x_found[im]=ftolerance; + break; + } + } + } } count = k; } @@ -351,6 +546,49 @@ void pix_opencv_lk :: processRGBImage(imageStruct &image) add_remove_pt = 0; } + // draw the delaunay + if ( delaunay >= 0 ) + { + CvSeqReader reader; + int i, total = x_subdiv->edges->total; + int elem_size = x_subdiv->edges->elem_size; + + cvStartReadSeq( (CvSeq*)(x_subdiv->edges), &reader, 0 ); + + for( i = 0; i < total; i++ ) + { + CvQuadEdge2D* edge = (CvQuadEdge2D*)(reader.ptr); + CvSubdiv2DPoint* org_pt; + CvSubdiv2DPoint* dst_pt; + CvPoint2D32f org; + CvPoint2D32f dst; + CvPoint iorg, idst; + + if( CV_IS_SET_ELEM( edge )) + { + org_pt = cvSubdiv2DEdgeOrg((CvSubdiv2DEdge)edge); + dst_pt = cvSubdiv2DEdgeDst((CvSubdiv2DEdge)edge); + + if( org_pt && dst_pt ) + { + org = org_pt->pt; + dst = dst_pt->pt; + + iorg = cvPoint( cvRound( org.x ), cvRound( org.y )); + idst = cvPoint( cvRound( dst.x ), cvRound( dst.y )); + + if ( ( org.x > 0 ) && ( org.x < comp_xsize ) && + ( dst.x > 0 ) && ( dst.x < comp_xsize ) && + ( org.y > 0 ) && ( org.y < comp_ysize ) && + ( dst.y > 0 ) && ( dst.y < comp_ysize ) ) + cvLine( rgb, iorg, idst, CV_RGB(255,0,0), 1, CV_AA, 0 ); + } + } + + CV_NEXT_SEQ_ELEM( elem_size, reader ); + } + } + CV_SWAP( prev_grey, grey, swap_temp ); CV_SWAP( prev_pyramid, pyramid, swap_temp ); CV_SWAP( points[0], points[1], swap_points ); @@ -368,6 +606,7 @@ void pix_opencv_lk :: processGrayImage(imageStruct &image) { int i, k; int im; + int marked; if ((this->comp_xsize!=image.xsize)&&(this->comp_ysize!=image.ysize)) { @@ -394,7 +633,23 @@ void pix_opencv_lk :: processGrayImage(imageStruct &image) for ( im=0; im<MAX_MARKERS; im++ ) { - x_found[im] = 0; + x_found[im]--; + } + + if ( delaunay >= 0 ) + { + // init data structures for the delaunay + x_fullrect.x = -comp_xsize/2; + x_fullrect.y = -comp_ysize/2; + x_fullrect.width = 2*comp_xsize; + x_fullrect.height = 2*comp_ysize; + + x_storage = cvCreateMemStorage(0); + x_subdiv = cvCreateSubdiv2D( CV_SEQ_KIND_SUBDIV2D, sizeof(*x_subdiv), + sizeof(CvSubdiv2DPoint), + sizeof(CvQuadEdge2D), + x_storage ); + cvInitSubdivDelaunay2D( x_subdiv, x_fullrect ); } if( need_to_init ) @@ -438,8 +693,45 @@ void pix_opencv_lk :: processGrayImage(imageStruct &image) continue; points[1][k++] = points[1][i]; + if ( delaunay == 0 ) // add all the points + { + cvSubdivDelaunay2DInsert( x_subdiv, points[1][i] ); + cvCalcSubdivVoronoi2D( x_subdiv ); + } + // only add points included in (color-threshold)<p<(color+treshold) + if ( ( delaunay > 0 ) && ( x_xmark[delaunay-1] != -1 ) ) + { + int px = cvPointFrom32f(points[1][i]).x; + int py = cvPointFrom32f(points[1][i]).y; + int ppx, ppy; + + // eight connected pixels + for ( ppx=px-1; ppx<=px+1; ppx++ ) + { + for ( ppy=py-1; ppy<=py+1; ppy++ ) + { + if ( ( ppx < 0 ) || ( ppx >= comp_xsize ) ) continue; + if ( ( ppy < 0 ) || ( ppy >= comp_ysize ) ) continue; + + uchar lum = ((uchar*)(grey->imageData + grey->widthStep*ppx))[ppy]; + uchar plum = ((uchar*)(grey->imageData + grey->widthStep*x_xmark[delaunay-1]))[x_ymark[delaunay-1]]; + + int diff = abs(plum-lum); + + // post( "pix_opencv_lk : point (%d,%d,%d) : diff : %d", blue, green, red, diff ); + + if ( diff < threshold ) + { + cvSubdivDelaunay2DInsert( x_subdiv, points[1][i] ); + cvCalcSubdivVoronoi2D( x_subdiv ); + } + } + } + } + cvCircle( grey, cvPointFrom32f(points[1][i]), 3, CV_RGB(0,255,0), -1, 8,0); + marked=0; for ( im=0; im<MAX_MARKERS; im++ ) { // first marking @@ -452,7 +744,8 @@ void pix_opencv_lk :: processGrayImage(imageStruct &image) cvPutText( grey, tindex, cvPointFrom32f(points[1][i]), &font, CV_RGB(255,255,255)); x_xmark[im]=points[1][i].x; x_ymark[im]=points[1][i].y; - x_found[im]=1; + x_found[im]=ftolerance; + marked=1; SETFLOAT(&x_list[0], im+1); SETFLOAT(&x_list[1], x_xmark[im]); SETFLOAT(&x_list[2], x_ymark[im]); @@ -460,6 +753,20 @@ void pix_opencv_lk :: processGrayImage(imageStruct &image) } } } + + if ( markall && !marked ) + { + for ( im=0; im<MAX_MARKERS; im++) + { + if ( x_xmark[im] == -1 ) + { + x_xmark[im]=points[1][i].x; + x_ymark[im]=points[1][i].y; + x_found[im]=ftolerance; + break; + } + } + } } count = k; } @@ -488,6 +795,49 @@ void pix_opencv_lk :: processGrayImage(imageStruct &image) add_remove_pt = 0; } + // draw the delaunay + if ( delaunay >= 0 ) + { + CvSeqReader reader; + int i, total = x_subdiv->edges->total; + int elem_size = x_subdiv->edges->elem_size; + + cvStartReadSeq( (CvSeq*)(x_subdiv->edges), &reader, 0 ); + + for( i = 0; i < total; i++ ) + { + CvQuadEdge2D* edge = (CvQuadEdge2D*)(reader.ptr); + CvSubdiv2DPoint* org_pt; + CvSubdiv2DPoint* dst_pt; + CvPoint2D32f org; + CvPoint2D32f dst; + CvPoint iorg, idst; + + if( CV_IS_SET_ELEM( edge )) + { + org_pt = cvSubdiv2DEdgeOrg((CvSubdiv2DEdge)edge); + dst_pt = cvSubdiv2DEdgeDst((CvSubdiv2DEdge)edge); + + if( org_pt && dst_pt ) + { + org = org_pt->pt; + dst = dst_pt->pt; + + iorg = cvPoint( cvRound( org.x ), cvRound( org.y )); + idst = cvPoint( cvRound( dst.x ), cvRound( dst.y )); + + if ( ( org.x > 0 ) && ( org.x < comp_xsize ) && + ( dst.x > 0 ) && ( dst.x < comp_xsize ) && + ( org.y > 0 ) && ( org.y < comp_ysize ) && + ( dst.y > 0 ) && ( dst.y < comp_ysize ) ) + cvLine( grey, iorg, idst, CV_RGB(255,0,0), 1, CV_AA, 0 ); + } + } + + CV_NEXT_SEQ_ELEM( elem_size, reader ); + } + } + CV_SWAP( prev_grey, grey, swap_temp ); CV_SWAP( prev_pyramid, pyramid, swap_temp ); CV_SWAP( points[0], points[1], swap_points ); @@ -512,7 +862,7 @@ void pix_opencv_lk :: obj_setupCallback(t_class *classPtr) class_addmethod(classPtr, (t_method)&pix_opencv_lk::initMessCallback, gensym("init"), A_NULL); class_addmethod(classPtr, (t_method)&pix_opencv_lk::markMessCallback, - gensym("mark"), A_FLOAT, A_FLOAT, A_NULL); + gensym("mark"), A_GIMME, A_NULL); class_addmethod(classPtr, (t_method)&pix_opencv_lk::deleteMessCallback, gensym("delete"), A_FLOAT, A_NULL); class_addmethod(classPtr, (t_method)&pix_opencv_lk::clearMessCallback, @@ -521,6 +871,12 @@ void pix_opencv_lk :: obj_setupCallback(t_class *classPtr) gensym("mindistance"), A_FLOAT, A_NULL); class_addmethod(classPtr, (t_method)&pix_opencv_lk::maxMoveMessCallback, gensym("maxmove"), A_FLOAT, A_NULL); + class_addmethod(classPtr, (t_method)&pix_opencv_lk::ftoleranceMessCallback, + gensym("ftolerance"), A_FLOAT, A_NULL); + class_addmethod(classPtr, (t_method)&pix_opencv_lk::delaunayMessCallback, + gensym("delaunay"), A_SYMBOL, A_NULL); + class_addmethod(classPtr, (t_method)&pix_opencv_lk::pdelaunayMessCallback, + gensym("pdelaunay"), A_FLOAT, A_FLOAT, A_NULL); } void pix_opencv_lk :: winSizeMessCallback(void *data, t_floatarg winsize) @@ -543,9 +899,9 @@ void pix_opencv_lk :: initMessCallback(void *data) GetMyClass(data)->initMess(); } -void pix_opencv_lk :: markMessCallback(void *data, t_floatarg mx, t_floatarg my) +void pix_opencv_lk :: markMessCallback(void *data, t_symbol *s, int argc, t_atom *argv) { - GetMyClass(data)->markMess((float)mx, (float)my); + GetMyClass(data)->markMess(argc, argv); } void pix_opencv_lk :: deleteMessCallback(void *data, t_floatarg index) @@ -568,6 +924,21 @@ void pix_opencv_lk :: maxMoveMessCallback(void *data, t_floatarg maxmove) GetMyClass(data)->maxMoveMess((float)maxmove); } +void pix_opencv_lk :: ftoleranceMessCallback(void *data, t_floatarg ftolerance) +{ + GetMyClass(data)->ftoleranceMess((float)ftolerance); +} + +void pix_opencv_lk :: delaunayMessCallback(void *data, t_symbol *s) +{ + GetMyClass(data)->delaunayMess(s); +} + +void pix_opencv_lk :: pdelaunayMessCallback(void *data, t_floatarg fpoint, t_floatarg fthreshold) +{ + GetMyClass(data)->pdelaunayMess(fpoint, fthreshold); +} + void pix_opencv_lk :: winSizeMess(float winsize) { if (winsize>1.0) win_size = (int)winsize; @@ -588,32 +959,68 @@ void pix_opencv_lk :: initMess(void) need_to_init = 1; } -void pix_opencv_lk :: markMess(float mx, float my) +void pix_opencv_lk :: markMess(int argc, t_atom *argv) { int i; int inserted; - if ( ( mx < 0.0 ) || ( mx >= comp_xsize ) || ( my < 0.0 ) || ( my >= comp_ysize ) ) + if ( argc == 1 ) // mark all or none { - return; - } - - inserted = 0; - for ( i=0; i<MAX_MARKERS; i++) - { - if ( x_xmark[i] == -1 ) - { - x_xmark[i] = (int)(mx); - x_ymark[i] = (int)(my); - post( "pix_opencv_lk : inserted point (%d,%d)", x_xmark[i], x_ymark[i] ); - inserted = 1; - break; - } + if ( argv[0].a_type != A_SYMBOL ) + { + error( "pix_opencv_lk : wrong argument (should be 'all')" ); + return; + } + if ( !strcmp( argv[0].a_w.w_symbol->s_name, "all" ) ) + { + markall = 1; + return; + } + if ( !strcmp( argv[0].a_w.w_symbol->s_name, "none" ) ) + { + markall = 0; + clearMess(); + return; + } } - if ( !inserted ) + else { - post( "pix_opencv_lk : max markers reached" ); - } + if ( ( argv[0].a_type != A_FLOAT ) || ( argv[1].a_type != A_FLOAT ) ) + { + error( "pix_opencv_lk : wrong argument (should be mark px py)" ); + return; + } + else + { + float fperx = argv[0].a_w.w_float; + float fpery = argv[1].a_w.w_float; + int px, py; + + if ( ( fperx < 0.0 ) || ( fperx > 1.0 ) || ( fpery < 0.0 ) || ( fpery > 1.0 ) ) + { + return; + } + + px = (int)(fperx*comp_xsize); + py = (int)(fpery*comp_ysize); + inserted = 0; + for ( i=0; i<MAX_MARKERS; i++) + { + if ( x_xmark[i] == -1 ) + { + x_xmark[i] = px; + x_ymark[i] = py; + x_found[i] = ftolerance; + inserted = 1; + break; + } + } + if ( !inserted ) + { + post( "pix_opencv_lk : max markers reached" ); + } + } + } } void pix_opencv_lk :: deleteMess(float index) @@ -653,3 +1060,25 @@ void pix_opencv_lk :: maxMoveMess(float maxmove) if (maxmove>=3.0) maxmove = (int)maxmove; } +void pix_opencv_lk :: ftoleranceMess(float ftolerance) +{ + if (ftolerance>=0.0) ftolerance = (int)ftolerance; +} + +void pix_opencv_lk :: delaunayMess(t_symbol *s) +{ + if (s == gensym("on")) + delaunay = 0; + if (s == gensym("off")) + delaunay = -1; +} + +void pix_opencv_lk :: pdelaunayMess(t_floatarg point, t_floatarg threshold) +{ + if (((int)point>0) && ((int)point<MAX_MARKERS)) + { + delaunay = (int)point; + threshold = (int)threshold; + } +} + diff --git a/pix_opencv_lk.h b/pix_opencv_lk.h index 97859a8..c8be6a7 100755 --- a/pix_opencv_lk.h +++ b/pix_opencv_lk.h @@ -65,11 +65,14 @@ class GEM_EXTERN pix_opencv_lk : public GemPixObj void nightModeMess(float nightmode); void qualityMess(float quality); void initMess(void); - void markMess(float mx, float my); + void markMess(int, t_atom*); void deleteMess(float index); void clearMess(void); void minDistanceMess(float mindistance); void maxMoveMess(float maxmove); + void ftoleranceMess(float ftolerance); + void delaunayMess(t_symbol *s); + void pdelaunayMess(t_floatarg fpoint, t_floatarg fthreshold); int comp_xsize; int comp_ysize; @@ -81,6 +84,10 @@ class GEM_EXTERN pix_opencv_lk : public GemPixObj int min_distance; int night_mode; int maxmove; + int markall; + int ftolerance; + int delaunay; + int threshold; private: @@ -90,11 +97,14 @@ class GEM_EXTERN pix_opencv_lk : public GemPixObj static void nightModeMessCallback(void *data, t_floatarg nightmode); static void qualityMessCallback(void *data, t_floatarg quality); static void initMessCallback(void *data); - static void markMessCallback(void *data, t_floatarg mx, t_floatarg my); + static void markMessCallback(void *data, t_symbol* name, int argc, t_atom* argv); static void deleteMessCallback(void *data, t_floatarg index); static void clearMessCallback(void *data); static void minDistanceMessCallback(void *data, t_floatarg mindistance); static void maxMoveMessCallback(void *data, t_floatarg maxmove); + static void ftoleranceMessCallback(void *data, t_floatarg ftolerance); + static void delaunayMessCallback(void *data, t_symbol *s); + static void pdelaunayMessCallback(void *data, t_floatarg fpoint, t_floatarg fthreshold); // Internal Open CV data IplImage *rgba, *rgb, *grey, *prev_grey, *pyramid, *prev_pyramid, *swap_temp; @@ -110,6 +120,10 @@ class GEM_EXTERN pix_opencv_lk : public GemPixObj CvPoint pt; CvFont font; + // structures needed for the delaunay + CvRect x_fullrect; + CvMemStorage* x_storage; + CvSubdiv2D* x_subdiv; }; |