aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorN.N. <sevyves@users.sourceforge.net>2009-09-03 22:34:27 +0000
committerN.N. <sevyves@users.sourceforge.net>2009-09-03 22:34:27 +0000
commit8f0e0686d06484cf9c2125590aa6e1a8984aeb8d (patch)
tree46d31433d03f3be88f5731751c36077e99d39896
parentc7599f2fe85abefedf083c04377530d2e3497246 (diff)
added pix_opencv_surf
svn path=/trunk/externals/pix_opencv/; revision=12236
-rw-r--r--Makefile2
-rw-r--r--README1
-rwxr-xr-xpix_opencv_surf-help.pd182
-rwxr-xr-xpix_opencv_surf.cc1005
-rwxr-xr-xpix_opencv_surf.h120
5 files changed, 1308 insertions, 2 deletions
diff --git a/Makefile b/Makefile
index f702dd5..3bc85a6 100644
--- a/Makefile
+++ b/Makefile
@@ -35,7 +35,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 pix_opencv_lk.cc pix_opencv_hist_compare.cc pix_opencv_knear.cc pix_opencv_threshold.cc pix_opencv_floodfill.cc pix_opencv_athreshold.cc pix_opencv_bgstats.cc pix_opencv_camshift.cc pix_opencv_hu_compare.cc pix_opencv_pgh_compare.cc pix_opencv_hough_circles.cc pix_opencv_hough_lines.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 pix_opencv_hist_compare.cc pix_opencv_knear.cc pix_opencv_threshold.cc pix_opencv_floodfill.cc pix_opencv_athreshold.cc pix_opencv_bgstats.cc pix_opencv_camshift.cc pix_opencv_hu_compare.cc pix_opencv_pgh_compare.cc pix_opencv_hough_circles.cc pix_opencv_hough_lines.cc pix_opencv_hu_moments.cc pix_opencv_surf.cc
all: $(SOURCES:.cc=.$(EXTENSION))
diff --git a/README b/README
deleted file mode 100644
index a138819..0000000
--- a/README
+++ /dev/null
@@ -1 +0,0 @@
-See docs/index.htm
diff --git a/pix_opencv_surf-help.pd b/pix_opencv_surf-help.pd
new file mode 100755
index 0000000..6b35907
--- /dev/null
+++ b/pix_opencv_surf-help.pd
@@ -0,0 +1,182 @@
+#N canvas 117 89 1211 737 10;
+#X obj 218 -57 gemhead;
+#X obj 218 457 pix_texture;
+#X obj 28 132 cnv 15 220 70 empty empty empty 20 12 0 14 -195568 -66577
+0;
+#N canvas 189 149 454 304 gemwin 0;
+#X obj 130 218 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 129 165 create \, 1;
+#X msg 205 166 destroy;
+#N canvas 87 154 363 340 Gem.init 0;
+#X obj 112 15 loadbang;
+#X msg 62 93 reset;
+#X obj 49 135 outlet;
+#X msg 107 89 dimen 320 240;
+#X msg 202 89 frame 5;
+#X obj 107 51 t b b b;
+#X connect 0 0 5 0;
+#X connect 1 0 2 0;
+#X connect 3 0 2 0;
+#X connect 4 0 2 0;
+#X connect 5 0 3 0;
+#X connect 5 1 4 0;
+#X connect 5 2 1 0;
+#X restore 289 80 pd Gem.init;
+#X obj 128 109 t b b b;
+#X msg 156 138 dimen 320 240;
+#X msg 251 138 frame 15;
+#X connect 2 0 3 0;
+#X connect 3 0 4 0;
+#X connect 3 0 9 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 9 0 6 0;
+#X connect 9 1 10 0;
+#X connect 9 2 11 0;
+#X connect 10 0 0 0;
+#X connect 11 0 0 0;
+#X restore 35 178 pd gemwin;
+#X msg 35 157 destroy;
+#X text 36 136 Create window and render;
+#X obj 340 180 cnv 15 600 450 empty empty empty 20 12 0 14 -24198 -66577
+0;
+#X obj 333 -86 bng 25 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 346 108 unpack 0 0 0;
+#X floatatom 336 131 5 0 0 3 length - -;
+#X floatatom 385 131 5 0 0 3 width - -;
+#X floatatom 435 131 5 0 0 3 height - -;
+#X obj 390 89 bng 15 250 50 0 empty empty end_reached 20 7 0 10 -262144
+-1 -1;
+#X floatatom 382 72 5 0 10000 1 frame# - -;
+#X obj 333 -57 openpanel;
+#X msg 333 -37 open \$1;
+#X obj 321 72 pix_film;
+#X msg 339 6 auto \$1;
+#X obj 339 -12 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1
+1;
+#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 obj 952 123 gemmouse;
+#X obj 1008 230 f;
+#X obj 978 229 f;
+#X obj 1022 201 t b b;
+#X obj 975 274 pack f f;
+#X obj 998 151 route 1;
+#X msg 1019 176 bang;
+#X floatatom 969 251 5 0 0 0 - - -;
+#X floatatom 1022 254 5 0 0 0 - - -;
+#X obj 208 534 rectangle 4 3;
+#X obj 212 489 pix_resize 320 240;
+#X obj 410 -7 loadbang;
+#X msg 410 18 colorspace RGBA;
+#X msg 514 18 colorspace RGB;
+#X msg 473 -8 colorspace Grey;
+#X obj 384 524 pix_opencv_surf;
+#X obj 467 252 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0
+1;
+#X msg 382 253 nightmode \$1;
+#X text 486 256 set nightmode;
+#X msg 429 316 mark \$1 \$2;
+#X msg 435 339 delete \$1;
+#X text 628 340 delete a marker;
+#X msg 446 362 clear;
+#X text 494 363 delete all markers;
+#X msg 461 392 maxmove \$1;
+#X text 575 392 max movement of a marker ( default 5 pisels );
+#X floatatom 537 394 5 0 0 0 - - -;
+#X text 502 316 mark %x %y : mark a point to track ( max points : 10
+);
+#X text 546 441 make a delaunay with all points;
+#X msg 465 439 delaunay on;
+#X msg 467 460 delaunay off;
+#X text 577 471 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 obj 500 339 hradio 15 1 0 8 empty empty empty 0 -8 0 10 -262144
+-1 -1 0;
+#X msg 473 483 pdelaunay 1 50;
+#X msg 363 224 hessian \$1;
+#X floatatom 438 225 5 0 0 0 - - -;
+#X floatatom 546 416 5 0 0 0 - - -;
+#X msg 464 415 ftolerance \$1;
+#X text 589 416 frame tolerance for point recognition ( default : 5
+);
+#X msg 406 272 mark all;
+#X text 476 273 mark all points;
+#X msg 416 293 mark none;
+#X text 486 294 suppress all marks;
+#X text 654 27 written by Lluis Gomez i Bigorda ( lluisgomez@hangar.org
+) and Yves Degoyon ( ydegoyon@gmail.com );
+#X text 652 4 pix_opencv_surf : SURF ( Speed Up Robust Features ) points
+detection and tracking;
+#X text 478 224 hessian threshold ( default 1000 );
+#X connect 0 0 16 0;
+#X connect 1 0 35 0;
+#X connect 3 0 4 0;
+#X connect 4 0 3 0;
+#X connect 7 0 14 0;
+#X connect 8 0 9 0;
+#X connect 8 1 10 0;
+#X connect 8 2 11 0;
+#X connect 12 0 13 0;
+#X connect 13 0 16 1;
+#X connect 14 0 15 0;
+#X connect 15 0 16 0;
+#X connect 16 0 40 0;
+#X connect 16 1 8 0;
+#X connect 16 2 12 0;
+#X connect 17 0 16 0;
+#X connect 18 0 17 0;
+#X connect 19 0 20 0;
+#X connect 19 1 21 0;
+#X connect 24 0 19 0;
+#X connect 25 0 27 1;
+#X connect 25 1 26 1;
+#X connect 25 2 30 0;
+#X connect 26 0 29 1;
+#X connect 26 0 33 0;
+#X connect 27 0 29 0;
+#X connect 27 0 32 0;
+#X connect 28 0 27 0;
+#X connect 28 1 26 0;
+#X connect 29 0 44 0;
+#X connect 30 0 31 0;
+#X connect 31 0 28 0;
+#X connect 35 0 34 0;
+#X connect 36 0 37 0;
+#X connect 37 0 16 0;
+#X connect 38 0 16 0;
+#X connect 39 0 16 0;
+#X connect 40 0 1 0;
+#X connect 40 1 24 0;
+#X connect 41 0 42 0;
+#X connect 42 0 40 0;
+#X connect 44 0 40 0;
+#X connect 45 0 40 0;
+#X connect 47 0 40 0;
+#X connect 49 0 40 0;
+#X connect 51 0 49 0;
+#X connect 54 0 40 0;
+#X connect 55 0 40 0;
+#X connect 57 0 45 0;
+#X connect 58 0 40 0;
+#X connect 59 0 40 0;
+#X connect 60 0 59 0;
+#X connect 61 0 62 0;
+#X connect 62 0 40 0;
+#X connect 64 0 40 0;
+#X connect 66 0 40 0;
diff --git a/pix_opencv_surf.cc b/pix_opencv_surf.cc
new file mode 100755
index 0000000..c1cfe9a
--- /dev/null
+++ b/pix_opencv_surf.cc
@@ -0,0 +1,1005 @@
+
+//
+// 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_surf.h"
+#include <stdio.h>
+
+
+CPPEXTERN_NEW(pix_opencv_surf)
+
+/////////////////////////////////////////////////////////
+//
+// pix_opencv_surf
+//
+/////////////////////////////////////////////////////////
+// Constructor
+//
+/////////////////////////////////////////////////////////
+
+pix_opencv_surf :: pix_opencv_surf()
+{
+ int i;
+
+ comp_xsize=320;
+ comp_ysize=240;
+
+ m_dataout = outlet_new(this->x_obj, &s_anything);
+
+ night_mode = 0;
+ x_maxmove = 8;
+ x_delaunay = -1;
+ x_threshold = -1;
+
+ objectKeypoints = NULL;
+ objectDescriptors = NULL;
+ x_hessian = 1000;
+ x_ftolerance = 5;
+
+ x_markall = 0;
+ 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 );
+ orgb = cvCreateImage( cvSize(comp_xsize, comp_ysize), 8, 3 );
+ rgb = cvCreateImage( cvSize(comp_xsize, comp_ysize), 8, 3 );
+ gray = cvCreateImage( cvSize(comp_xsize, comp_ysize), 8, 1 );
+ ogray = cvCreateImage( cvSize(comp_xsize, comp_ysize), 8, 1 );
+
+}
+
+/////////////////////////////////////////////////////////
+// Destructor
+//
+/////////////////////////////////////////////////////////
+pix_opencv_surf :: ~pix_opencv_surf()
+{
+ // Destroy cv_images
+ cvReleaseImage( &rgba );
+ cvReleaseImage( &orgb );
+ cvReleaseImage( &rgb );
+ cvReleaseImage( &gray );
+ cvReleaseImage( &ogray );
+}
+
+/////////////////////////////////////////////////////////
+// processImage
+//
+/////////////////////////////////////////////////////////
+void pix_opencv_surf :: processRGBAImage(imageStruct &image)
+{
+ int i, k;
+ int im;
+ int marked;
+ int descsize;
+ char tindex[4];
+
+ if ((this->comp_xsize!=image.xsize)&&(this->comp_ysize!=image.ysize))
+ {
+
+ this->comp_xsize=image.xsize;
+ this->comp_ysize=image.ysize;
+
+ cvReleaseImage( &rgba );
+ cvReleaseImage( &orgb );
+ cvReleaseImage( &rgb );
+ cvReleaseImage( &gray );
+ cvReleaseImage( &ogray );
+
+ rgba = cvCreateImage( cvSize(comp_xsize, comp_ysize), 8, 4 );
+ orgb = cvCreateImage( cvSize(comp_xsize, comp_ysize), 8, 3 );
+ rgb = cvCreateImage( cvSize(comp_xsize, comp_ysize), 8, 3 );
+ gray = cvCreateImage( cvSize(comp_xsize, comp_ysize), 8, 1 );
+ ogray = cvCreateImage( cvSize(comp_xsize, comp_ysize), 8, 1 );
+
+ }
+
+ memcpy( rgba->imageData, image.data, image.xsize*image.ysize*4 );
+ cvCvtColor(rgba, orgb, CV_BGRA2BGR);
+ cvCvtColor(rgba, rgb, CV_BGRA2BGR);
+ cvCvtColor(rgba, gray, CV_BGRA2GRAY);
+
+ x_storage = cvCreateMemStorage(0);
+
+ if( night_mode )
+ cvZero( rgb );
+
+ for ( im=0; im<MAX_MARKERS; im++ )
+ {
+ x_found[im]--;
+ }
+
+ if ( x_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_subdiv = cvCreateSubdiv2D( CV_SEQ_KIND_SUBDIV2D, sizeof(*x_subdiv),
+ sizeof(CvSubdiv2DPoint),
+ sizeof(CvQuadEdge2D),
+ x_storage );
+ cvInitSubdivDelaunay2D( x_subdiv, x_fullrect );
+ }
+
+ cvExtractSURF( gray, 0, &objectKeypoints, &objectDescriptors, x_storage, cvSURFParams(x_hessian, 1) );
+ descsize = (int)(objectDescriptors->elem_size/sizeof(float));
+
+ for( i = 0; i < objectKeypoints->total; i++ )
+ {
+ CvSURFPoint* r1 = (CvSURFPoint*)cvGetSeqElem( objectKeypoints, i );
+ const float* rdesc = (const float*)cvGetSeqElem( objectDescriptors, i );
+
+ if ( x_delaunay == 0 ) // add all the points
+ {
+ cvSubdivDelaunay2DInsert( x_subdiv, r1->pt );
+ cvCalcSubdivVoronoi2D( x_subdiv );
+ }
+
+ // only add points included in (color-threshold)<p<(color+treshold)
+ if ( ( x_delaunay > 0 ) && ( x_xmark[x_delaunay-1] != -1 ) )
+ {
+ int px = cvPointFrom32f(r1->pt).x;
+ int py = cvPointFrom32f(r1->pt).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*)(orgb->imageData + orgb->widthStep*ppx))[ppy*3];
+ uchar green = ((uchar*)(orgb->imageData + orgb->widthStep*ppx))[ppy*3+1];
+ uchar blue = ((uchar*)(orgb->imageData + orgb->widthStep*ppx))[ppy*3+2];
+
+ uchar pred = ((uchar*)(orgb->imageData + orgb->widthStep*x_xmark[x_delaunay-1]))[x_ymark[x_delaunay-1]*3];
+ uchar pgreen = ((uchar*)(orgb->imageData + orgb->widthStep*x_xmark[x_delaunay-1]))[x_ymark[x_delaunay-1]*3+1];
+ uchar pblue = ((uchar*)(orgb->imageData + orgb->widthStep*x_xmark[x_delaunay-1]))[x_ymark[x_delaunay-1]*3+2];
+
+ int diff = abs(red-pred) + abs(green-pgreen) + abs(blue-pblue);
+
+ // post( "pdp_opencv_surf : point (%d,%d,%d) : diff : %d", blue, green, red, diff );
+
+ if ( diff < x_threshold )
+ {
+ cvSubdivDelaunay2DInsert( x_subdiv, r1->pt );
+ cvCalcSubdivVoronoi2D( x_subdiv );
+ }
+ }
+ }
+ }
+
+ cvCircle( rgb, cvPointFrom32f(r1->pt), 3, CV_RGB(0,255,0), -1, 8,0);
+
+ // mark the point if it is not already
+ if ( x_markall )
+ {
+ int marked = 0;
+
+ for ( im=0; im<MAX_MARKERS; im++ )
+ {
+ if ( x_xmark[im] != -1.0 )
+ {
+ if ( ( abs( r1->pt.x - x_xmark[im] ) <= x_maxmove ) && ( abs( r1->pt.y - x_ymark[im] ) <= x_maxmove ) )
+ {
+ marked = 1;
+ // post( "pdp_opencv_surf : point already marked" );
+ break;
+ }
+ }
+ }
+ if ( !marked )
+ {
+ for ( i=0; i<MAX_MARKERS; i++)
+ {
+ if ( x_xmark[i] == -1 )
+ {
+ x_xmark[i] = r1->pt.x;
+ x_ymark[i] = r1->pt.y;
+ x_found[i] = x_ftolerance;
+ memset( (float * )x_rdesc[i], 0x0, DSCSIZE*sizeof(float));
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ for ( im=0; im<MAX_MARKERS; im++ )
+ {
+ int neighbour = -1;
+ double d, dist1 = 1000000, dist2 = 1000000;
+
+ for( i = 0; i < objectKeypoints->total; i++ )
+ {
+ CvSURFPoint* r1 = (CvSURFPoint*)cvGetSeqElem( objectKeypoints, i );
+ const float* rdesc = (const float*)cvGetSeqElem( objectDescriptors, i );
+ int descsize = (int)(objectDescriptors->elem_size/sizeof(float));
+
+ // manually marked points
+ // recognized on position
+ if ( x_xmark[im] != -1.0 )
+ {
+ if ( ( abs( r1->pt.x - x_xmark[im] ) <= x_maxmove ) && ( abs( r1->pt.y - x_ymark[im] ) <= x_maxmove ) )
+ {
+ sprintf( tindex, "%d", im+1 );
+ cvPutText( rgb, tindex, cvPointFrom32f(r1->pt), &font, CV_RGB(255,255,255));
+ x_xmark[im]=r1->pt.x;
+ x_ymark[im]=r1->pt.y;
+ memcpy( (float * )x_rdesc[im], rdesc, descsize*sizeof(float));
+ x_found[im]++;
+ 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 );
+ break;
+ }
+ }
+ }
+ }
+
+ // draw the delaunay
+ if ( x_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 );
+ }
+ }
+
+ // suppress lost points
+ 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( "pdp_opencv_surf : lost point %d", im+1 );
+ }
+ }
+
+ cvReleaseMemStorage( &x_storage );
+
+ cvCvtColor(rgb, rgba, CV_BGR2BGRA);
+ memcpy( image.data, rgba->imageData, image.xsize*image.ysize*4 );
+}
+
+void pix_opencv_surf :: processRGBImage(imageStruct &image)
+{
+ int i, k;
+ int im;
+ int marked;
+ int descsize;
+ char tindex[4];
+
+ if ((this->comp_xsize!=image.xsize)&&(this->comp_ysize!=image.ysize))
+ {
+
+ this->comp_xsize=image.xsize;
+ this->comp_ysize=image.ysize;
+
+ cvReleaseImage( &rgba );
+ cvReleaseImage( &orgb );
+ cvReleaseImage( &rgb );
+ cvReleaseImage( &gray );
+ cvReleaseImage( &ogray );
+
+ rgba = cvCreateImage( cvSize(comp_xsize, comp_ysize), 8, 4 );
+ orgb = cvCreateImage( cvSize(comp_xsize, comp_ysize), 8, 3 );
+ rgb = cvCreateImage( cvSize(comp_xsize, comp_ysize), 8, 3 );
+ gray = cvCreateImage( cvSize(comp_xsize, comp_ysize), 8, 1 );
+ ogray = cvCreateImage( cvSize(comp_xsize, comp_ysize), 8, 1 );
+
+ }
+
+ memcpy( rgb->imageData, image.data, image.xsize*image.ysize*3 );
+ memcpy( orgb->imageData, image.data, image.xsize*image.ysize*3 );
+ cvCvtColor(rgb, gray, CV_BGRA2GRAY);
+
+ x_storage = cvCreateMemStorage(0);
+
+ if( night_mode )
+ cvZero( rgb );
+
+ for ( im=0; im<MAX_MARKERS; im++ )
+ {
+ x_found[im]--;
+ }
+
+ if ( x_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_subdiv = cvCreateSubdiv2D( CV_SEQ_KIND_SUBDIV2D, sizeof(*x_subdiv),
+ sizeof(CvSubdiv2DPoint),
+ sizeof(CvQuadEdge2D),
+ x_storage );
+ cvInitSubdivDelaunay2D( x_subdiv, x_fullrect );
+ }
+
+ cvExtractSURF( gray, 0, &objectKeypoints, &objectDescriptors, x_storage, cvSURFParams(x_hessian, 1) );
+ descsize = (int)(objectDescriptors->elem_size/sizeof(float));
+
+ for( i = 0; i < objectKeypoints->total; i++ )
+ {
+ CvSURFPoint* r1 = (CvSURFPoint*)cvGetSeqElem( objectKeypoints, i );
+ const float* rdesc = (const float*)cvGetSeqElem( objectDescriptors, i );
+
+ if ( x_delaunay == 0 ) // add all the points
+ {
+ cvSubdivDelaunay2DInsert( x_subdiv, r1->pt );
+ cvCalcSubdivVoronoi2D( x_subdiv );
+ }
+
+ // only add points included in (color-threshold)<p<(color+treshold)
+ if ( ( x_delaunay > 0 ) && ( x_xmark[x_delaunay-1] != -1 ) )
+ {
+ int px = cvPointFrom32f(r1->pt).x;
+ int py = cvPointFrom32f(r1->pt).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*)(orgb->imageData + orgb->widthStep*ppx))[ppy*3];
+ uchar green = ((uchar*)(orgb->imageData + orgb->widthStep*ppx))[ppy*3+1];
+ uchar blue = ((uchar*)(orgb->imageData + orgb->widthStep*ppx))[ppy*3+2];
+
+ uchar pred = ((uchar*)(orgb->imageData + orgb->widthStep*x_xmark[x_delaunay-1]))[x_ymark[x_delaunay-1]*3];
+ uchar pgreen = ((uchar*)(orgb->imageData + orgb->widthStep*x_xmark[x_delaunay-1]))[x_ymark[x_delaunay-1]*3+1];
+ uchar pblue = ((uchar*)(orgb->imageData + orgb->widthStep*x_xmark[x_delaunay-1]))[x_ymark[x_delaunay-1]*3+2];
+
+ int diff = abs(red-pred) + abs(green-pgreen) + abs(blue-pblue);
+
+ // post( "pdp_opencv_surf : point (%d,%d,%d) : diff : %d", blue, green, red, diff );
+
+ if ( diff < x_threshold )
+ {
+ cvSubdivDelaunay2DInsert( x_subdiv, r1->pt );
+ cvCalcSubdivVoronoi2D( x_subdiv );
+ }
+ }
+ }
+ }
+
+ cvCircle( rgb, cvPointFrom32f(r1->pt), 3, CV_RGB(0,255,0), -1, 8,0);
+
+ // mark the point if it is not already
+ if ( x_markall )
+ {
+ int marked = 0;
+
+ for ( im=0; im<MAX_MARKERS; im++ )
+ {
+ if ( x_xmark[im] != -1.0 )
+ {
+ if ( ( abs( r1->pt.x - x_xmark[im] ) <= x_maxmove ) && ( abs( r1->pt.y - x_ymark[im] ) <= x_maxmove ) )
+ {
+ marked = 1;
+ // post( "pdp_opencv_surf : point already marked" );
+ break;
+ }
+ }
+ }
+ if ( !marked )
+ {
+ for ( i=0; i<MAX_MARKERS; i++)
+ {
+ if ( x_xmark[i] == -1 )
+ {
+ x_xmark[i] = r1->pt.x;
+ x_ymark[i] = r1->pt.y;
+ x_found[i] = x_ftolerance;
+ memset( (float * )x_rdesc[i], 0x0, DSCSIZE*sizeof(float));
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ for ( im=0; im<MAX_MARKERS; im++ )
+ {
+ int neighbour = -1;
+ double d, dist1 = 1000000, dist2 = 1000000;
+
+ for( i = 0; i < objectKeypoints->total; i++ )
+ {
+ CvSURFPoint* r1 = (CvSURFPoint*)cvGetSeqElem( objectKeypoints, i );
+ const float* rdesc = (const float*)cvGetSeqElem( objectDescriptors, i );
+ int descsize = (int)(objectDescriptors->elem_size/sizeof(float));
+
+ // manually marked points
+ // recognized on position
+ if ( x_xmark[im] != -1.0 )
+ {
+ if ( ( abs( r1->pt.x - x_xmark[im] ) <= x_maxmove ) && ( abs( r1->pt.y - x_ymark[im] ) <= x_maxmove ) )
+ {
+ sprintf( tindex, "%d", im+1 );
+ cvPutText( rgb, tindex, cvPointFrom32f(r1->pt), &font, CV_RGB(255,255,255));
+ x_xmark[im]=r1->pt.x;
+ x_ymark[im]=r1->pt.y;
+ memcpy( (float * )x_rdesc[im], rdesc, descsize*sizeof(float));
+ x_found[im]++;
+ 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 );
+ break;
+ }
+ }
+ }
+ }
+
+ // draw the delaunay
+ if ( x_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 );
+ }
+ }
+
+ // suppress lost points
+ 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( "pdp_opencv_surf : lost point %d", im+1 );
+ }
+ }
+
+ cvReleaseMemStorage( &x_storage );
+ memcpy( image.data, rgb->imageData, image.xsize*image.ysize*3 );
+}
+
+void pix_opencv_surf :: processYUVImage(imageStruct &image)
+{
+ post( "pix_opencv_surf : yuv format not supported" );
+}
+
+void pix_opencv_surf :: processGrayImage(imageStruct &image)
+{
+ int i, k;
+ int im;
+ int marked;
+ int descsize;
+ char tindex[4];
+
+ if ((this->comp_xsize!=image.xsize)&&(this->comp_ysize!=image.ysize))
+ {
+
+ this->comp_xsize=image.xsize;
+ this->comp_ysize=image.ysize;
+
+ cvReleaseImage( &rgba );
+ cvReleaseImage( &orgb );
+ cvReleaseImage( &rgb );
+ cvReleaseImage( &gray );
+ cvReleaseImage( &ogray );
+
+ rgba = cvCreateImage( cvSize(comp_xsize, comp_ysize), 8, 4 );
+ orgb = cvCreateImage( cvSize(comp_xsize, comp_ysize), 8, 3 );
+ rgb = cvCreateImage( cvSize(comp_xsize, comp_ysize), 8, 3 );
+ gray = cvCreateImage( cvSize(comp_xsize, comp_ysize), 8, 1 );
+ ogray = cvCreateImage( cvSize(comp_xsize, comp_ysize), 8, 1 );
+
+ }
+
+ memcpy( gray->imageData, image.data, image.xsize*image.ysize );
+ memcpy( ogray->imageData, image.data, image.xsize*image.ysize );
+ x_storage = cvCreateMemStorage(0);
+
+ if( night_mode )
+ cvZero( gray );
+
+ for ( im=0; im<MAX_MARKERS; im++ )
+ {
+ x_found[im]--;
+ }
+
+ if ( x_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_subdiv = cvCreateSubdiv2D( CV_SEQ_KIND_SUBDIV2D, sizeof(*x_subdiv),
+ sizeof(CvSubdiv2DPoint),
+ sizeof(CvQuadEdge2D),
+ x_storage );
+ cvInitSubdivDelaunay2D( x_subdiv, x_fullrect );
+ }
+
+ cvExtractSURF( ogray, 0, &objectKeypoints, &objectDescriptors, x_storage, cvSURFParams(x_hessian, 1) );
+ descsize = (int)(objectDescriptors->elem_size/sizeof(float));
+
+ for( i = 0; i < objectKeypoints->total; i++ )
+ {
+ CvSURFPoint* r1 = (CvSURFPoint*)cvGetSeqElem( objectKeypoints, i );
+ const float* rdesc = (const float*)cvGetSeqElem( objectDescriptors, i );
+
+ if ( x_delaunay == 0 ) // add all the points
+ {
+ cvSubdivDelaunay2DInsert( x_subdiv, r1->pt );
+ cvCalcSubdivVoronoi2D( x_subdiv );
+ }
+
+ // only add points included in (color-threshold)<p<(color+treshold)
+ if ( ( x_delaunay > 0 ) && ( x_xmark[x_delaunay-1] != -1 ) )
+ {
+ int px = cvPointFrom32f(r1->pt).x;
+ int py = cvPointFrom32f(r1->pt).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*)(ogray->imageData + ogray->widthStep*ppx))[ppy];
+
+ uchar plum = ((uchar*)(ogray->imageData + ogray->widthStep*x_xmark[x_delaunay-1]))[x_ymark[x_delaunay-1]];
+
+ int diff = abs(lum-plum);
+
+ if ( diff < x_threshold )
+ {
+ cvSubdivDelaunay2DInsert( x_subdiv, r1->pt );
+ cvCalcSubdivVoronoi2D( x_subdiv );
+ }
+ }
+ }
+ }
+
+ cvCircle( gray, cvPointFrom32f(r1->pt), 3, CV_RGB(255,255,255), -1, 8,0);
+
+ // mark the point if it is not already
+ if ( x_markall )
+ {
+ int marked = 0;
+
+ for ( im=0; im<MAX_MARKERS; im++ )
+ {
+ if ( x_xmark[im] != -1.0 )
+ {
+ if ( ( abs( r1->pt.x - x_xmark[im] ) <= x_maxmove ) && ( abs( r1->pt.y - x_ymark[im] ) <= x_maxmove ) )
+ {
+ marked = 1;
+ // post( "pdp_opencv_surf : point already marked" );
+ break;
+ }
+ }
+ }
+ if ( !marked )
+ {
+ for ( i=0; i<MAX_MARKERS; i++)
+ {
+ if ( x_xmark[i] == -1 )
+ {
+ x_xmark[i] = r1->pt.x;
+ x_ymark[i] = r1->pt.y;
+ x_found[i] = x_ftolerance;
+ memset( (float * )x_rdesc[i], 0x0, DSCSIZE*sizeof(float));
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ for ( im=0; im<MAX_MARKERS; im++ )
+ {
+ int neighbour = -1;
+ double d, dist1 = 1000000, dist2 = 1000000;
+
+ for( i = 0; i < objectKeypoints->total; i++ )
+ {
+ CvSURFPoint* r1 = (CvSURFPoint*)cvGetSeqElem( objectKeypoints, i );
+ const float* rdesc = (const float*)cvGetSeqElem( objectDescriptors, i );
+ int descsize = (int)(objectDescriptors->elem_size/sizeof(float));
+
+ // manually marked points
+ // recognized on position
+ if ( x_xmark[im] != -1.0 )
+ {
+ if ( ( abs( r1->pt.x - x_xmark[im] ) <= x_maxmove ) && ( abs( r1->pt.y - x_ymark[im] ) <= x_maxmove ) )
+ {
+ sprintf( tindex, "%d", im+1 );
+ cvPutText( gray, tindex, cvPointFrom32f(r1->pt), &font, CV_RGB(255,255,255));
+ x_xmark[im]=r1->pt.x;
+ x_ymark[im]=r1->pt.y;
+ memcpy( (float * )x_rdesc[im], rdesc, descsize*sizeof(float));
+ x_found[im]++;
+ 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 );
+ break;
+ }
+ }
+ }
+ }
+
+ // draw the delaunay
+ if ( x_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( gray, iorg, idst, CV_RGB(255,255,255), 1, CV_AA, 0 );
+ }
+ }
+
+ CV_NEXT_SEQ_ELEM( elem_size, reader );
+ }
+ }
+
+ // suppress lost points
+ 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( "pdp_opencv_surf : lost point %d", im+1 );
+ }
+ }
+
+ cvReleaseMemStorage( &x_storage );
+ memcpy( image.data, gray->imageData, image.xsize*image.ysize );
+}
+
+/////////////////////////////////////////////////////////
+// static member function
+//
+/////////////////////////////////////////////////////////
+
+void pix_opencv_surf :: obj_setupCallback(t_class *classPtr)
+{
+ class_addmethod(classPtr, (t_method)&pix_opencv_surf::nightModeMessCallback,
+ gensym("nightmode"), A_FLOAT, A_NULL);
+ class_addmethod(classPtr, (t_method)&pix_opencv_surf::hessianMessCallback,
+ gensym("hessian"), A_FLOAT, A_NULL);
+ class_addmethod(classPtr, (t_method)&pix_opencv_surf::markMessCallback,
+ gensym("mark"), A_GIMME, A_NULL);
+ class_addmethod(classPtr, (t_method)&pix_opencv_surf::deleteMessCallback,
+ gensym("delete"), A_FLOAT, A_NULL);
+ class_addmethod(classPtr, (t_method)&pix_opencv_surf::clearMessCallback,
+ gensym("clear"), A_NULL);
+ class_addmethod(classPtr, (t_method)&pix_opencv_surf::maxMoveMessCallback,
+ gensym("maxmove"), A_FLOAT, A_NULL);
+ class_addmethod(classPtr, (t_method)&pix_opencv_surf::ftoleranceMessCallback,
+ gensym("ftolerance"), A_FLOAT, A_NULL);
+ class_addmethod(classPtr, (t_method)&pix_opencv_surf::delaunayMessCallback,
+ gensym("delaunay"), A_SYMBOL, A_NULL);
+ class_addmethod(classPtr, (t_method)&pix_opencv_surf::pdelaunayMessCallback,
+ gensym("pdelaunay"), A_FLOAT, A_FLOAT, A_NULL);
+}
+
+void pix_opencv_surf :: nightModeMessCallback(void *data, t_floatarg nightmode)
+{
+ GetMyClass(data)->nightModeMess((float)nightmode);
+}
+
+void pix_opencv_surf :: hessianMessCallback(void *data, t_floatarg hessian)
+{
+ GetMyClass(data)->hessianMess((float)hessian);
+}
+
+void pix_opencv_surf :: markMessCallback(void *data, t_symbol *s, int argc, t_atom *argv)
+{
+ GetMyClass(data)->markMess(argc, argv);
+}
+
+void pix_opencv_surf :: deleteMessCallback(void *data, t_floatarg index)
+{
+ GetMyClass(data)->deleteMess((float)index);
+}
+
+void pix_opencv_surf :: clearMessCallback(void *data)
+{
+ GetMyClass(data)->clearMess();
+}
+
+void pix_opencv_surf :: maxMoveMessCallback(void *data, t_floatarg maxmove)
+{
+ GetMyClass(data)->maxMoveMess((float)maxmove);
+}
+
+void pix_opencv_surf :: ftoleranceMessCallback(void *data, t_floatarg ftolerance)
+{
+ GetMyClass(data)->ftoleranceMess((float)ftolerance);
+}
+
+void pix_opencv_surf :: delaunayMessCallback(void *data, t_symbol *s)
+{
+ GetMyClass(data)->delaunayMess(s);
+}
+
+void pix_opencv_surf :: pdelaunayMessCallback(void *data, t_floatarg fpoint, t_floatarg fthreshold)
+{
+ GetMyClass(data)->pdelaunayMess(fpoint, fthreshold);
+}
+
+void pix_opencv_surf :: nightModeMess(float nightmode)
+{
+ if ((nightmode==0.0)||(nightmode==1.0)) night_mode = (int)nightmode;
+}
+
+void pix_opencv_surf :: hessianMess(float hessian)
+{
+ if (hessian>0.0) x_hessian = (int)hessian;
+}
+
+void pix_opencv_surf :: markMess(int argc, t_atom *argv)
+{
+ int i;
+ int inserted;
+
+ if ( argc == 1 ) // mark all or none
+ {
+ if ( argv[0].a_type != A_SYMBOL )
+ {
+ error( "pix_opencv_surf : wrong argument (should be 'all')" );
+ return;
+ }
+ if ( !strcmp( argv[0].a_w.w_symbol->s_name, "all" ) )
+ {
+ x_markall = 1;
+ return;
+ }
+ if ( !strcmp( argv[0].a_w.w_symbol->s_name, "none" ) )
+ {
+ x_markall = 0;
+ clearMess();
+ return;
+ }
+ }
+ else
+ {
+ if ( ( argv[0].a_type != A_FLOAT ) || ( argv[1].a_type != A_FLOAT ) )
+ {
+ error( "pix_opencv_surf : wrong argument (should be mark px py)" );
+ return;
+ }
+ else
+ {
+ float fpx = argv[0].a_w.w_float;
+ float fpy = argv[1].a_w.w_float;
+ int px, py;
+
+ if ( ( fpx < 0.0 ) || ( fpx > comp_xsize ) || ( fpy < 0.0 ) || ( fpy > comp_ysize ) )
+ {
+ return;
+ }
+
+ px = (int)fpx;
+ py = comp_ysize-(int)fpy;
+ 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] = x_ftolerance;
+ inserted = 1;
+ // post( "pix_opencv_surf : inserted point (%d,%d)", px, py );
+ break;
+ }
+ }
+ if ( !inserted )
+ {
+ post( "pix_opencv_surf : max markers reached" );
+ }
+ }
+ }
+}
+
+void pix_opencv_surf :: 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_surf :: clearMess(void)
+{
+ int i;
+
+ for ( i=0; i<MAX_MARKERS; i++)
+ {
+ x_xmark[i] = -1;
+ x_ymark[i] = -1;
+ }
+
+}
+
+void pix_opencv_surf :: maxMoveMess(float maxmove)
+{
+ // has to be more than the size of a point
+ if (maxmove>=3.0) maxmove = (int)maxmove;
+}
+
+void pix_opencv_surf :: ftoleranceMess(float ftolerance)
+{
+ if (ftolerance>=0.0) ftolerance = (int)ftolerance;
+}
+
+void pix_opencv_surf :: delaunayMess(t_symbol *s)
+{
+ if (s == gensym("on"))
+ x_delaunay = 0;
+ if (s == gensym("off"))
+ x_delaunay = -1;
+}
+
+void pix_opencv_surf :: pdelaunayMess(t_floatarg point, t_floatarg threshold)
+{
+ if (((int)point>0) && ((int)point<MAX_MARKERS))
+ {
+ x_delaunay = (int)point;
+ x_threshold = (int)threshold;
+ }
+}
+
diff --git a/pix_opencv_surf.h b/pix_opencv_surf.h
new file mode 100755
index 0000000..bbc0277
--- /dev/null
+++ b/pix_opencv_surf.h
@@ -0,0 +1,120 @@
+/*-----------------------------------------------------------------
+LOG
+ GEM - Graphics Environment for Multimedia
+
+ SURF point detection and tracking
+
+ 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_SURF_H_
+#define INCLUDE_PIX_OPENCV_SURF_H_
+
+#include "Base/GemPixObj.h"
+
+#ifndef _EiC
+#include "cv.h"
+#endif
+
+#define MAX_MARKERS 500
+#define DSCSIZE 128
+
+/*-----------------------------------------------------------------
+-------------------------------------------------------------------
+CLASS
+ pix_opencv_surf
+
+ SURF point detection and tracking
+
+KEYWORDS
+ pix
+
+DESCRIPTION
+
+-----------------------------------------------------------------*/
+class GEM_EXTERN pix_opencv_surf : public GemPixObj
+{
+ CPPEXTERN_HEADER(pix_opencv_surf, GemPixObj)
+
+ public:
+
+ //////////
+ // Constructor
+ pix_opencv_surf();
+
+ protected:
+
+ //////////
+ // Destructor
+ virtual ~pix_opencv_surf();
+
+ //////////
+ // Do the processing
+ virtual void processRGBAImage(imageStruct &image);
+ virtual void processRGBImage(imageStruct &image);
+ virtual void processYUVImage(imageStruct &image);
+ virtual void processGrayImage(imageStruct &image);
+
+ void nightModeMess(float nightmode);
+ void hessianMess(float hessian);
+ void markMess(int, t_atom*);
+ void deleteMess(float index);
+ void clearMess(void);
+ 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;
+
+ t_outlet *m_dataout;
+ int x_hessian;
+ int x_criteria;
+ int night_mode;
+ int x_maxmove;
+ int x_markall;
+ int x_ftolerance;
+ int x_delaunay;
+ int x_threshold;
+
+ private:
+
+ //////////
+ // Static member functions
+ static void nightModeMessCallback(void *data, t_floatarg nightmode);
+ static void hessianMessCallback(void *data, t_floatarg hessian);
+ 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 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 *orgb, *rgba, *rgb, *gray, *ogray;
+ t_atom x_list[3];
+
+ int x_xmark[MAX_MARKERS];
+ int x_ymark[MAX_MARKERS];
+ float x_rdesc[MAX_MARKERS][DSCSIZE];
+ int x_found[MAX_MARKERS];
+
+ // internal OpenCV structures
+ CvSeq *objectKeypoints, *objectDescriptors;
+ CvFont font;
+
+ // structures needed for the delaunay
+ CvRect x_fullrect;
+ CvMemStorage* x_storage;
+ CvSubdiv2D* x_subdiv;
+};
+
+#endif // for header file