From ba994f4404b6eadcab4e0ead46ef4d3ffeceb024 Mon Sep 17 00:00:00 2001 From: Antoine Villeret Date: Thu, 10 Jul 2014 14:39:22 +0000 Subject: lots of changes ! 1. switch to a new build system based on automake (because we need to check for some lib on ./configure before make) 2. sort files in different directory 3. add some new features (some of them need OpenCV >= 2.4.5) svn path=/trunk/externals/pix_opencv/; revision=17324 --- src/pix_opencv_haarcascade.cc | 526 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 526 insertions(+) create mode 100644 src/pix_opencv_haarcascade.cc (limited to 'src/pix_opencv_haarcascade.cc') diff --git a/src/pix_opencv_haarcascade.cc b/src/pix_opencv_haarcascade.cc new file mode 100644 index 0000000..59dce35 --- /dev/null +++ b/src/pix_opencv_haarcascade.cc @@ -0,0 +1,526 @@ +//////////////////////////////////////////////////////// +// +// 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_haarcascade.h" +#include +#include + +CPPEXTERN_NEW(pix_opencv_haarcascade) + +///////////////////////////////////////////////////////// +// +// pix_opencv_haarcascade +// +///////////////////////////////////////////////////////// +// Constructor +// +///////////////////////////////////////////////////////// +pix_opencv_haarcascade :: pix_opencv_haarcascade() +{ + int i; + + m_numout = outlet_new(this->x_obj, 0); + m_dataout = outlet_new(this->x_obj, 0); + + scale_factor = 1.1; + min_neighbors = 2; + mode = 0; + min_size = 30; + + comp_xsize = 0; + comp_ysize = 0; + rgba = NULL; + grey = NULL; + frame = NULL; + x_ftolerance = 5; + + for ( i=0; icomp_xsize!=image.xsize)||(this->comp_ysize!=image.ysize)||(!rgba)) { + + this->comp_xsize = image.xsize; + this->comp_ysize = image.ysize; + + //Destroy cv_images to clean memory + cvReleaseImage(&rgba); + cvReleaseImage(&grey); + cvReleaseImage(&frame); + + //create the orig image with new size + rgba = cvCreateImage(cvSize(image.xsize,image.ysize), IPL_DEPTH_8U, 4); + frame = cvCreateImage(cvSize(rgba->width,rgba->height), IPL_DEPTH_8U, 3); + grey = cvCreateImage( cvSize(rgba->width,rgba->height), 8, 1 ); + } + // FEM UNA COPIA DEL PACKET A image->imageData ... http://www.cs.iit.edu/~agam/cs512/lect-notes/opencv-intro/opencv-intro.html aqui veiem la estructura de IplImage + memcpy( rgba->imageData, image.data, image.xsize*image.ysize*4 ); + CvMemStorage* storage = cvCreateMemStorage(0); + + static CvScalar colors[] = + { + {{0,0,255}}, + {{0,128,255}}, + {{0,255,255}}, + {{0,255,0}}, + {{255,128,0}}, + {{255,255,0}}, + {{255,0,0}}, + {{255,0,255}} + }; + + int i, im; + + if( cascade ) + { + CvSeq* faces = cvHaarDetectObjects( rgba, cascade, storage, + scale_factor, min_neighbors, mode, cvSize(min_size, min_size) ); + + if ( faces && (faces->total > 0 ) ) + outlet_float(this->m_numout, (float)faces->total); + else + outlet_float(this->m_numout, 0.0); + + for ( im=0; imx_xmark[im] != -1.0 ) + { + this->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); + + found = 0; + oi = -1; + for ( im=0; imx_xmark[im], 2 ) + pow((double)center.y - this->x_ymark[im], 2 ) ) <= radius ) + { + oi=im; + found=1; + this->x_found[im] = this->x_ftolerance; + this->x_xmark[im] = center.x; + this->x_ymark[im] = center.y; + break; + } + } + // new object detected + if ( !found ) + { + oi = this->mark(center.x, center.y ); + } + + char tindex[4]; + sprintf( tindex, "%d", oi ); + cvCircle( rgba, center, radius, colors[oi%8], 3, 8, 0 ); + cvPutText( rgba, tindex, center, &this->font, CV_RGB(255,255,255)); + + SETFLOAT(&this->rlist[0], oi); + SETFLOAT(&this->rlist[1], center.x); + SETFLOAT(&this->rlist[2], center.y); + SETFLOAT(&this->rlist[3], radius); + outlet_list( m_dataout, 0, 4, this->rlist ); + } + // delete lost objects + for ( im=0; imx_found[im] < 0 ) + { + this->x_xmark[im] = -1.0; + this->x_ymark[im] = -1,0; + this->x_found[im] = this->x_ftolerance; + } + } + + } + + cvReleaseMemStorage( &storage ); + memcpy( image.data, rgba->imageData, image.xsize*image.ysize*4 ); +} + +void pix_opencv_haarcascade :: processRGBImage(imageStruct &image) +{ + double scale = 1; + + if ((this->comp_xsize!=image.xsize)||(this->comp_ysize!=image.ysize)||(!frame)) { + + this->comp_xsize = image.xsize; + this->comp_ysize = image.ysize; + + //Destroy cv_images to clean memory + cvReleaseImage(&rgba); + cvReleaseImage(&grey); + cvReleaseImage(&frame); + + //create the orig image with new size + rgba = cvCreateImage(cvSize(image.xsize,image.ysize), IPL_DEPTH_8U, 4); + frame = cvCreateImage(cvSize(rgba->width,rgba->height), IPL_DEPTH_8U, 3); + grey = cvCreateImage( cvSize(rgba->width,rgba->height), 8, 1 ); + } + // FEM UNA COPIA DEL PACKET A image->imageData ... http://www.cs.iit.edu/~agam/cs512/lect-notes/opencv-intro/opencv-intro.html aqui veiem la estructura de IplImage + memcpy( frame->imageData, image.data, image.xsize*image.ysize*3 ); + CvMemStorage* storage = cvCreateMemStorage(0); + + static CvScalar colors[] = + { + {{0,0,255}}, + {{0,128,255}}, + {{0,255,255}}, + {{0,255,0}}, + {{255,128,0}}, + {{255,255,0}}, + {{255,0,0}}, + {{255,0,255}} + }; + + int i, im; + + if( cascade ) + { + CvSeq* faces = cvHaarDetectObjects( frame, cascade, storage, + 1.1, 2, 0, cvSize(30, 30) ); + + if ( faces && (faces->total > 0 ) ) + outlet_float(this->m_numout, (float)faces->total); + else + outlet_float(this->m_numout, 0.0); + + for ( im=0; imx_xmark[im] != -1.0 ) + { + this->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); + + found = 0; + oi = -1; + for ( im=0; imx_xmark[im], 2 ) + pow((double)center.y - this->x_ymark[im], 2 ) ) <= radius ) + { + oi=im; + found=1; + this->x_found[im] = this->x_ftolerance; + this->x_xmark[im] = center.x; + this->x_ymark[im] = center.y; + break; + } + } + // new object detected + if ( !found ) + { + oi = this->mark(center.x, center.y ); + } + + char tindex[4]; + sprintf( tindex, "%d", oi ); + cvCircle( frame, center, radius, colors[oi%8], 3, 8, 0 ); + cvPutText( frame, tindex, center, &this->font, CV_RGB(255,255,255)); + + SETFLOAT(&this->rlist[0], oi); + SETFLOAT(&this->rlist[1], center.x); + SETFLOAT(&this->rlist[2], center.y); + SETFLOAT(&this->rlist[3], radius); + outlet_list( m_dataout, 0, 4, this->rlist ); + } + // delete lost objects + for ( im=0; imx_found[im] < 0 ) + { + this->x_xmark[im] = -1.0; + this->x_ymark[im] = -1,0; + this->x_found[im] = this->x_ftolerance; + } + } + } + + cvReleaseMemStorage( &storage ); + memcpy( image.data, frame->imageData, image.xsize*image.ysize*3 ); +} + +void pix_opencv_haarcascade :: processYUVImage(imageStruct &image) +{ + post( "pix_opencv_haarcascade : yuv format not supported" ); +} + +void pix_opencv_haarcascade :: processGrayImage(imageStruct &image) +{ + double scale = 1; + + if ((this->comp_xsize!=image.xsize)||(this->comp_ysize!=image.ysize)||(!grey)) { + + this->comp_xsize = image.xsize; + this->comp_ysize = image.ysize; + + //Destroy cv_images to clean memory + cvReleaseImage(&rgba); + cvReleaseImage(&grey); + cvReleaseImage(&frame); + + //create the orig image with new size + rgba = cvCreateImage(cvSize(image.xsize,image.ysize), IPL_DEPTH_8U, 4); + frame = cvCreateImage(cvSize(rgba->width,rgba->height), IPL_DEPTH_8U, 3); + grey = cvCreateImage( cvSize(rgba->width,rgba->height), 8, 1 ); + } + // FEM UNA COPIA DEL PACKET A image->imageData ... http://www.cs.iit.edu/~agam/cs512/lect-notes/opencv-intro/opencv-intro.html aqui veiem la estructura de IplImage + memcpy( grey->imageData, image.data, image.xsize*image.ysize ); + CvMemStorage* storage = cvCreateMemStorage(0); + + static CvScalar colors[] = + { + {{0,0,255}}, + {{0,128,255}}, + {{0,255,255}}, + {{0,255,0}}, + {{255,128,0}}, + {{255,255,0}}, + {{255,0,0}}, + {{255,0,255}} + }; + + int i; + + if( cascade ) + { + CvSeq* faces = cvHaarDetectObjects( grey, cascade, storage, + 1.1, 2, 0, cvSize(30, 30) ); + for( i = 0; i < (faces ? faces->total : 0); i++ ) + { + 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( grey, center, radius, colors[i%8], 3, 8, 0 ); + + t_atom rlist[4]; + SETFLOAT(&rlist[0], i); + SETFLOAT(&rlist[1], center.x); + SETFLOAT(&rlist[2], center.y); + SETFLOAT(&rlist[3], radius); + outlet_list( m_dataout, 0, 4, rlist ); + } + } + + + cvReleaseMemStorage( &storage ); + //cvShowImage(wndname, cedge); + memcpy( image.data, grey->imageData, image.xsize*image.ysize ); +} + +///////////////////////////////////////////////////////// +// scaleFactorMess +// +///////////////////////////////////////////////////////// +void pix_opencv_haarcascade :: scaleFactorMess (float scale_factor) +{ + this->scale_factor = scale_factor; +} + +///////////////////////////////////////////////////////// +// minNeighborsMess +// +///////////////////////////////////////////////////////// +void pix_opencv_haarcascade :: minNeighborsMess (float min_neighbors) +{ + this->min_neighbors = (int)min_neighbors; +} + +///////////////////////////////////////////////////////// +// modeMess +// +///////////////////////////////////////////////////////// +void pix_opencv_haarcascade :: modeMess (float mode) +{ + this->mode = !(!(int)mode); +} + +///////////////////////////////////////////////////////// +// minSizeMess +// +///////////////////////////////////////////////////////// +void pix_opencv_haarcascade :: minSizeMess (float min_size) +{ + this->min_size = (int)min_size; +} + +///////////////////////////////////////////////////////// +// fToleranceMess +// +///////////////////////////////////////////////////////// +void pix_opencv_haarcascade :: fToleranceMess (float ftolerance) +{ + this->x_ftolerance = (int)ftolerance; +} + +///////////////////////////////////////////////////////// +// clearMess +// +///////////////////////////////////////////////////////// +void pix_opencv_haarcascade :: clearMess (void) +{ + int i; + + for ( i=0; ix_xmark[i] = -1; + this->x_ymark[i] = -1; + this->x_found[i] = this->x_ftolerance; + } +} + +///////////////////////////////////////////////////////// +// static member function +// +///////////////////////////////////////////////////////// +void pix_opencv_haarcascade :: obj_setupCallback(t_class *classPtr) +{ + class_addmethod(classPtr, (t_method)&pix_opencv_haarcascade::scaleFactorMessCallback, + gensym("scale_factor"), A_FLOAT, A_NULL); + class_addmethod(classPtr, (t_method)&pix_opencv_haarcascade::minNeighborsMessCallback, + gensym("min_neighbors"), A_FLOAT, A_NULL); + class_addmethod(classPtr, (t_method)&pix_opencv_haarcascade::modeMessCallback, + gensym("mode"), A_FLOAT, A_NULL); + class_addmethod(classPtr, (t_method)&pix_opencv_haarcascade::minSizeMessCallback, + gensym("min_size"), A_FLOAT, A_NULL); + class_addmethod(classPtr, (t_method)&pix_opencv_haarcascade::loadCascadeMessCallback, + gensym("load"), A_SYMBOL, A_NULL); + class_addmethod(classPtr, (t_method)&pix_opencv_haarcascade::fToleranceMessCallback, + gensym("ftolerance"), A_FLOAT, A_NULL); + class_addmethod(classPtr, (t_method)&pix_opencv_haarcascade::clearMessCallback, + gensym("clear"), A_NULL); +} +void pix_opencv_haarcascade :: scaleFactorMessCallback(void *data, t_floatarg scale_factor) +{ + if (scale_factor>1) GetMyClass(data)->scaleFactorMess((float)scale_factor); +} +void pix_opencv_haarcascade :: minNeighborsMessCallback(void *data, t_floatarg min_neighbors) +{ + if (min_neighbors>=1) GetMyClass(data)->minNeighborsMess((float)min_neighbors); +} +void pix_opencv_haarcascade :: modeMessCallback(void *data, t_floatarg mode) +{ + if ((mode==0)||(mode==1)) GetMyClass(data)->modeMess((float)mode); +} +void pix_opencv_haarcascade :: minSizeMessCallback(void *data, t_floatarg min_size) +{ + if (min_size>1) GetMyClass(data)->minSizeMess((float)min_size); +} +void pix_opencv_haarcascade :: fToleranceMessCallback(void *data, t_floatarg ftolerance) +{ + if (ftolerance>1) GetMyClass(data)->fToleranceMess((float)ftolerance); +} +void pix_opencv_haarcascade :: clearMessCallback(void *data) +{ + GetMyClass(data)->clearMess(); +} +void pix_opencv_haarcascade :: loadCascadeMessCallback(void *data, t_symbol* filename) +{ + GetMyClass(data)->loadCascadeMess(filename); +} +void pix_opencv_haarcascade :: loadCascadeMess(t_symbol *filename) +{ + cascade = (CvHaarClassifierCascade*)cvLoad( filename->s_name, 0, 0, 0 ); + if( !cascade ) + { + post( "ERROR: Could not load classifier cascade" ); + } + else post( "Loaded classifier cascade from %s", filename->s_name ); +} +int pix_opencv_haarcascade :: mark(float fx, float fy ) +{ + int i; + + if ( ( fx < 0.0 ) || ( fx > this->rgba->width ) || ( fy < 0 ) || ( fy > this->rgba->height ) ) + { + return -1; + } + + for ( i=0; ix_xmark[i] == -1 ) + { + this->x_xmark[i] = (int)fx; + this->x_ymark[i] = (int)fy; + this->x_found[i] = this->x_ftolerance; + return i; + } + } + + post( "pix_opencv_haarcascade : max markers reached" ); + return -1; +} -- cgit v1.2.1