diff options
-rw-r--r-- | Makefile | 2 | ||||
-rwxr-xr-x | pix_opencv_lk-help.pd | 162 | ||||
-rwxr-xr-x | pix_opencv_lk.cc | 654 | ||||
-rwxr-xr-x | pix_opencv_lk.h | 116 |
4 files changed, 933 insertions, 1 deletions
@@ -36,7 +36,7 @@ endif .SUFFIXES = $(EXTENSION) -SOURCES = pix_opencv_edge.cc pix_opencv_laplace.cc pix_opencv_morphology.cc pix_opencv_distrans.cc pix_opencv_motempl.cc pix_opencv_haarcascade.cc pix_opencv_contours_boundingrect.cc pix_opencv_bgsubstract.cc pix_opencv_contours_convexity.cc pix_opencv_dft.cc +SOURCES = pix_opencv_edge.cc pix_opencv_laplace.cc pix_opencv_morphology.cc pix_opencv_distrans.cc pix_opencv_motempl.cc pix_opencv_haarcascade.cc pix_opencv_contours_boundingrect.cc pix_opencv_bgsubstract.cc pix_opencv_contours_convexity.cc pix_opencv_dft.cc pix_opencv_lk.cc all: $(SOURCES:.cc=.$(EXTENSION)) diff --git a/pix_opencv_lk-help.pd b/pix_opencv_lk-help.pd new file mode 100755 index 0000000..4b67d7c --- /dev/null +++ b/pix_opencv_lk-help.pd @@ -0,0 +1,162 @@ +#N canvas 288 90 1192 685 10; +#X obj 396 -37 gemhead; +#X obj 212 501 pix_texture; +#X obj 212 529 square 2; +#X obj 28 132 cnv 15 220 70 empty empty empty 20 12 0 14 -195568 -66577 +0; +#N canvas 0 22 454 304 gemwin 0; +#X obj 132 136 gemwin; +#X obj 67 89 outlet; +#X obj 67 10 inlet; +#X obj 67 41 route create; +#X msg 67 70 set destroy; +#X msg 182 68 set create; +#X msg 132 112 create \, 1; +#X msg 238 112 destroy; +#N canvas 87 154 247 179 Gem.init 0; +#X obj 118 46 loadbang; +#X msg 118 81 reset; +#X obj 118 113 outlet; +#X connect 0 0 1 0; +#X connect 1 0 2 0; +#X restore 289 80 pd Gem.init; +#X connect 2 0 3 0; +#X connect 3 0 4 0; +#X connect 3 0 6 0; +#X connect 3 1 5 0; +#X connect 3 1 7 0; +#X connect 4 0 1 0; +#X connect 5 0 1 0; +#X connect 6 0 0 0; +#X connect 7 0 0 0; +#X connect 8 0 0 0; +#X restore 35 178 pd gemwin; +#X msg 35 154 create; +#X text 36 136 Create window and render; +#X obj 213 404 pix_texture; +#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 +0; +#X obj 511 -66 bng 25 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 524 128 unpack 0 0 0; +#X floatatom 514 151 5 0 0 3 length - -; +#X floatatom 563 151 5 0 0 3 width - -; +#X floatatom 613 151 5 0 0 3 height - -; +#X obj 568 109 bng 15 250 50 0 empty empty end_reached 20 7 0 10 -262144 +-1 -1; +#X floatatom 550 74 5 0 10000 1 frame# - -; +#X obj 511 -37 openpanel; +#X msg 511 -17 open \$1; +#X obj 499 92 pix_film; +#X msg 517 26 auto \$1; +#X obj 517 8 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#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 obj 553 262 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 +1; +#X msg 468 260 nightmode \$1; +#X text 572 263 set nightmode; +#X msg 463 234 quality \$1; +#X floatatom 538 235 5 0 0 0 - - -; +#X floatatom 546 210 5 0 0 0 - - -; +#X msg 449 209 mindistance \$1; +#X text 587 208 set distance ( default 10 ); +#X msg 442 181 init; +#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 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 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 obj 998 151 route 1; +#X msg 1019 176 bang; +#X connect 0 0 21 0; +#X connect 1 0 2 0; +#X connect 4 0 5 0; +#X connect 5 0 4 0; +#X connect 7 0 8 0; +#X connect 9 0 7 0; +#X connect 9 0 10 0; +#X connect 10 0 24 0; +#X connect 12 0 19 0; +#X connect 13 0 14 0; +#X connect 13 1 15 0; +#X connect 13 2 16 0; +#X connect 17 0 18 0; +#X connect 18 0 21 1; +#X connect 19 0 20 0; +#X connect 20 0 21 0; +#X connect 21 0 9 0; +#X connect 21 1 13 0; +#X connect 21 2 17 0; +#X connect 22 0 21 0; +#X connect 23 0 22 0; +#X connect 24 0 59 0; +#X connect 25 0 26 0; +#X connect 26 0 21 0; +#X connect 27 0 59 1; +#X connect 29 0 30 0; +#X connect 30 0 59 0; +#X connect 32 0 59 0; +#X connect 33 0 32 0; +#X connect 34 0 35 0; +#X connect 35 0 59 0; +#X connect 37 0 59 0; +#X connect 39 0 40 0; +#X connect 40 0 33 0; +#X connect 41 0 59 0; +#X connect 42 0 59 0; +#X connect 44 0 59 0; +#X connect 46 0 59 0; +#X connect 48 0 46 0; +#X connect 50 0 39 0; +#X connect 51 0 50 0; +#X connect 52 0 53 0; +#X connect 52 1 54 0; +#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; diff --git a/pix_opencv_lk.cc b/pix_opencv_lk.cc new file mode 100755 index 0000000..a4a7acb --- /dev/null +++ b/pix_opencv_lk.cc @@ -0,0 +1,654 @@ +//////////////////////////////////////////////////////// +// +// GEM - Graphics Environment for Multimedia +// +// zmoelnig@iem.kug.ac.at +// +// Implementation file +// +// Copyright (c) 1997-2000 Mark Danks. +// Copyright (c) Günther Geiger. +// Copyright (c) 2001-2002 IOhannes m zmoelnig. forum::für::umläute. IEM +// Copyright (c) 2002 James Tittle & Chris Clepper +// For information on usage and redistribution, and for a DISCLAIMER OF ALL +// WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution. +// +///////////////////////////////////////////////////////// + +#include "pix_opencv_lk.h" +#include <stdio.h> + +CPPEXTERN_NEW(pix_opencv_lk) + +///////////////////////////////////////////////////////// +// +// pix_opencv_lk +// +///////////////////////////////////////////////////////// +// Constructor +// +///////////////////////////////////////////////////////// + +pix_opencv_lk :: pix_opencv_lk() +{ + int i; + + comp_xsize=0; + comp_ysize=0; + + inlet_new(this->x_obj, &this->x_obj->ob_pd, gensym("float"), gensym("winsize")); + + m_dataout = outlet_new(this->x_obj, &s_anything); + win_size = 10; + + points[0] = 0; + points[1] = 0; + status = 0; + count = 0; + need_to_init = 1; + night_mode = 0; + flags = 0; + add_remove_pt = 0; + quality = 0.1; + min_distance = 10; + maxmove = 8; + + for ( i=0; i<MAX_MARKERS; i++ ) + { + x_xmark[i] = -1; + x_ymark[i] = -1; + } + + // initialize font + cvInitFont( &font, CV_FONT_HERSHEY_PLAIN, 1.0, 1.0, 0, 1, 8 ); + + rgba = cvCreateImage( cvSize(comp_xsize, comp_ysize), 8, 4 ); + rgb = cvCreateImage( cvSize(comp_xsize, comp_ysize), 8, 3 ); + grey = cvCreateImage( cvSize(comp_xsize, comp_ysize), 8, 1 ); + prev_grey = cvCreateImage( cvSize(comp_xsize, comp_ysize), 8, 1 ); + pyramid = cvCreateImage( cvSize(comp_xsize, comp_ysize), 8, 1 ); + prev_pyramid = cvCreateImage( cvSize(comp_xsize, comp_ysize), 8, 1 ); + points[0] = (CvPoint2D32f*)cvAlloc(MAX_COUNT*sizeof(points[0][0])); + points[1] = (CvPoint2D32f*)cvAlloc(MAX_COUNT*sizeof(points[0][0])); + status = (char*)cvAlloc(MAX_COUNT); + +} + +///////////////////////////////////////////////////////// +// Destructor +// +///////////////////////////////////////////////////////// +pix_opencv_lk :: ~pix_opencv_lk() +{ + // Destroy cv_images + cvReleaseImage( &rgba ); + cvReleaseImage( &rgb ); + cvReleaseImage( &grey ); + cvReleaseImage( &prev_grey ); + cvReleaseImage( &pyramid ); + cvReleaseImage( &prev_pyramid ); +} + +///////////////////////////////////////////////////////// +// processImage +// +///////////////////////////////////////////////////////// +void pix_opencv_lk :: processRGBAImage(imageStruct &image) +{ + int i, k; + int im; + + if ((this->comp_xsize!=image.xsize)&&(this->comp_ysize!=image.ysize)) + { + + this->comp_xsize=image.xsize; + this->comp_ysize=image.ysize; + + rgba = cvCreateImage( cvSize(comp_xsize, comp_ysize), 8, 4 ); + rgb = cvCreateImage( cvSize(comp_xsize, comp_ysize), 8, 3 ); + grey = cvCreateImage( cvSize(comp_xsize, comp_ysize), 8, 1 ); + prev_grey = cvCreateImage( cvSize(comp_xsize, comp_ysize), 8, 1 ); + pyramid = cvCreateImage( cvSize(comp_xsize, comp_ysize), 8, 1 ); + prev_pyramid = cvCreateImage( cvSize(comp_xsize, comp_ysize), 8, 1 ); + points[0] = (CvPoint2D32f*)cvAlloc(MAX_COUNT*sizeof(points[0][0])); + points[1] = (CvPoint2D32f*)cvAlloc(MAX_COUNT*sizeof(points[0][0])); + status = (char*)cvAlloc(MAX_COUNT); + + } + + memcpy( rgba->imageData, image.data, image.xsize*image.ysize*4 ); + cvCvtColor(rgba, grey, CV_BGRA2GRAY); + + if( night_mode ) + cvZero( rgba ); + + for ( im=0; im<MAX_MARKERS; im++ ) + { + x_found[im] = 0; + } + + if( need_to_init ) + { + /* automatic initialization */ + IplImage* eig = cvCreateImage( cvSize(grey->width,grey->height), 32, 1 ); + IplImage* temp = cvCreateImage( cvSize(grey->width,grey->height), 32, 1 ); + + count = MAX_COUNT; + cvGoodFeaturesToTrack( grey, eig, temp, points[1], &count, + quality, min_distance, 0, 3, 0, 0.04 ); + cvFindCornerSubPix( grey, points[1], count, + cvSize(win_size,win_size), cvSize(-1,-1), + cvTermCriteria(CV_TERMCRIT_ITER|CV_TERMCRIT_EPS,20,0.03)); + cvReleaseImage( &eig ); + cvReleaseImage( &temp ); + + add_remove_pt = 0; + } + else if( count > 0 ) + { + cvCalcOpticalFlowPyrLK( prev_grey, grey, prev_pyramid, pyramid, + points[0], points[1], count, cvSize(win_size,win_size), 3, status, 0, + cvTermCriteria(CV_TERMCRIT_ITER|CV_TERMCRIT_EPS,20,0.03), flags ); + flags |= CV_LKFLOW_PYR_A_READY; + for( i = k = 0; i < count; i++ ) + { + if( add_remove_pt ) + { + double dx = pt.x - points[1][i].x; + double dy = pt.y - points[1][i].y; + + if( dx*dx + dy*dy <= 25 ) + { + add_remove_pt = 0; + continue; + } + } + + if( !status[i] ) + continue; + + points[1][k++] = points[1][i]; + cvCircle( rgba, cvPointFrom32f(points[1][i]), 3, CV_RGB(0,255,0), -1, 8,0); + + for ( im=0; im<MAX_MARKERS; im++ ) + { + // first marking + if ( x_xmark[im] != -1.0 ) + { + if ( ( abs( points[1][i].x - x_xmark[im] ) <= maxmove ) && ( abs( points[1][i].y - x_ymark[im] ) <= maxmove ) ) + { + char tindex[4]; + sprintf( tindex, "%d", im+1 ); + 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; + SETFLOAT(&x_list[0], im+1); + SETFLOAT(&x_list[1], x_xmark[im]); + SETFLOAT(&x_list[2], x_ymark[im]); + outlet_list( m_dataout, 0, 3, x_list ); + } + } + } + } + count = k; + } + + for ( im=0; im<MAX_MARKERS; im++ ) + { + if ( (x_xmark[im] != -1.0 ) && !x_found[im] ) + { + x_xmark[im]=-1.0; + x_ymark[im]=-1.0; + SETFLOAT(&x_list[0], im+1); + SETFLOAT(&x_list[1], x_xmark[im]); + SETFLOAT(&x_list[2], x_ymark[im]); + // send a lost point message to the patch + outlet_list( m_dataout, 0, 3, x_list ); + post( "pix_opencv_lk : lost point %d", im+1 ); + } + } + + if( add_remove_pt && count < MAX_COUNT ) + { + points[1][count++] = cvPointTo32f(pt); + cvFindCornerSubPix( grey, points[1] + count - 1, 1, + cvSize(win_size,win_size), cvSize(-1,-1), + cvTermCriteria(CV_TERMCRIT_ITER|CV_TERMCRIT_EPS,20,0.03)); + add_remove_pt = 0; + } + + CV_SWAP( prev_grey, grey, swap_temp ); + CV_SWAP( prev_pyramid, pyramid, swap_temp ); + CV_SWAP( points[0], points[1], swap_points ); + need_to_init = 0; + + memcpy( image.data, rgba->imageData, image.xsize*image.ysize*4 ); +} + +void pix_opencv_lk :: processRGBImage(imageStruct &image) +{ + int i, k; + int im; + + if ((this->comp_xsize!=image.xsize)&&(this->comp_ysize!=image.ysize)) + { + + this->comp_xsize=image.xsize; + this->comp_ysize=image.ysize; + + rgba = cvCreateImage( cvSize(comp_xsize, comp_ysize), 8, 4 ); + rgb = cvCreateImage( cvSize(comp_xsize, comp_ysize), 8, 3 ); + grey = cvCreateImage( cvSize(comp_xsize, comp_ysize), 8, 1 ); + prev_grey = cvCreateImage( cvSize(comp_xsize, comp_ysize), 8, 1 ); + pyramid = cvCreateImage( cvSize(comp_xsize, comp_ysize), 8, 1 ); + prev_pyramid = cvCreateImage( cvSize(comp_xsize, comp_ysize), 8, 1 ); + points[0] = (CvPoint2D32f*)cvAlloc(MAX_COUNT*sizeof(points[0][0])); + points[1] = (CvPoint2D32f*)cvAlloc(MAX_COUNT*sizeof(points[0][0])); + status = (char*)cvAlloc(MAX_COUNT); + + } + + memcpy( rgb->imageData, image.data, image.xsize*image.ysize*3 ); + cvCvtColor(rgb, grey, CV_BGRA2GRAY); + + if( night_mode ) + cvZero( rgb ); + + for ( im=0; im<MAX_MARKERS; im++ ) + { + x_found[im] = 0; + } + + if( need_to_init ) + { + /* automatic initialization */ + IplImage* eig = cvCreateImage( cvSize(grey->width,grey->height), 32, 1 ); + IplImage* temp = cvCreateImage( cvSize(grey->width,grey->height), 32, 1 ); + + count = MAX_COUNT; + cvGoodFeaturesToTrack( grey, eig, temp, points[1], &count, + quality, min_distance, 0, 3, 0, 0.04 ); + cvFindCornerSubPix( grey, points[1], count, + cvSize(win_size,win_size), cvSize(-1,-1), + cvTermCriteria(CV_TERMCRIT_ITER|CV_TERMCRIT_EPS,20,0.03)); + cvReleaseImage( &eig ); + cvReleaseImage( &temp ); + + add_remove_pt = 0; + } + else if( count > 0 ) + { + cvCalcOpticalFlowPyrLK( prev_grey, grey, prev_pyramid, pyramid, + points[0], points[1], count, cvSize(win_size,win_size), 3, status, 0, + cvTermCriteria(CV_TERMCRIT_ITER|CV_TERMCRIT_EPS,20,0.03), flags ); + flags |= CV_LKFLOW_PYR_A_READY; + for( i = k = 0; i < count; i++ ) + { + if( add_remove_pt ) + { + double dx = pt.x - points[1][i].x; + double dy = pt.y - points[1][i].y; + + if( dx*dx + dy*dy <= 25 ) + { + add_remove_pt = 0; + continue; + } + } + + if( !status[i] ) + continue; + + points[1][k++] = points[1][i]; + cvCircle( rgb, cvPointFrom32f(points[1][i]), 3, CV_RGB(0,255,0), -1, 8,0); + + for ( im=0; im<MAX_MARKERS; im++ ) + { + // first marking + if ( x_xmark[im] != -1.0 ) + { + if ( ( abs( points[1][i].x - x_xmark[im] ) <= maxmove ) && ( abs( points[1][i].y - x_ymark[im] ) <= maxmove ) ) + { + char tindex[4]; + sprintf( tindex, "%d", im+1 ); + 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; + SETFLOAT(&x_list[0], im+1); + SETFLOAT(&x_list[1], x_xmark[im]); + SETFLOAT(&x_list[2], x_ymark[im]); + outlet_list( m_dataout, 0, 3, x_list ); + } + } + } + } + count = k; + } + + for ( im=0; im<MAX_MARKERS; im++ ) + { + if ( (x_xmark[im] != -1.0 ) && !x_found[im] ) + { + x_xmark[im]=-1.0; + x_ymark[im]=-1.0; + SETFLOAT(&x_list[0], im+1); + SETFLOAT(&x_list[1], x_xmark[im]); + SETFLOAT(&x_list[2], x_ymark[im]); + // send a lost point message to the patch + outlet_list( m_dataout, 0, 3, x_list ); + post( "pix_opencv_lk : lost point %d", im+1 ); + } + } + + if( add_remove_pt && count < MAX_COUNT ) + { + points[1][count++] = cvPointTo32f(pt); + cvFindCornerSubPix( grey, points[1] + count - 1, 1, + cvSize(win_size,win_size), cvSize(-1,-1), + cvTermCriteria(CV_TERMCRIT_ITER|CV_TERMCRIT_EPS,20,0.03)); + add_remove_pt = 0; + } + + CV_SWAP( prev_grey, grey, swap_temp ); + CV_SWAP( prev_pyramid, pyramid, swap_temp ); + CV_SWAP( points[0], points[1], swap_points ); + need_to_init = 0; + + memcpy( image.data, rgb->imageData, image.xsize*image.ysize*3 ); +} + +void pix_opencv_lk :: processYUVImage(imageStruct &image) +{ +} + +void pix_opencv_lk :: processGrayImage(imageStruct &image) +{ + int i, k; + int im; + + if ((this->comp_xsize!=image.xsize)&&(this->comp_ysize!=image.ysize)) + { + + this->comp_xsize=image.xsize; + this->comp_ysize=image.ysize; + + rgba = cvCreateImage( cvSize(comp_xsize, comp_ysize), 8, 4 ); + rgb = cvCreateImage( cvSize(comp_xsize, comp_ysize), 8, 3 ); + grey = cvCreateImage( cvSize(comp_xsize, comp_ysize), 8, 1 ); + prev_grey = cvCreateImage( cvSize(comp_xsize, comp_ysize), 8, 1 ); + pyramid = cvCreateImage( cvSize(comp_xsize, comp_ysize), 8, 1 ); + prev_pyramid = cvCreateImage( cvSize(comp_xsize, comp_ysize), 8, 1 ); + points[0] = (CvPoint2D32f*)cvAlloc(MAX_COUNT*sizeof(points[0][0])); + points[1] = (CvPoint2D32f*)cvAlloc(MAX_COUNT*sizeof(points[0][0])); + status = (char*)cvAlloc(MAX_COUNT); + + } + + memcpy( grey->imageData, image.data, image.xsize*image.ysize ); + + if( night_mode ) + cvZero( grey ); + + for ( im=0; im<MAX_MARKERS; im++ ) + { + x_found[im] = 0; + } + + if( need_to_init ) + { + /* automatic initialization */ + IplImage* eig = cvCreateImage( cvSize(grey->width,grey->height), 32, 1 ); + IplImage* temp = cvCreateImage( cvSize(grey->width,grey->height), 32, 1 ); + + count = MAX_COUNT; + cvGoodFeaturesToTrack( grey, eig, temp, points[1], &count, + quality, min_distance, 0, 3, 0, 0.04 ); + cvFindCornerSubPix( grey, points[1], count, + cvSize(win_size,win_size), cvSize(-1,-1), + cvTermCriteria(CV_TERMCRIT_ITER|CV_TERMCRIT_EPS,20,0.03)); + cvReleaseImage( &eig ); + cvReleaseImage( &temp ); + + add_remove_pt = 0; + } + else if( count > 0 ) + { + cvCalcOpticalFlowPyrLK( prev_grey, grey, prev_pyramid, pyramid, + points[0], points[1], count, cvSize(win_size,win_size), 3, status, 0, + cvTermCriteria(CV_TERMCRIT_ITER|CV_TERMCRIT_EPS,20,0.03), flags ); + flags |= CV_LKFLOW_PYR_A_READY; + for( i = k = 0; i < count; i++ ) + { + if( add_remove_pt ) + { + double dx = pt.x - points[1][i].x; + double dy = pt.y - points[1][i].y; + + if( dx*dx + dy*dy <= 25 ) + { + add_remove_pt = 0; + continue; + } + } + + if( !status[i] ) + continue; + + points[1][k++] = points[1][i]; + cvCircle( grey, cvPointFrom32f(points[1][i]), 3, CV_RGB(0,255,0), -1, 8,0); + + for ( im=0; im<MAX_MARKERS; im++ ) + { + // first marking + if ( x_xmark[im] != -1.0 ) + { + if ( ( abs( points[1][i].x - x_xmark[im] ) <= maxmove ) && ( abs( points[1][i].y - x_ymark[im] ) <= maxmove ) ) + { + char tindex[4]; + sprintf( tindex, "%d", im+1 ); + 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; + SETFLOAT(&x_list[0], im+1); + SETFLOAT(&x_list[1], x_xmark[im]); + SETFLOAT(&x_list[2], x_ymark[im]); + outlet_list( m_dataout, 0, 3, x_list ); + } + } + } + } + count = k; + } + + for ( im=0; im<MAX_MARKERS; im++ ) + { + if ( (x_xmark[im] != -1.0 ) && !x_found[im] ) + { + x_xmark[im]=-1.0; + x_ymark[im]=-1.0; + SETFLOAT(&x_list[0], im+1); + SETFLOAT(&x_list[1], x_xmark[im]); + SETFLOAT(&x_list[2], x_ymark[im]); + // send a lost point message to the patch + outlet_list( m_dataout, 0, 3, x_list ); + post( "pix_opencv_lk : lost point %d", im+1 ); + } + } + + if( add_remove_pt && count < MAX_COUNT ) + { + points[1][count++] = cvPointTo32f(pt); + cvFindCornerSubPix( grey, points[1] + count - 1, 1, + cvSize(win_size,win_size), cvSize(-1,-1), + cvTermCriteria(CV_TERMCRIT_ITER|CV_TERMCRIT_EPS,20,0.03)); + add_remove_pt = 0; + } + + CV_SWAP( prev_grey, grey, swap_temp ); + CV_SWAP( prev_pyramid, pyramid, swap_temp ); + CV_SWAP( points[0], points[1], swap_points ); + need_to_init = 0; + + memcpy( image.data, grey->imageData, image.xsize*image.ysize ); +} + +///////////////////////////////////////////////////////// +// static member function +// +///////////////////////////////////////////////////////// + +void pix_opencv_lk :: obj_setupCallback(t_class *classPtr) +{ + class_addmethod(classPtr, (t_method)&pix_opencv_lk::winSizeMessCallback, + gensym("winsize"), A_FLOAT, A_NULL); + class_addmethod(classPtr, (t_method)&pix_opencv_lk::nightModeMessCallback, + gensym("nightmode"), A_FLOAT, A_NULL); + class_addmethod(classPtr, (t_method)&pix_opencv_lk::qualityMessCallback, + gensym("quality"), A_FLOAT, A_NULL); + 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); + class_addmethod(classPtr, (t_method)&pix_opencv_lk::deleteMessCallback, + gensym("delete"), A_FLOAT, A_NULL); + class_addmethod(classPtr, (t_method)&pix_opencv_lk::clearMessCallback, + gensym("clear"), A_NULL); + class_addmethod(classPtr, (t_method)&pix_opencv_lk::minDistanceMessCallback, + gensym("mindistance"), A_FLOAT, A_NULL); + class_addmethod(classPtr, (t_method)&pix_opencv_lk::maxMoveMessCallback, + gensym("maxmove"), A_FLOAT, A_NULL); +} + +void pix_opencv_lk :: winSizeMessCallback(void *data, t_floatarg winsize) +{ + GetMyClass(data)->winSizeMess((float)winsize); +} + +void pix_opencv_lk :: nightModeMessCallback(void *data, t_floatarg nightmode) +{ + GetMyClass(data)->nightModeMess((float)nightmode); +} + +void pix_opencv_lk :: qualityMessCallback(void *data, t_floatarg quality) +{ + GetMyClass(data)->qualityMess((float)quality); +} + +void pix_opencv_lk :: initMessCallback(void *data) +{ + GetMyClass(data)->initMess(); +} + +void pix_opencv_lk :: markMessCallback(void *data, t_floatarg mx, t_floatarg my) +{ + GetMyClass(data)->markMess((float)mx, (float)my); +} + +void pix_opencv_lk :: deleteMessCallback(void *data, t_floatarg index) +{ + GetMyClass(data)->deleteMess((float)index); +} + +void pix_opencv_lk :: clearMessCallback(void *data) +{ + GetMyClass(data)->clearMess(); +} + +void pix_opencv_lk :: minDistanceMessCallback(void *data, t_floatarg mindistance) +{ + GetMyClass(data)->minDistanceMess((float)mindistance); +} + +void pix_opencv_lk :: maxMoveMessCallback(void *data, t_floatarg maxmove) +{ + GetMyClass(data)->maxMoveMess((float)maxmove); +} + +void pix_opencv_lk :: winSizeMess(float winsize) +{ + if (winsize>1.0) win_size = (int)winsize; +} + +void pix_opencv_lk :: nightModeMess(float nightmode) +{ + if ((nightmode==0.0)||(nightmode==1.0)) night_mode = (int)nightmode; +} + +void pix_opencv_lk :: qualityMess(float quality) +{ + if (quality>0.0) quality = quality; +} + +void pix_opencv_lk :: initMess(void) +{ + need_to_init = 1; +} + +void pix_opencv_lk :: markMess(float mx, float my) +{ + int i; + int inserted; + + if ( ( mx < 0.0 ) || ( mx >= comp_xsize ) || ( my < 0.0 ) || ( my >= comp_ysize ) ) + { + 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 ( !inserted ) + { + post( "pix_opencv_lk : max markers reached" ); + } +} + +void pix_opencv_lk :: deleteMess(float index) +{ + int i; + + if ( ( index < 1.0 ) || ( index > MAX_MARKERS ) ) + { + return; + } + + x_xmark[(int)index-1] = -1; + x_ymark[(int)index-1] = -1; + +} + +void pix_opencv_lk :: clearMess(void) +{ + int i; + + for ( i=0; i<MAX_MARKERS; i++) + { + x_xmark[i] = -1; + x_ymark[i] = -1; + } + +} + +void pix_opencv_lk :: minDistanceMess(float mindistance) +{ + if (mindistance>1.0) min_distance = (int)mindistance; +} + +void pix_opencv_lk :: maxMoveMess(float maxmove) +{ + // has to be more than the size of a point + if (maxmove>=3.0) maxmove = (int)maxmove; +} + diff --git a/pix_opencv_lk.h b/pix_opencv_lk.h new file mode 100755 index 0000000..3f8c8f6 --- /dev/null +++ b/pix_opencv_lk.h @@ -0,0 +1,116 @@ +/*----------------------------------------------------------------- +LOG + GEM - Graphics Environment for Multimedia + + Change pix to greyscale + + Copyright (c) 1997-1999 Mark Danks. mark@danks.org + Copyright (c) Günther Geiger. geiger@epy.co.at + Copyright (c) 2001-2002 IOhannes m zmoelnig. forum::für::umläute. IEM. zmoelnig@iem.kug.ac.at + Copyright (c) 2002 James Tittle & Chris Clepper + For information on usage and redistribution, and for a DISCLAIMER OF ALL + WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution. + +-----------------------------------------------------------------*/ + +#ifndef INCLUDE_PIX_OPENCV_DISTRANS_H_ +#define INCLUDE_PIX_OPENCV_DISTRANS_H_ + +#include "Base/GemPixObj.h" + +#ifndef _EiC +#include "cv.h" +#endif + +#define MAX_MARKERS 10 +const int MAX_COUNT = 500; + +/*----------------------------------------------------------------- +------------------------------------------------------------------- +CLASS + pix_opencv_lk + + Change pix to greyscale + +KEYWORDS + pix + +DESCRIPTION + +-----------------------------------------------------------------*/ +class GEM_EXTERN pix_opencv_lk : public GemPixObj +{ + CPPEXTERN_HEADER(pix_opencv_lk, GemPixObj) + + public: + + ////////// + // Constructor + pix_opencv_lk(); + + protected: + + ////////// + // Destructor + virtual ~pix_opencv_lk(); + + ////////// + // Do the processing + virtual void processRGBAImage(imageStruct &image); + virtual void processRGBImage(imageStruct &image); + virtual void processYUVImage(imageStruct &image); + virtual void processGrayImage(imageStruct &image); + + void winSizeMess(float winsize); + void nightModeMess(float nightmode); + void qualityMess(float quality); + void initMess(void); + void markMess(float mx, float my); + void deleteMess(float index); + void clearMess(void); + void minDistanceMess(float mindistance); + void maxMoveMess(float maxmove); + + int comp_xsize; + int comp_ysize; + + t_outlet *m_dataout; + t_atom x_list[3]; + int win_size; + double quality; + int min_distance; + int night_mode; + int maxmove; + + private: + + ////////// + // Static member functions + static void winSizeMessCallback(void *data, t_floatarg winsize); + 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 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); + + // Internal Open CV data + IplImage *rgba, *rgb, *grey, *prev_grey, *pyramid, *prev_pyramid, *swap_temp; + int x_xmark[MAX_MARKERS]; + int x_ymark[MAX_MARKERS]; + int x_found[MAX_MARKERS]; + CvPoint2D32f* points[2], *swap_points; + char* status; + int count; + int need_to_init; + int flags; + int add_remove_pt; + CvPoint pt; + CvFont font; + + +}; + +#endif // for header file |