From e8268332983d8c7c28f868467c0e82f5b35e8511 Mon Sep 17 00:00:00 2001 From: "N.N." Date: Mon, 12 Oct 2009 22:56:45 +0000 Subject: passed everything to c++ for opencv 2.0 svn path=/trunk/externals/pdp_opencv/; revision=12584 --- Makefile | 4 +- Makefile.in | 2 +- pdp_opencv.c | 107 ------ pdp_opencv_athreshold.c | 277 -------------- pdp_opencv_athreshold.cc | 277 ++++++++++++++ pdp_opencv_bgsubstract.c | 292 --------------- pdp_opencv_bgsubstract.cc | 292 +++++++++++++++ pdp_opencv_bm-help.pd | 103 ++++++ pdp_opencv_bm.cc | 327 +++++++++++++++++ pdp_opencv_colorfilt.c | 332 ----------------- pdp_opencv_colorfilt.cc | 329 +++++++++++++++++ pdp_opencv_contours_boundingrect.c | 534 --------------------------- pdp_opencv_contours_boundingrect.cc | 534 +++++++++++++++++++++++++++ pdp_opencv_contours_convexhull.c | 411 --------------------- pdp_opencv_contours_convexhull.cc | 411 +++++++++++++++++++++ pdp_opencv_contours_convexity.c | 455 ----------------------- pdp_opencv_contours_convexity.cc | 455 +++++++++++++++++++++++ pdp_opencv_dft.c | 397 -------------------- pdp_opencv_dft.cc | 397 ++++++++++++++++++++ pdp_opencv_distrans.c | 357 ------------------ pdp_opencv_distrans.cc | 357 ++++++++++++++++++ pdp_opencv_edge.c | 272 -------------- pdp_opencv_edge.cc | 272 ++++++++++++++ pdp_opencv_floodfill.c | 402 --------------------- pdp_opencv_floodfill.cc | 402 +++++++++++++++++++++ pdp_opencv_haarcascade.c | 453 ----------------------- pdp_opencv_haarcascade.cc | 453 +++++++++++++++++++++++ pdp_opencv_hist_compare.c | 401 --------------------- pdp_opencv_hist_compare.cc | 401 +++++++++++++++++++++ pdp_opencv_hu_moments.c | 242 ------------- pdp_opencv_hu_moments.cc | 242 +++++++++++++ pdp_opencv_laplace.c | 248 ------------- pdp_opencv_laplace.cc | 248 +++++++++++++ pdp_opencv_lk.c | 700 ------------------------------------ pdp_opencv_lk.cc | 700 ++++++++++++++++++++++++++++++++++++ pdp_opencv_morphology.c | 299 --------------- pdp_opencv_morphology.cc | 299 +++++++++++++++ pdp_opencv_motempl.c | 468 ------------------------ pdp_opencv_motempl.cc | 468 ++++++++++++++++++++++++ pdp_opencv_threshold.c | 267 -------------- pdp_opencv_threshold.cc | 267 ++++++++++++++ 41 files changed, 7237 insertions(+), 6917 deletions(-) delete mode 100644 pdp_opencv.c delete mode 100644 pdp_opencv_athreshold.c create mode 100755 pdp_opencv_athreshold.cc delete mode 100644 pdp_opencv_bgsubstract.c create mode 100755 pdp_opencv_bgsubstract.cc create mode 100755 pdp_opencv_bm-help.pd create mode 100755 pdp_opencv_bm.cc delete mode 100755 pdp_opencv_colorfilt.c create mode 100755 pdp_opencv_colorfilt.cc delete mode 100644 pdp_opencv_contours_boundingrect.c create mode 100755 pdp_opencv_contours_boundingrect.cc delete mode 100644 pdp_opencv_contours_convexhull.c create mode 100644 pdp_opencv_contours_convexhull.cc delete mode 100644 pdp_opencv_contours_convexity.c create mode 100755 pdp_opencv_contours_convexity.cc delete mode 100755 pdp_opencv_dft.c create mode 100755 pdp_opencv_dft.cc delete mode 100644 pdp_opencv_distrans.c create mode 100755 pdp_opencv_distrans.cc delete mode 100644 pdp_opencv_edge.c create mode 100755 pdp_opencv_edge.cc delete mode 100644 pdp_opencv_floodfill.c create mode 100755 pdp_opencv_floodfill.cc delete mode 100644 pdp_opencv_haarcascade.c create mode 100755 pdp_opencv_haarcascade.cc delete mode 100644 pdp_opencv_hist_compare.c create mode 100755 pdp_opencv_hist_compare.cc delete mode 100755 pdp_opencv_hu_moments.c create mode 100755 pdp_opencv_hu_moments.cc delete mode 100644 pdp_opencv_laplace.c create mode 100755 pdp_opencv_laplace.cc delete mode 100644 pdp_opencv_lk.c create mode 100755 pdp_opencv_lk.cc delete mode 100644 pdp_opencv_morphology.c create mode 100755 pdp_opencv_morphology.cc delete mode 100644 pdp_opencv_motempl.c create mode 100755 pdp_opencv_motempl.cc delete mode 100644 pdp_opencv_threshold.c create mode 100755 pdp_opencv_threshold.cc diff --git a/Makefile b/Makefile index a0815c2..208e59a 100644 --- a/Makefile +++ b/Makefile @@ -18,7 +18,7 @@ ifeq ($(UNAME),Linux) EXTENSION = pd_linux endif ifeq ($(UNAME),Darwin) - INCLUDES += -I/System/Library/Frameworks/OpenCV.framework/Headers/ + INCLUDES += -I/Library/Frameworks/OpenCV.framework/Headers/ LDFLAGS = -bundle -undefined dynamic_lookup LIBS = -lm -framework OpenCV EXTENSION = pd_darwin @@ -26,7 +26,7 @@ endif .SUFFIXES = $(EXTENSION) -SOURCES = pdp_opencv_threshold.c pdp_opencv_edge.c pdp_opencv_distrans.c pdp_opencv_laplace.c pdp_opencv_motempl.c pdp_opencv_morphology.c pdp_opencv_haarcascade.c pdp_opencv_contours_convexity.c pdp_opencv_contours_boundingrect.c pdp_opencv_bgsubstract.c pdp_opencv_lk.c pdp_opencv_floodfill.c pdp_opencv_hist_compare.c pdp_opencv_dft.c pdp_opencv_knear.cc pdp_opencv_hu_moments.c pdp_opencv_hu_compare.cc pdp_opencv_pgh_compare.cc pdp_opencv_bgstats.cc pdp_opencv_athreshold.c pdp_opencv_hough_lines.cc pdp_opencv_channels.cc pdp_opencv_hough_circles.cc pdp_opencv_camshift.cc pdp_opencv_colorfilt.c pdp_opencv_contours_convexhull.c +SOURCES = pdp_opencv_threshold.cc pdp_opencv_edge.cc pdp_opencv_distrans.cc pdp_opencv_laplace.cc pdp_opencv_motempl.cc pdp_opencv_morphology.cc pdp_opencv_haarcascade.cc pdp_opencv_contours_convexity.cc pdp_opencv_contours_boundingrect.cc pdp_opencv_bgsubstract.cc pdp_opencv_lk.cc pdp_opencv_floodfill.cc pdp_opencv_hist_compare.cc pdp_opencv_dft.cc pdp_opencv_knear.cc pdp_opencv_hu_moments.cc pdp_opencv_hu_compare.cc pdp_opencv_pgh_compare.cc pdp_opencv_bgstats.cc pdp_opencv_athreshold.cc pdp_opencv_hough_lines.cc pdp_opencv_channels.cc pdp_opencv_hough_circles.cc pdp_opencv_camshift.cc pdp_opencv_colorfilt.cc pdp_opencv_contours_convexhull.cc pdp_opencv_bm.cc SOURCES_OPT = pdp_opencv_surf.cc all: $(SOURCES:.c=.$(EXTENSION)) $(SOURCES:.cc=.$(EXTENSION)) $(SOURCES_OPT:.c=.$(EXTENSION)) $(SOURCES_OPT:.cc=.$(EXTENSION)) diff --git a/Makefile.in b/Makefile.in index 49e352e..4bed297 100755 --- a/Makefile.in +++ b/Makefile.in @@ -26,7 +26,7 @@ endif .SUFFIXES = $(EXTENSION) -SOURCES = pdp_opencv_threshold.c pdp_opencv_edge.c pdp_opencv_distrans.c pdp_opencv_laplace.c pdp_opencv_motempl.c pdp_opencv_morphology.c pdp_opencv_haarcascade.c pdp_opencv_contours_convexity.c pdp_opencv_contours_boundingrect.c pdp_opencv_bgsubstract.c pdp_opencv_lk.c pdp_opencv_floodfill.c pdp_opencv_hist_compare.c pdp_opencv_dft.c pdp_opencv_knear.cc pdp_opencv_hu_moments.c pdp_opencv_hu_compare.cc pdp_opencv_pgh_compare.cc pdp_opencv_bgstats.cc pdp_opencv_athreshold.c pdp_opencv_hough_lines.cc pdp_opencv_channels.cc pdp_opencv_hough_circles.cc pdp_opencv_camshift.cc pdp_opencv_colorfilt.c pdp_opencv_contours_convexhull.c +SOURCES = pdp_opencv_threshold.cc pdp_opencv_edge.cc pdp_opencv_distrans.cc pdp_opencv_laplace.cc pdp_opencv_motempl.cc pdp_opencv_morphology.cc pdp_opencv_haarcascade.cc pdp_opencv_contours_convexity.cc pdp_opencv_contours_boundingrect.cc pdp_opencv_bgsubstract.cc pdp_opencv_lk.cc pdp_opencv_floodfill.cc pdp_opencv_hist_compare.cc pdp_opencv_dft.cc pdp_opencv_knear.cc pdp_opencv_hu_moments.cc pdp_opencv_hu_compare.cc pdp_opencv_pgh_compare.cc pdp_opencv_bgstats.cc pdp_opencv_athreshold.cc pdp_opencv_hough_lines.cc pdp_opencv_channels.cc pdp_opencv_hough_circles.cc pdp_opencv_camshift.cc pdp_opencv_colorfilt.cc pdp_opencv_contours_convexhull.cc pdp_opencv_bm.cc SOURCES_OPT = @SOURCES_OPT@ all: $(SOURCES:.c=.$(EXTENSION)) $(SOURCES:.cc=.$(EXTENSION)) $(SOURCES_OPT:.c=.$(EXTENSION)) $(SOURCES_OPT:.cc=.$(EXTENSION)) diff --git a/pdp_opencv.c b/pdp_opencv.c deleted file mode 100644 index 59a2ea9..0000000 --- a/pdp_opencv.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Pure Data Packet system implementation: setup code - * Copyright (c) by Tom Schouten - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include -#include - -static int pdp_opencv_initialized = 0; - -/* all symbols are C style */ -#ifdef __cplusplus -extern "C" -{ -#endif - -void pdp_opencv_edge_setup(void); -void pdp_opencv_threshold_setup(void); -void pdp_opencv_bgsubstract_setup(void); -void pdp_opencv_distrans_setup(void); -void pdp_opencv_laplace_setup(void); -void pdp_opencv_motempl_setup(void); -void pdp_opencv_morphology_setup(void); -void pdp_opencv_haarcascade_setup(void); -void pdp_opencv_floodfill_setup(void); -void pdp_opencv_contours_convexity_setup(void); -void pdp_opencv_contours_boundingrect_setup(void); -void pdp_opencv_lk_setup(void); -void pdp_opencv_dft_setup(void); -void pdp_opencv_knear_setup(void); -void pdp_opencv_hu_moments_setup(void); -void pdp_opencv_hu_compare_setup(void); -void pdp_opencv_pgh_compare_setup(void); -void pdp_opencv_bgstats_setup(void); -void pdp_opencv_surf_setup(void); -void pdp_opencv_lk_setup(void); -void pdp_opencv_athreshold_setup(void); -void pdp_opencv_channels_setup(void); -void pdp_opencv_hough_lines_setup(void); -void pdp_opencv_hough_circles_setup(void); -void pdp_opencv_camshift_setup(void); - - - -/* library setup routine */ -void pdp_opencv_setup(void){ - - if (pdp_opencv_initialized) return; - - /* babble */ -#ifdef PDP_CV_VERSION - post("PDP_opencv: pure data packet openCV wrapper version " PDP_CV_VERSION ); -#else - post ("PDP_opencv: pure data packet openCV wrapper"); -#endif - - - /* setup pdp_opencv system */ - pdp_opencv_edge_setup(); - pdp_opencv_threshold_setup(); - pdp_opencv_bgsubstract_setup(); - pdp_opencv_distrans_setup(); - pdp_opencv_laplace_setup(); - pdp_opencv_motempl_setup(); - pdp_opencv_morphology_setup(); - pdp_opencv_haarcascade_setup(); - pdp_opencv_floodfill_setup(); - pdp_opencv_contours_convexity_setup(); - pdp_opencv_contours_boundingrect_setup(); - pdp_opencv_lk_setup(); - pdp_opencv_dft_setup(); - pdp_opencv_knear_setup(); - pdp_opencv_hu_moments_setup(); - pdp_opencv_hu_compare_setup(); - pdp_opencv_pgh_compare_setup(); - pdp_opencv_bgstats_setup(); - pdp_opencv_surf_setup(); - pdp_opencv_lk_setup(); - pdp_opencv_athreshold_setup(); - pdp_opencv_channels_setup(); - pdp_opencv_hough_lines_setup(); - pdp_opencv_hough_circles_setup(); - pdp_opencv_camshift_setup(); - - pdp_opencv_initialized++; - - -} - -#ifdef __cplusplus -} -#endif diff --git a/pdp_opencv_athreshold.c b/pdp_opencv_athreshold.c deleted file mode 100644 index ac7c9c2..0000000 --- a/pdp_opencv_athreshold.c +++ /dev/null @@ -1,277 +0,0 @@ -/* - * Pure Data Packet module. - * Copyright (c) by Tom Schouten - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include -#include -#include -#include -#include -#include - -#include "pdp.h" - -#ifndef _EiC -#include "cv.h" -#endif - - - -typedef struct pdp_opencv_athreshold_struct -{ - t_object x_obj; - t_float x_f; - - t_outlet *x_outlet0; - int x_packet0; - int x_packet1; - int x_dropped; - int x_queue_id; - - int x_width; - int x_height; - int x_size; - - int x_infosok; - - int max_value; - int x_threshold_mode; - int x_threshold_method; - int x_blocksize; - int x_dim; - IplImage *image, *gray; - - -} t_pdp_opencv_athreshold; - -static void pdp_opencv_athreshold_process_rgb(t_pdp_opencv_athreshold *x) -{ - t_pdp *header = pdp_packet_header(x->x_packet0); - short int *data = (short int *)pdp_packet_data(x->x_packet0); - t_pdp *newheader = pdp_packet_header(x->x_packet1); - short int *newdata = (short int *)pdp_packet_data(x->x_packet1); - - if ((x->x_width != (t_int)header->info.image.width) || - (x->x_height != (t_int)header->info.image.height)) - { - - post("pdp_opencv_athreshold :: resizing plugins"); - - x->x_width = header->info.image.width; - x->x_height = header->info.image.height; - x->x_size = x->x_width*x->x_height; - - //Destroy cv_images - cvReleaseImage(&x->image); - cvReleaseImage(&x->gray); - - //create the orig image with new size - x->image = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 3); - - // Create the output images with new sizes - x->gray = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 1); - - } - - newheader->info.image.encoding = header->info.image.encoding; - newheader->info.image.width = x->x_width; - newheader->info.image.height = x->x_height; - - memcpy( newdata, data, x->x_size*3 ); - - memcpy( x->image->imageData, data, x->x_size*3 ); - - // Convert to grayscale - cvCvtColor(x->image, x->gray, CV_BGR2GRAY); - - // Applies fixed-level thresholding to single-channel array. - switch(x->x_threshold_mode) { - case 0: - cvAdaptiveThreshold(x->gray, x->gray, (float)x->max_value, x->x_threshold_method, CV_THRESH_BINARY, x->x_blocksize, x->x_dim); - break; - case 1: - cvAdaptiveThreshold(x->gray, x->gray, (float)x->max_value, x->x_threshold_method, CV_THRESH_BINARY_INV, x->x_blocksize, x->x_dim); - break; - } - - cvCvtColor(x->gray, x->image, CV_GRAY2BGR); - memcpy( newdata, x->image->imageData, x->x_size*3 ); - - return; -} - -static void pdp_opencv_athreshold_max(t_pdp_opencv_athreshold *x, t_floatarg f) -{ - if ( (int)f>0 ) x->max_value = (int)f; -} - -static void pdp_opencv_athreshold_mode(t_pdp_opencv_athreshold *x, t_floatarg f) -{ - if ( ( (int)f==0 ) || ( (int)f==1 ) ) x->x_threshold_mode = (int)f; -} - -static void pdp_opencv_athreshold_method(t_pdp_opencv_athreshold *x, t_floatarg f) -{ - if ( (int)f==CV_ADAPTIVE_THRESH_MEAN_C ) x->x_threshold_method = CV_ADAPTIVE_THRESH_MEAN_C; - if ( (int)f==CV_ADAPTIVE_THRESH_GAUSSIAN_C ) x->x_threshold_method = CV_ADAPTIVE_THRESH_GAUSSIAN_C; -} - -static void pdp_opencv_athreshold_blocksize(t_pdp_opencv_athreshold *x, t_floatarg f) -{ - if ( ( (int)f>=3 ) && ( (int)(f+1)%2 == 0 ) ) - { - x->x_blocksize = (int)f; - } -} - -static void pdp_opencv_athreshold_dim(t_pdp_opencv_athreshold *x, t_floatarg f) -{ - x->x_dim = (int)f; -} - -static void pdp_opencv_athreshold_sendpacket(t_pdp_opencv_athreshold *x) -{ - /* release the packet */ - pdp_packet_mark_unused(x->x_packet0); - x->x_packet0 = -1; - - /* unregister and propagate if valid dest packet */ - pdp_packet_pass_if_valid(x->x_outlet0, &x->x_packet1); -} - -static void pdp_opencv_athreshold_process(t_pdp_opencv_athreshold *x) -{ - int encoding; - t_pdp *header = 0; - char *parname; - unsigned pi; - int partype; - float pardefault; - t_atom plist[2]; - t_atom tlist[2]; - t_atom vlist[2]; - - /* check if image data packets are compatible */ - if ( (header = pdp_packet_header(x->x_packet0)) - && (PDP_BITMAP == header->type)){ - - /* pdp_opencv_athreshold_process inputs and write into active inlet */ - switch(pdp_packet_header(x->x_packet0)->info.image.encoding){ - - case PDP_BITMAP_RGB: - x->x_packet1 = pdp_packet_clone_rw(x->x_packet0); - pdp_queue_add(x, pdp_opencv_athreshold_process_rgb, pdp_opencv_athreshold_sendpacket, &x->x_queue_id); - break; - - default: - /* don't know the type, so dont pdp_opencv_athreshold_process */ - break; - - } - } - -} - -static void pdp_opencv_athreshold_input_0(t_pdp_opencv_athreshold *x, t_symbol *s, t_floatarg f) -{ - /* if this is a register_ro message or register_rw message, register with packet factory */ - - if (s == gensym("register_rw")) - x->x_dropped = pdp_packet_convert_ro_or_drop(&x->x_packet0, (int)f, pdp_gensym("bitmap/rgb/*") ); - - if ((s == gensym("process")) && (-1 != x->x_packet0) && (!x->x_dropped)) - { - /* add the process method and callback to the process queue */ - pdp_opencv_athreshold_process(x); - } -} - -static void pdp_opencv_athreshold_free(t_pdp_opencv_athreshold *x) -{ - int i; - - pdp_queue_finish(x->x_queue_id); - pdp_packet_mark_unused(x->x_packet0); - - //Destroy cv_images - cvReleaseImage(&x->image); - cvReleaseImage(&x->gray); -} - -t_class *pdp_opencv_athreshold_class; - -void *pdp_opencv_athreshold_new(t_floatarg f) -{ - int i; - - t_pdp_opencv_athreshold *x = (t_pdp_opencv_athreshold *)pd_new(pdp_opencv_athreshold_class); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("max_value")); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("blocksize")); - - x->x_outlet0 = outlet_new(&x->x_obj, &s_anything); - - x->x_packet0 = -1; - x->x_packet1 = -1; - x->x_queue_id = -1; - - x->x_width = 320; - x->x_height = 240; - x->x_size = x->x_width * x->x_height; - - x->x_infosok = 0; - - x->max_value = 255; - x->x_threshold_mode = 0; - x->x_threshold_method = CV_ADAPTIVE_THRESH_MEAN_C; - x->x_blocksize = 3; - x->x_dim = 0; - - x->image = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 3); - x->gray = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 1); - - return (void *)x; -} - - -#ifdef __cplusplus -extern "C" -{ -#endif - - -void pdp_opencv_athreshold_setup(void) -{ - - post( " pdp_opencv_athreshold"); - pdp_opencv_athreshold_class = class_new(gensym("pdp_opencv_athreshold"), (t_newmethod)pdp_opencv_athreshold_new, - (t_method)pdp_opencv_athreshold_free, sizeof(t_pdp_opencv_athreshold), 0, A_DEFFLOAT, A_NULL); - - class_addmethod(pdp_opencv_athreshold_class, (t_method)pdp_opencv_athreshold_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL); - class_addmethod(pdp_opencv_athreshold_class, (t_method)pdp_opencv_athreshold_max, gensym("max_value"), A_FLOAT, A_NULL ); - class_addmethod(pdp_opencv_athreshold_class, (t_method)pdp_opencv_athreshold_mode, gensym("mode"), A_FLOAT, A_NULL ); - class_addmethod(pdp_opencv_athreshold_class, (t_method)pdp_opencv_athreshold_method, gensym("method"), A_FLOAT, A_NULL ); - class_addmethod(pdp_opencv_athreshold_class, (t_method)pdp_opencv_athreshold_blocksize, gensym("blocksize"), A_FLOAT, A_NULL ); - class_addmethod(pdp_opencv_athreshold_class, (t_method)pdp_opencv_athreshold_dim, gensym("dim"), A_FLOAT, A_NULL ); - - -} - -#ifdef __cplusplus -} -#endif diff --git a/pdp_opencv_athreshold.cc b/pdp_opencv_athreshold.cc new file mode 100755 index 0000000..f43c556 --- /dev/null +++ b/pdp_opencv_athreshold.cc @@ -0,0 +1,277 @@ +/* + * Pure Data Packet module. + * Copyright (c) by Tom Schouten + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include + +#include "pdp.h" + +#ifndef _EiC +#include "cv.h" +#endif + + + +typedef struct pdp_opencv_athreshold_struct +{ + t_object x_obj; + t_float x_f; + + t_outlet *x_outlet0; + int x_packet0; + int x_packet1; + int x_dropped; + int x_queue_id; + + int x_width; + int x_height; + int x_size; + + int x_infosok; + + int max_value; + int x_threshold_mode; + int x_threshold_method; + int x_blocksize; + int x_dim; + IplImage *image, *gray; + + +} t_pdp_opencv_athreshold; + +static void pdp_opencv_athreshold_process_rgb(t_pdp_opencv_athreshold *x) +{ + t_pdp *header = pdp_packet_header(x->x_packet0); + short int *data = (short int *)pdp_packet_data(x->x_packet0); + t_pdp *newheader = pdp_packet_header(x->x_packet1); + short int *newdata = (short int *)pdp_packet_data(x->x_packet1); + + if ((x->x_width != (t_int)header->info.image.width) || + (x->x_height != (t_int)header->info.image.height)) + { + + post("pdp_opencv_athreshold :: resizing plugins"); + + x->x_width = header->info.image.width; + x->x_height = header->info.image.height; + x->x_size = x->x_width*x->x_height; + + //Destroy cv_images + cvReleaseImage(&x->image); + cvReleaseImage(&x->gray); + + //create the orig image with new size + x->image = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 3); + + // Create the output images with new sizes + x->gray = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 1); + + } + + newheader->info.image.encoding = header->info.image.encoding; + newheader->info.image.width = x->x_width; + newheader->info.image.height = x->x_height; + + memcpy( newdata, data, x->x_size*3 ); + + memcpy( x->image->imageData, data, x->x_size*3 ); + + // Convert to grayscale + cvCvtColor(x->image, x->gray, CV_BGR2GRAY); + + // Applies fixed-level thresholding to single-channel array. + switch(x->x_threshold_mode) { + case 0: + cvAdaptiveThreshold(x->gray, x->gray, (float)x->max_value, x->x_threshold_method, CV_THRESH_BINARY, x->x_blocksize, x->x_dim); + break; + case 1: + cvAdaptiveThreshold(x->gray, x->gray, (float)x->max_value, x->x_threshold_method, CV_THRESH_BINARY_INV, x->x_blocksize, x->x_dim); + break; + } + + cvCvtColor(x->gray, x->image, CV_GRAY2BGR); + memcpy( newdata, x->image->imageData, x->x_size*3 ); + + return; +} + +static void pdp_opencv_athreshold_max(t_pdp_opencv_athreshold *x, t_floatarg f) +{ + if ( (int)f>0 ) x->max_value = (int)f; +} + +static void pdp_opencv_athreshold_mode(t_pdp_opencv_athreshold *x, t_floatarg f) +{ + if ( ( (int)f==0 ) || ( (int)f==1 ) ) x->x_threshold_mode = (int)f; +} + +static void pdp_opencv_athreshold_method(t_pdp_opencv_athreshold *x, t_floatarg f) +{ + if ( (int)f==CV_ADAPTIVE_THRESH_MEAN_C ) x->x_threshold_method = CV_ADAPTIVE_THRESH_MEAN_C; + if ( (int)f==CV_ADAPTIVE_THRESH_GAUSSIAN_C ) x->x_threshold_method = CV_ADAPTIVE_THRESH_GAUSSIAN_C; +} + +static void pdp_opencv_athreshold_blocksize(t_pdp_opencv_athreshold *x, t_floatarg f) +{ + if ( ( (int)f>=3 ) && ( (int)(f+1)%2 == 0 ) ) + { + x->x_blocksize = (int)f; + } +} + +static void pdp_opencv_athreshold_dim(t_pdp_opencv_athreshold *x, t_floatarg f) +{ + x->x_dim = (int)f; +} + +static void pdp_opencv_athreshold_sendpacket(t_pdp_opencv_athreshold *x) +{ + /* release the packet */ + pdp_packet_mark_unused(x->x_packet0); + x->x_packet0 = -1; + + /* unregister and propagate if valid dest packet */ + pdp_packet_pass_if_valid(x->x_outlet0, &x->x_packet1); +} + +static void pdp_opencv_athreshold_process(t_pdp_opencv_athreshold *x) +{ + int encoding; + t_pdp *header = 0; + char *parname; + unsigned pi; + int partype; + float pardefault; + t_atom plist[2]; + t_atom tlist[2]; + t_atom vlist[2]; + + /* check if image data packets are compatible */ + if ( (header = pdp_packet_header(x->x_packet0)) + && (PDP_BITMAP == header->type)){ + + /* pdp_opencv_athreshold_process inputs and write into active inlet */ + switch(pdp_packet_header(x->x_packet0)->info.image.encoding){ + + case PDP_BITMAP_RGB: + x->x_packet1 = pdp_packet_clone_rw(x->x_packet0); + pdp_queue_add(x, (void*)pdp_opencv_athreshold_process_rgb, (void*)pdp_opencv_athreshold_sendpacket, &x->x_queue_id); + break; + + default: + /* don't know the type, so dont pdp_opencv_athreshold_process */ + break; + + } + } + +} + +static void pdp_opencv_athreshold_input_0(t_pdp_opencv_athreshold *x, t_symbol *s, t_floatarg f) +{ + /* if this is a register_ro message or register_rw message, register with packet factory */ + + if (s == gensym("register_rw")) + x->x_dropped = pdp_packet_convert_ro_or_drop(&x->x_packet0, (int)f, pdp_gensym((char*)"bitmap/rgb/*") ); + + if ((s == gensym("process")) && (-1 != x->x_packet0) && (!x->x_dropped)) + { + /* add the process method and callback to the process queue */ + pdp_opencv_athreshold_process(x); + } +} + +static void pdp_opencv_athreshold_free(t_pdp_opencv_athreshold *x) +{ + int i; + + pdp_queue_finish(x->x_queue_id); + pdp_packet_mark_unused(x->x_packet0); + + //Destroy cv_images + cvReleaseImage(&x->image); + cvReleaseImage(&x->gray); +} + +t_class *pdp_opencv_athreshold_class; + +void *pdp_opencv_athreshold_new(t_floatarg f) +{ + int i; + + t_pdp_opencv_athreshold *x = (t_pdp_opencv_athreshold *)pd_new(pdp_opencv_athreshold_class); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("max_value")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("blocksize")); + + x->x_outlet0 = outlet_new(&x->x_obj, &s_anything); + + x->x_packet0 = -1; + x->x_packet1 = -1; + x->x_queue_id = -1; + + x->x_width = 320; + x->x_height = 240; + x->x_size = x->x_width * x->x_height; + + x->x_infosok = 0; + + x->max_value = 255; + x->x_threshold_mode = 0; + x->x_threshold_method = CV_ADAPTIVE_THRESH_MEAN_C; + x->x_blocksize = 3; + x->x_dim = 0; + + x->image = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 3); + x->gray = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 1); + + return (void *)x; +} + + +#ifdef __cplusplus +extern "C" +{ +#endif + + +void pdp_opencv_athreshold_setup(void) +{ + + post( " pdp_opencv_athreshold"); + pdp_opencv_athreshold_class = class_new(gensym("pdp_opencv_athreshold"), (t_newmethod)pdp_opencv_athreshold_new, + (t_method)pdp_opencv_athreshold_free, sizeof(t_pdp_opencv_athreshold), 0, A_DEFFLOAT, A_NULL); + + class_addmethod(pdp_opencv_athreshold_class, (t_method)pdp_opencv_athreshold_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL); + class_addmethod(pdp_opencv_athreshold_class, (t_method)pdp_opencv_athreshold_max, gensym("max_value"), A_FLOAT, A_NULL ); + class_addmethod(pdp_opencv_athreshold_class, (t_method)pdp_opencv_athreshold_mode, gensym("mode"), A_FLOAT, A_NULL ); + class_addmethod(pdp_opencv_athreshold_class, (t_method)pdp_opencv_athreshold_method, gensym("method"), A_FLOAT, A_NULL ); + class_addmethod(pdp_opencv_athreshold_class, (t_method)pdp_opencv_athreshold_blocksize, gensym("blocksize"), A_FLOAT, A_NULL ); + class_addmethod(pdp_opencv_athreshold_class, (t_method)pdp_opencv_athreshold_dim, gensym("dim"), A_FLOAT, A_NULL ); + + +} + +#ifdef __cplusplus +} +#endif diff --git a/pdp_opencv_bgsubstract.c b/pdp_opencv_bgsubstract.c deleted file mode 100644 index 1895a82..0000000 --- a/pdp_opencv_bgsubstract.c +++ /dev/null @@ -1,292 +0,0 @@ -/* - * Pure Data Packet module. - * Copyright (c) by Tom Schouten - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include -#include -#include -#include -#include -#include - -#include "pdp.h" - -#ifndef _EiC -#include "cv.h" -#include "cvaux.h" -#endif - - -typedef struct pdp_opencv_bgsubstract_struct -{ - t_object x_obj; - t_float x_f; - - t_outlet *x_outlet0; - int x_packet0; - int x_packet1; - int x_dropped; - int x_queue_id; - - int x_width; - int x_height; - int x_size; - - int x_infosok; - int x_set; - int x_threshold; - - IplImage *image, *prev_image, *gray, *grayLow, *grayUp, *diff_8U; - -} t_pdp_opencv_bgsubstract; - -static void pdp_opencv_bgsubstract_process_rgb(t_pdp_opencv_bgsubstract *x) -{ - t_pdp *header = pdp_packet_header(x->x_packet0); - short int *data = (short int *)pdp_packet_data(x->x_packet0); - t_pdp *newheader = pdp_packet_header(x->x_packet1); - short int *newdata = (short int *)pdp_packet_data(x->x_packet1); - - - if ((x->x_width != (t_int)header->info.image.width) || - (x->x_height != (t_int)header->info.image.height)) - { - - post("pdp_opencv_bgsubstract :: resizing plugins"); - - x->x_width = header->info.image.width; - x->x_height = header->info.image.height; - x->x_size = x->x_width*x->x_height; - - //Destroy cv_images - cvReleaseImage(&x->image); - cvReleaseImage(&x->gray); - cvReleaseImage(&x->grayLow); - cvReleaseImage(&x->grayUp); - cvReleaseImage(&x->prev_image); - cvReleaseImage(&x->diff_8U); - - //create the orig image with new size - x->image = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 3); - // Create the output and temp images with new sizes - x->gray = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 1); - x->grayLow = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 1); - x->grayUp = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 1); - x->prev_image = cvCreateImage( cvSize(x->image->width,x->image->height), 8, 3 ); - x->diff_8U = cvCreateImage( cvSize(x->image->width,x->image->height), 8, 1 ); - } - - newheader->info.image.encoding = header->info.image.encoding; - newheader->info.image.width = x->x_width; - newheader->info.image.height = x->x_height; - - memcpy( newdata, data, x->x_size*3 ); - - // 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( x->image->imageData, data, x->x_size*3 ); - - //cvCvtColor( x->image, x->gray, CV_BGR2GRAY ); - - if (x->x_set) { - memcpy( x->prev_image->imageData, data, x->x_size*3 ); - x->x_set=0; - } - - //cvSubS (x->prev_image,cvScalar(x->x_threshold,x->x_threshold,x->x_threshold,x->x_threshold),x->grayLow,NULL); - //cvAddS (x->prev_image,cvScalar(x->x_threshold,x->x_threshold,x->x_threshold,x->x_threshold),x->grayUp,NULL); - //cvInRange (x->gray, x->grayLow, x->grayUp, x->diff_8U); - - //cvNot (x->diff_8U,x->diff_8U); - - //cvCvtColor(x->diff_8U,x->image,CV_GRAY2BGR); - - int h,w,hlength, chRed, chGreen, chBlue; - long src,pixsize; - - chRed =0; - chGreen =1; - chBlue =2; - - src = 0; - - - for (h=0; himage->height; h++){ - for(w=0; wimage->width; w++){ - if (((x->image->imageData[src+chRed ] > x->prev_image->imageData[src+chRed ] - x->x_threshold)&& - (x->image->imageData[src+chRed ] < x->prev_image->imageData[src+chRed ] + x->x_threshold))&& - ((x->image->imageData[src+chGreen] > x->prev_image->imageData[src+chGreen] - x->x_threshold)&& - (x->image->imageData[src+chGreen] < x->prev_image->imageData[src+chGreen] + x->x_threshold))&& - ((x->image->imageData[src+chBlue ] > x->prev_image->imageData[src+chBlue ] - x->x_threshold)&& - (x->image->imageData[src+chBlue ] < x->prev_image->imageData[src+chBlue ] + x->x_threshold))) - { - x->image->imageData[src+chRed] = 0; - x->image->imageData[src+chGreen] = 0; - x->image->imageData[src+chBlue] = 0; - } - src+=3; - } - } - - - memcpy( newdata, x->image->imageData, x->x_size*3 ); - - return; -} - -static void pdp_opencv_bgsubstract_threshold(t_pdp_opencv_bgsubstract *x, t_floatarg f) -{ - if (f>=1) x->x_threshold=(int)f; -} - -static void pdp_opencv_bgsubstract_set(t_pdp_opencv_bgsubstract *x) -{ - x->x_set=1; -} - -static void pdp_opencv_bgsubstract_sendpacket(t_pdp_opencv_bgsubstract *x) -{ - /* release the packet */ - pdp_packet_mark_unused(x->x_packet0); - x->x_packet0 = -1; - - /* unregister and propagate if valid dest packet */ - pdp_packet_pass_if_valid(x->x_outlet0, &x->x_packet1); -} - -static void pdp_opencv_bgsubstract_process(t_pdp_opencv_bgsubstract *x) -{ - int encoding; - t_pdp *header = 0; - char *parname; - unsigned pi; - int partype; - float pardefault; - t_atom plist[2]; - t_atom tlist[2]; - t_atom vlist[2]; - - /* check if image data packets are compatible */ - if ( (header = pdp_packet_header(x->x_packet0)) - && (PDP_BITMAP == header->type)){ - - /* pdp_opencv_bgsubstract_process inputs and write into active inlet */ - switch(pdp_packet_header(x->x_packet0)->info.image.encoding){ - - case PDP_BITMAP_RGB: - x->x_packet1 = pdp_packet_clone_rw(x->x_packet0); - pdp_queue_add(x, pdp_opencv_bgsubstract_process_rgb, pdp_opencv_bgsubstract_sendpacket, &x->x_queue_id); - break; - - default: - /* don't know the type, so dont pdp_opencv_bgsubstract_process */ - break; - - } - } - -} - -static void pdp_opencv_bgsubstract_input_0(t_pdp_opencv_bgsubstract *x, t_symbol *s, t_floatarg f) -{ - /* if this is a register_ro message or register_rw message, register with packet factory */ - - if (s == gensym("register_rw")) - x->x_dropped = pdp_packet_convert_ro_or_drop(&x->x_packet0, (int)f, pdp_gensym("bitmap/rgb/*") ); - - if ((s == gensym("process")) && (-1 != x->x_packet0) && (!x->x_dropped)) - { - /* add the process method and callback to the process queue */ - pdp_opencv_bgsubstract_process(x); - } -} - -static void pdp_opencv_bgsubstract_free(t_pdp_opencv_bgsubstract *x) -{ - int i; - - pdp_queue_finish(x->x_queue_id); - pdp_packet_mark_unused(x->x_packet0); - //cv_freeplugins(x); - - //Destroy cv_images - cvReleaseImage(&x->image); - cvReleaseImage(&x->gray); - cvReleaseImage(&x->grayLow); - cvReleaseImage(&x->grayUp); - cvReleaseImage(&x->prev_image); - cvReleaseImage(&x->diff_8U); -} - -t_class *pdp_opencv_bgsubstract_class; - - -void *pdp_opencv_bgsubstract_new(t_floatarg f) -{ - int i; - - t_pdp_opencv_bgsubstract *x = (t_pdp_opencv_bgsubstract *)pd_new(pdp_opencv_bgsubstract_class); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("threshold")); - - x->x_outlet0 = outlet_new(&x->x_obj, &s_anything); - - x->x_packet0 = -1; - x->x_packet1 = -1; - x->x_queue_id = -1; - - x->x_width = 320; - x->x_height = 240; - x->x_size = x->x_width * x->x_height; - - x->x_infosok = 0; - x->x_set = 1; - x->x_threshold = 13; - - x->image = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 3); - x->gray = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 1); - x->grayLow = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 1); - x->grayUp = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 1); - x->prev_image = cvCreateImage( cvSize(x->image->width,x->image->height), 8, 3 ); - x->diff_8U = cvCreateImage( cvSize(x->image->width,x->image->height), 8, 1 ); - - return (void *)x; -} - - -#ifdef __cplusplus -extern "C" -{ -#endif - - -void pdp_opencv_bgsubstract_setup(void) -{ - - post( " pdp_opencv_bgsubstract"); - pdp_opencv_bgsubstract_class = class_new(gensym("pdp_opencv_bgsubstract"), (t_newmethod)pdp_opencv_bgsubstract_new, - (t_method)pdp_opencv_bgsubstract_free, sizeof(t_pdp_opencv_bgsubstract), 0, A_DEFFLOAT, A_NULL); - - class_addmethod(pdp_opencv_bgsubstract_class, (t_method)pdp_opencv_bgsubstract_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL); - class_addmethod(pdp_opencv_bgsubstract_class, (t_method)pdp_opencv_bgsubstract_set, gensym("set"), A_NULL ); - class_addmethod(pdp_opencv_bgsubstract_class, (t_method)pdp_opencv_bgsubstract_threshold, gensym("threshold"), A_FLOAT, A_NULL ); - -} - -#ifdef __cplusplus -} -#endif diff --git a/pdp_opencv_bgsubstract.cc b/pdp_opencv_bgsubstract.cc new file mode 100755 index 0000000..f28a33a --- /dev/null +++ b/pdp_opencv_bgsubstract.cc @@ -0,0 +1,292 @@ +/* + * Pure Data Packet module. + * Copyright (c) by Tom Schouten + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include + +#include "pdp.h" + +#ifndef _EiC +#include "cv.h" +#include "cvaux.h" +#endif + + +typedef struct pdp_opencv_bgsubstract_struct +{ + t_object x_obj; + t_float x_f; + + t_outlet *x_outlet0; + int x_packet0; + int x_packet1; + int x_dropped; + int x_queue_id; + + int x_width; + int x_height; + int x_size; + + int x_infosok; + int x_set; + int x_threshold; + + IplImage *image, *prev_image, *gray, *grayLow, *grayUp, *diff_8U; + +} t_pdp_opencv_bgsubstract; + +static void pdp_opencv_bgsubstract_process_rgb(t_pdp_opencv_bgsubstract *x) +{ + t_pdp *header = pdp_packet_header(x->x_packet0); + short int *data = (short int *)pdp_packet_data(x->x_packet0); + t_pdp *newheader = pdp_packet_header(x->x_packet1); + short int *newdata = (short int *)pdp_packet_data(x->x_packet1); + + + if ((x->x_width != (t_int)header->info.image.width) || + (x->x_height != (t_int)header->info.image.height)) + { + + post("pdp_opencv_bgsubstract :: resizing plugins"); + + x->x_width = header->info.image.width; + x->x_height = header->info.image.height; + x->x_size = x->x_width*x->x_height; + + //Destroy cv_images + cvReleaseImage(&x->image); + cvReleaseImage(&x->gray); + cvReleaseImage(&x->grayLow); + cvReleaseImage(&x->grayUp); + cvReleaseImage(&x->prev_image); + cvReleaseImage(&x->diff_8U); + + //create the orig image with new size + x->image = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 3); + // Create the output and temp images with new sizes + x->gray = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 1); + x->grayLow = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 1); + x->grayUp = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 1); + x->prev_image = cvCreateImage( cvSize(x->image->width,x->image->height), 8, 3 ); + x->diff_8U = cvCreateImage( cvSize(x->image->width,x->image->height), 8, 1 ); + } + + newheader->info.image.encoding = header->info.image.encoding; + newheader->info.image.width = x->x_width; + newheader->info.image.height = x->x_height; + + memcpy( newdata, data, x->x_size*3 ); + + // 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( x->image->imageData, data, x->x_size*3 ); + + //cvCvtColor( x->image, x->gray, CV_BGR2GRAY ); + + if (x->x_set) { + memcpy( x->prev_image->imageData, data, x->x_size*3 ); + x->x_set=0; + } + + //cvSubS (x->prev_image,cvScalar(x->x_threshold,x->x_threshold,x->x_threshold,x->x_threshold),x->grayLow,NULL); + //cvAddS (x->prev_image,cvScalar(x->x_threshold,x->x_threshold,x->x_threshold,x->x_threshold),x->grayUp,NULL); + //cvInRange (x->gray, x->grayLow, x->grayUp, x->diff_8U); + + //cvNot (x->diff_8U,x->diff_8U); + + //cvCvtColor(x->diff_8U,x->image,CV_GRAY2BGR); + + int h,w,hlength, chRed, chGreen, chBlue; + long src,pixsize; + + chRed =0; + chGreen =1; + chBlue =2; + + src = 0; + + + for (h=0; himage->height; h++){ + for(w=0; wimage->width; w++){ + if (((x->image->imageData[src+chRed ] > x->prev_image->imageData[src+chRed ] - x->x_threshold)&& + (x->image->imageData[src+chRed ] < x->prev_image->imageData[src+chRed ] + x->x_threshold))&& + ((x->image->imageData[src+chGreen] > x->prev_image->imageData[src+chGreen] - x->x_threshold)&& + (x->image->imageData[src+chGreen] < x->prev_image->imageData[src+chGreen] + x->x_threshold))&& + ((x->image->imageData[src+chBlue ] > x->prev_image->imageData[src+chBlue ] - x->x_threshold)&& + (x->image->imageData[src+chBlue ] < x->prev_image->imageData[src+chBlue ] + x->x_threshold))) + { + x->image->imageData[src+chRed] = 0; + x->image->imageData[src+chGreen] = 0; + x->image->imageData[src+chBlue] = 0; + } + src+=3; + } + } + + + memcpy( newdata, x->image->imageData, x->x_size*3 ); + + return; +} + +static void pdp_opencv_bgsubstract_threshold(t_pdp_opencv_bgsubstract *x, t_floatarg f) +{ + if (f>=1) x->x_threshold=(int)f; +} + +static void pdp_opencv_bgsubstract_set(t_pdp_opencv_bgsubstract *x) +{ + x->x_set=1; +} + +static void pdp_opencv_bgsubstract_sendpacket(t_pdp_opencv_bgsubstract *x) +{ + /* release the packet */ + pdp_packet_mark_unused(x->x_packet0); + x->x_packet0 = -1; + + /* unregister and propagate if valid dest packet */ + pdp_packet_pass_if_valid(x->x_outlet0, &x->x_packet1); +} + +static void pdp_opencv_bgsubstract_process(t_pdp_opencv_bgsubstract *x) +{ + int encoding; + t_pdp *header = 0; + char *parname; + unsigned pi; + int partype; + float pardefault; + t_atom plist[2]; + t_atom tlist[2]; + t_atom vlist[2]; + + /* check if image data packets are compatible */ + if ( (header = pdp_packet_header(x->x_packet0)) + && (PDP_BITMAP == header->type)){ + + /* pdp_opencv_bgsubstract_process inputs and write into active inlet */ + switch(pdp_packet_header(x->x_packet0)->info.image.encoding){ + + case PDP_BITMAP_RGB: + x->x_packet1 = pdp_packet_clone_rw(x->x_packet0); + pdp_queue_add(x, (void*)pdp_opencv_bgsubstract_process_rgb, (void*)pdp_opencv_bgsubstract_sendpacket, &x->x_queue_id); + break; + + default: + /* don't know the type, so dont pdp_opencv_bgsubstract_process */ + break; + + } + } + +} + +static void pdp_opencv_bgsubstract_input_0(t_pdp_opencv_bgsubstract *x, t_symbol *s, t_floatarg f) +{ + /* if this is a register_ro message or register_rw message, register with packet factory */ + + if (s == gensym("register_rw")) + x->x_dropped = pdp_packet_convert_ro_or_drop(&x->x_packet0, (int)f, pdp_gensym((char*)"bitmap/rgb/*") ); + + if ((s == gensym("process")) && (-1 != x->x_packet0) && (!x->x_dropped)) + { + /* add the process method and callback to the process queue */ + pdp_opencv_bgsubstract_process(x); + } +} + +static void pdp_opencv_bgsubstract_free(t_pdp_opencv_bgsubstract *x) +{ + int i; + + pdp_queue_finish(x->x_queue_id); + pdp_packet_mark_unused(x->x_packet0); + //cv_freeplugins(x); + + //Destroy cv_images + cvReleaseImage(&x->image); + cvReleaseImage(&x->gray); + cvReleaseImage(&x->grayLow); + cvReleaseImage(&x->grayUp); + cvReleaseImage(&x->prev_image); + cvReleaseImage(&x->diff_8U); +} + +t_class *pdp_opencv_bgsubstract_class; + + +void *pdp_opencv_bgsubstract_new(t_floatarg f) +{ + int i; + + t_pdp_opencv_bgsubstract *x = (t_pdp_opencv_bgsubstract *)pd_new(pdp_opencv_bgsubstract_class); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("threshold")); + + x->x_outlet0 = outlet_new(&x->x_obj, &s_anything); + + x->x_packet0 = -1; + x->x_packet1 = -1; + x->x_queue_id = -1; + + x->x_width = 320; + x->x_height = 240; + x->x_size = x->x_width * x->x_height; + + x->x_infosok = 0; + x->x_set = 1; + x->x_threshold = 13; + + x->image = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 3); + x->gray = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 1); + x->grayLow = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 1); + x->grayUp = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 1); + x->prev_image = cvCreateImage( cvSize(x->image->width,x->image->height), 8, 3 ); + x->diff_8U = cvCreateImage( cvSize(x->image->width,x->image->height), 8, 1 ); + + return (void *)x; +} + + +#ifdef __cplusplus +extern "C" +{ +#endif + + +void pdp_opencv_bgsubstract_setup(void) +{ + + post( " pdp_opencv_bgsubstract"); + pdp_opencv_bgsubstract_class = class_new(gensym("pdp_opencv_bgsubstract"), (t_newmethod)pdp_opencv_bgsubstract_new, + (t_method)pdp_opencv_bgsubstract_free, sizeof(t_pdp_opencv_bgsubstract), 0, A_DEFFLOAT, A_NULL); + + class_addmethod(pdp_opencv_bgsubstract_class, (t_method)pdp_opencv_bgsubstract_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL); + class_addmethod(pdp_opencv_bgsubstract_class, (t_method)pdp_opencv_bgsubstract_set, gensym("set"), A_NULL ); + class_addmethod(pdp_opencv_bgsubstract_class, (t_method)pdp_opencv_bgsubstract_threshold, gensym("threshold"), A_FLOAT, A_NULL ); + +} + +#ifdef __cplusplus +} +#endif diff --git a/pdp_opencv_bm-help.pd b/pdp_opencv_bm-help.pd new file mode 100755 index 0000000..039c1e0 --- /dev/null +++ b/pdp_opencv_bm-help.pd @@ -0,0 +1,103 @@ +#N canvas 503 49 833 785 10; +#X obj -17 -55 cnv 15 621 250 empty empty empty 20 12 0 14 -260097 +-66577 0; +#X obj 223 -15 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 +1; +#X obj 223 12 metro 40; +#X msg 313 39 close; +#X obj 243 110 pdp_v4l; +#X msg 300 7 open /dev/video0; +#X obj 412 -20 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 +1; +#X obj 412 7 metro 40; +#X msg 493 26 close; +#X msg 489 2 open /dev/video0; +#X obj 433 106 pdp_v4l2; +#X msg 498 81 format \$1; +#X obj 499 59 hradio 15 1 0 4 empty empty empty 0 -8 0 10 -262144 -1 +-1 0; +#X obj 13 160 pdp_qt; +#X obj 46 96 metro 40; +#X msg 46 68 bang; +#X msg 87 68 stop; +#X obj 13 -1 openpanel; +#X msg 13 24 open \$1; +#X msg 13 -29 bang; +#X msg 47 123 loop \$1; +#X obj 127 123 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 1 +1; +#X obj 127 41 loadbang; +#X text 56 -26 playing a video file; +#X text 253 -17 Camera input; +#X obj 73 161 hsl 128 15 0 500 0 0 empty empty empty -2 -8 0 10 -262144 +-1 -1 0 1; +#X obj -15 203 cnv 15 621 250 empty empty empty 20 12 0 14 -258113 +-66577 0; +#X obj 9 468 pdp_xv; +#X obj 158 368 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 +1; +#X msg 73 366 nightmode \$1; +#X text 177 369 set nightmode; +#X floatatom 163 223 5 0 0 0 - - -; +#X text -14 -77 pdp_opencv_bm : Block Matching optical flow algorithm. +; +#X msg 53 222 blocksize \$1 \$1; +#X floatatom 172 250 5 0 0 0 - - -; +#X floatatom 179 279 5 0 0 0 - - -; +#X obj 9 422 pdp_opencv_bm; +#X msg 62 249 shiftsize \$1 \$1; +#X text 204 223 set blocksize (width height) ( default 10x10 ); +#X text 212 249 set shiftsize (width height) ( default 10x10 ); +#X msg 69 278 maxrange \$1 \$1; +#X text 220 279 set maxrange (width height) ( default 5x5 ); +#X floatatom 162 318 5 0 0 0 - - -; +#X msg 75 316 threshold \$1; +#X text 204 315 threhold value for the detection of movement ( default +10 ); +#X obj 296 385 pdp_background; +#X obj 293 358 metro 40; +#X obj 292 337 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 +-1 -1; +#X msg 99 -157; +#X msg 321 334 stop; +#X obj 281 413 pdp_convert image/YCrCb/*; +#X connect 1 0 2 0; +#X connect 2 0 4 0; +#X connect 3 0 4 0; +#X connect 4 0 36 0; +#X connect 5 0 4 0; +#X connect 6 0 7 0; +#X connect 7 0 10 0; +#X connect 8 0 10 0; +#X connect 9 0 10 0; +#X connect 10 0 36 0; +#X connect 11 0 10 0; +#X connect 12 0 11 0; +#X connect 13 0 36 0; +#X connect 14 0 13 0; +#X connect 15 0 14 0; +#X connect 16 0 14 0; +#X connect 17 0 18 0; +#X connect 18 0 13 0; +#X connect 19 0 17 0; +#X connect 20 0 13 0; +#X connect 21 0 20 0; +#X connect 22 0 21 0; +#X connect 22 0 15 0; +#X connect 25 0 13 1; +#X connect 28 0 29 0; +#X connect 29 0 36 0; +#X connect 31 0 33 0; +#X connect 33 0 36 0; +#X connect 34 0 37 0; +#X connect 35 0 40 0; +#X connect 36 0 27 0; +#X connect 37 0 36 0; +#X connect 40 0 36 0; +#X connect 42 0 43 0; +#X connect 43 0 36 0; +#X connect 45 0 50 0; +#X connect 46 0 45 0; +#X connect 47 0 46 0; +#X connect 49 0 46 0; +#X connect 50 0 36 0; diff --git a/pdp_opencv_bm.cc b/pdp_opencv_bm.cc new file mode 100755 index 0000000..1d26dab --- /dev/null +++ b/pdp_opencv_bm.cc @@ -0,0 +1,327 @@ +/* + * Pure Data Packet module. + * Copyright (c) by Tom Schouten + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "pdp.h" + +#ifndef _EiC +#include "cv.h" +#endif + +typedef struct pdp_opencv_bm_struct +{ + t_object x_obj; + t_float x_f; + + t_outlet *x_outlet0; + t_outlet *x_outlet1; + t_atom x_list[3]; + + int x_packet0; + int x_packet1; + int x_dropped; + int x_queue_id; + + int x_width; + int x_height; + int x_size; + + // OpenCv structures + IplImage *image, *grey, *prev_grey, *swap_temp; + IplImage *x_velx, *x_vely; + CvSize x_blocksize, x_shiftsize, x_maxrange, x_velsize; + + int x_nightmode; + int x_threshold; + CvFont font; + +} t_pdp_opencv_bm; + +static void pdp_opencv_bm_process_rgb(t_pdp_opencv_bm *x) +{ + t_pdp *header = pdp_packet_header(x->x_packet0); + short int *data = (short int *)pdp_packet_data(x->x_packet0); + t_pdp *newheader = pdp_packet_header(x->x_packet1); + short int *newdata = (short int *)pdp_packet_data(x->x_packet1); + int i,j,k,im; + int marked; + int px,py; + + if ((x->x_width != (t_int)header->info.image.width) || + (x->x_height != (t_int)header->info.image.height) || (!x->image)) + { + + post("pdp_opencv_bm :: resizing plugins"); + + x->x_width = header->info.image.width; + x->x_height = header->info.image.height; + x->x_size = x->x_width*x->x_height; + + x->x_velsize.width = (x->x_width-x->x_blocksize.width)/x->x_shiftsize.width; + x->x_velsize.height = (x->x_height-x->x_blocksize.height)/x->x_shiftsize.height; + x->x_maxrange.width = x->x_width; + x->x_maxrange.height = x->x_height; + + //Destroy cv_images + cvReleaseImage( &x->image ); + cvReleaseImage( &x->grey ); + cvReleaseImage( &x->prev_grey ); + cvReleaseImage( &x->x_velx ); + cvReleaseImage( &x->x_vely ); + + //Create cv_images + x->image = cvCreateImage( cvSize(x->x_width, x->x_height), 8, 3 ); + x->grey = cvCreateImage( cvSize(x->x_width, x->x_height), 8, 1 ); + x->prev_grey = cvCreateImage( cvSize(x->x_width, x->x_height), 8, 1 ); + + x->x_velx = cvCreateImage( x->x_velsize, IPL_DEPTH_32F, 1 ); + x->x_vely = cvCreateImage( x->x_velsize, IPL_DEPTH_32F, 1 ); + } + + newheader->info.image.encoding = header->info.image.encoding; + newheader->info.image.width = x->x_width; + newheader->info.image.height = x->x_height; + + memcpy( newdata, data, x->x_size*3 ); + + memcpy( x->image->imageData, data, x->x_size*3 ); + + cvCvtColor( x->image, x->grey, CV_RGB2GRAY ); + + if( x->x_nightmode ) + cvZero( x->image ); + + cvCalcOpticalFlowBM( x->prev_grey, x->grey, + x->x_blocksize, x->x_shiftsize, + x->x_maxrange, 1, + x->x_velx, x->x_vely ); + + for( py=0; pyx_velsize.height; py++ ) + { + for( px=0; pxx_velsize.width; px++ ) + { + float velxf = (float)*( x->x_velx->imageData + py * x->x_velx->widthStep + px); + float velyf = (float)*( x->x_vely->imageData + py * x->x_vely->widthStep + px); + + if ( sqrt( velxf*velxf + velyf*velyf ) > x->x_threshold ) + { + // post( "pdp_opencv_bm : (%d,%d) values (%f,%f)", px, py, velxf, velyf ); + CvPoint orig, dest; + orig.x = px*x->x_shiftsize.width; + orig.y = py*x->x_shiftsize.height; + dest.x = px*x->x_shiftsize.width+(int)velxf; + dest.y = py*x->x_shiftsize.height+(int)velyf; + + cvLine( x->image, orig, dest, CV_RGB(0,255,0), 1, 8 ); + } + } + } + + CV_SWAP( x->prev_grey, x->grey, x->swap_temp ); + + memcpy( newdata, x->image->imageData, x->x_size*3 ); + return; +} + +static void pdp_opencv_bm_nightmode(t_pdp_opencv_bm *x, t_floatarg f) +{ + if ((f==0.0)||(f==1.0)) x->x_nightmode = (int)f; +} + +static void pdp_opencv_bm_threshold(t_pdp_opencv_bm *x, t_floatarg f) +{ + if (f>=0.0) x->x_threshold = (int)f; +} + +static void pdp_opencv_bm_blocksize(t_pdp_opencv_bm *x, t_floatarg fwidth, t_floatarg fheight ) +{ + if (fwidth>=1.0) x->x_blocksize.width = (int)fwidth; + if (fheight>=1.0) x->x_blocksize.height = (int)fheight; + + x->x_velsize.width = (x->x_width-x->x_blocksize.width)/x->x_shiftsize.width; + x->x_velsize.height = (x->x_height-x->x_blocksize.height)/x->x_shiftsize.height; + cvReleaseImage( &x->x_velx ); + cvReleaseImage( &x->x_vely ); + x->x_velx = cvCreateImage( x->x_velsize, IPL_DEPTH_32F, 1 ); + x->x_vely = cvCreateImage( x->x_velsize, IPL_DEPTH_32F, 1 ); + +} + +static void pdp_opencv_bm_shiftsize(t_pdp_opencv_bm *x, t_floatarg fwidth, t_floatarg fheight ) +{ + if (fwidth>=1.0) x->x_shiftsize.width = (int)fwidth; + if (fheight>=1.0) x->x_shiftsize.height = (int)fheight; + + x->x_velsize.width = (x->x_width-x->x_blocksize.width)/x->x_shiftsize.width; + x->x_velsize.height = (x->x_height-x->x_blocksize.height)/x->x_shiftsize.height; + cvReleaseImage( &x->x_velx ); + cvReleaseImage( &x->x_vely ); + x->x_velx = cvCreateImage( x->x_velsize, IPL_DEPTH_32F, 1 ); + x->x_vely = cvCreateImage( x->x_velsize, IPL_DEPTH_32F, 1 ); +} + +static void pdp_opencv_bm_maxrange(t_pdp_opencv_bm *x, t_floatarg fwidth, t_floatarg fheight ) +{ + if (fwidth>=1.0) x->x_maxrange.width = (int)fwidth; + if (fheight>=1.0) x->x_maxrange.height = (int)fheight; +} + +static void pdp_opencv_bm_sendpacket(t_pdp_opencv_bm *x) +{ + /* release the packet */ + pdp_packet_mark_unused(x->x_packet0); + x->x_packet0 = -1; + + /* unregister and propagate if valid dest packet */ + pdp_packet_pass_if_valid(x->x_outlet0, &x->x_packet1); +} + +static void pdp_opencv_bm_process(t_pdp_opencv_bm *x) +{ + int encoding; + t_pdp *header = 0; + + /* check if image data packets are compatible */ + if ( (header = pdp_packet_header(x->x_packet0)) + && (PDP_BITMAP == header->type)){ + + /* pdp_opencv_bm_process inputs and write into active inlet */ + switch(pdp_packet_header(x->x_packet0)->info.image.encoding){ + + case PDP_BITMAP_RGB: + x->x_packet1 = pdp_packet_clone_rw(x->x_packet0); + pdp_queue_add(x, (void*)pdp_opencv_bm_process_rgb, (void*)pdp_opencv_bm_sendpacket, &x->x_queue_id); + break; + + default: + /* don't know the type, so dont pdp_opencv_bm_process */ + break; + + } + } + +} + +static void pdp_opencv_bm_input_0(t_pdp_opencv_bm *x, t_symbol *s, t_floatarg f) +{ + /* if this is a register_ro message or register_rw message, register with packet factory */ + + if (s == gensym("register_rw")) + x->x_dropped = pdp_packet_convert_ro_or_drop(&x->x_packet0, (int)f, pdp_gensym((char*)"bitmap/rgb/*") ); + + if ((s == gensym("process")) && (-1 != x->x_packet0) && (!x->x_dropped)) + { + /* add the process method and callback to the process queue */ + pdp_opencv_bm_process(x); + } +} + +static void pdp_opencv_bm_free(t_pdp_opencv_bm *x) +{ + int i; + + pdp_queue_finish(x->x_queue_id); + pdp_packet_mark_unused(x->x_packet0); + //cv_freeplugins(x); + + //Destroy cv_images + cvReleaseImage( &x->image ); + cvReleaseImage( &x->grey ); + cvReleaseImage( &x->prev_grey ); + cvReleaseImage( &x->x_velx ); + cvReleaseImage( &x->x_vely ); +} + +t_class *pdp_opencv_bm_class; + +void *pdp_opencv_bm_new(t_floatarg f) +{ + int i; + + t_pdp_opencv_bm *x = (t_pdp_opencv_bm *)pd_new(pdp_opencv_bm_class); + + x->x_outlet0 = outlet_new(&x->x_obj, &s_anything); + x->x_outlet1 = outlet_new(&x->x_obj, &s_anything); + + x->x_packet0 = -1; + x->x_packet1 = -1; + x->x_queue_id = -1; + + x->x_width = 320; + x->x_height = 240; + x->x_size = x->x_width * x->x_height; + + x->x_nightmode=0; + x->x_threshold=10; + x->x_blocksize.width = 10; + x->x_blocksize.height = 10; + x->x_shiftsize.width = 10; + x->x_shiftsize.height = 10; + x->x_maxrange.width = x->x_width; + x->x_maxrange.height = x->x_height; + x->x_velsize.width = (x->x_width-x->x_blocksize.width)/x->x_shiftsize.width; + x->x_velsize.height = (x->x_height-x->x_blocksize.height)/x->x_shiftsize.height; + + // initialize font + cvInitFont( &x->font, CV_FONT_HERSHEY_PLAIN, 1.0, 1.0, 0, 1, 8 ); + + x->image = cvCreateImage( cvSize(x->x_width, x->x_height), 8, 3 ); + x->grey = cvCreateImage( cvSize(x->x_width, x->x_height), 8, 1 ); + x->prev_grey = cvCreateImage( cvSize(x->x_width, x->x_height), 8, 1 ); + + x->x_velx = cvCreateImage( x->x_velsize, IPL_DEPTH_32F, 1 ); + x->x_vely = cvCreateImage( x->x_velsize, IPL_DEPTH_32F, 1 ); + + return (void *)x; +} + + +#ifdef __cplusplus +extern "C" +{ +#endif + + +void pdp_opencv_bm_setup(void) +{ + + post( " pdp_opencv_bm"); + pdp_opencv_bm_class = class_new(gensym("pdp_opencv_bm"), (t_newmethod)pdp_opencv_bm_new, + (t_method)pdp_opencv_bm_free, sizeof(t_pdp_opencv_bm), 0, A_DEFFLOAT, A_NULL); + + class_addmethod(pdp_opencv_bm_class, (t_method)pdp_opencv_bm_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL); + class_addmethod(pdp_opencv_bm_class, (t_method)pdp_opencv_bm_nightmode, gensym("nightmode"), A_FLOAT, A_NULL ); + class_addmethod(pdp_opencv_bm_class, (t_method)pdp_opencv_bm_threshold, gensym("threshold"), A_FLOAT, A_NULL ); + class_addmethod(pdp_opencv_bm_class, (t_method)pdp_opencv_bm_blocksize, gensym("blocksize"), A_FLOAT, A_FLOAT, A_NULL ); + class_addmethod(pdp_opencv_bm_class, (t_method)pdp_opencv_bm_shiftsize, gensym("shiftsize"), A_FLOAT, A_FLOAT, A_NULL ); + class_addmethod(pdp_opencv_bm_class, (t_method)pdp_opencv_bm_maxrange, gensym("maxrange"), A_FLOAT, A_FLOAT, A_NULL ); + +} + +#ifdef __cplusplus +} +#endif diff --git a/pdp_opencv_colorfilt.c b/pdp_opencv_colorfilt.c deleted file mode 100755 index b2d4092..0000000 --- a/pdp_opencv_colorfilt.c +++ /dev/null @@ -1,332 +0,0 @@ -/* - * Pd OpenCV module - * Copyright (c) by Yves Degoyon ( ydegoyon@free.fr ) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -/* This object is a color filter - */ - -#include "pdp.h" -#include -#include -#include "g_canvas.h" - -static char *pdp_opencv_colorfilt_version = "pdp_opencv_colorfilt: a color filter"; - -typedef struct pdp_opencv_colorfilt_struct -{ - t_object x_obj; - - int x_packet0; - int x_packet1; - int x_queue_id; - int x_dropped; - - int x_width; - int x_height; - int x_size; - unsigned char x_colorR; // RGB components of binary mask - unsigned char x_colorG; - unsigned char x_colorB; - int x_tolerance; // tolerance - unsigned char *x_frame; // keep a copy of current frame for picking color - - t_outlet *x_pdp_output; // output packets - t_outlet *x_R; // output R component of selected color - t_outlet *x_G; // output G component of selected color - t_outlet *x_B; // output B component of selected color - - t_canvas *x_canvas; - -} t_pdp_opencv_colorfilt; - -static void pdp_opencv_colorfilt_draw_color(t_pdp_opencv_colorfilt *x) -{ - int width, height; - char color[32]; - - sprintf( color, "#%.2X%.2X%.2X", x->x_colorR, x->x_colorG, x->x_colorB ); - width = rtext_width( glist_findrtext( (t_glist*)x->x_canvas, (t_text *)x ) ); - height = rtext_height( glist_findrtext( (t_glist*)x->x_canvas, (t_text *)x ) ); - sys_vgui(".x%x.c delete rectangle %xCOLOR\n", x->x_canvas, x ); - sys_vgui(".x%x.c create rectangle %d %d %d %d -fill %s -tags %xCOLOR\n", - x->x_canvas, x->x_obj.te_xpix+width+5, x->x_obj.te_ypix, - x->x_obj.te_xpix+width+height+5, - x->x_obj.te_ypix+height, color, x ); -} - - -static void pdp_opencv_colorfilt_r(t_pdp_opencv_colorfilt *x, t_floatarg fr ) -{ - if ( fr <= 255. && fr >= 0. ) - { - x->x_colorR = (int)fr; - outlet_float( x->x_R, x->x_colorR ); - if (glist_isvisible(x->x_canvas)) pdp_opencv_colorfilt_draw_color( x ); - } -} - -static void pdp_opencv_colorfilt_g(t_pdp_opencv_colorfilt *x, t_floatarg fg ) -{ - if ( fg <= 255. && fg >= 0. ) - { - x->x_colorG = (int)fg; - outlet_float( x->x_G, x->x_colorG ); - if (glist_isvisible(x->x_canvas)) pdp_opencv_colorfilt_draw_color( x ); - } -} - -static void pdp_opencv_colorfilt_b(t_pdp_opencv_colorfilt *x, t_floatarg fb ) -{ - if ( fb < 255 && fb >= 0. ) - { - x->x_colorB = (int)fb; - outlet_float( x->x_B, x->x_colorB ); - if (glist_isvisible(x->x_canvas)) pdp_opencv_colorfilt_draw_color( x ); - } -} - -static void pdp_opencv_colorfilt_tolerance(t_pdp_opencv_colorfilt *x, t_floatarg ftolerance ) -{ - if ( ftolerance >= 0 ) - { - x->x_tolerance = (int)ftolerance; - } -} - -static void pdp_opencv_colorfilt_pick(t_pdp_opencv_colorfilt *x, t_floatarg px, t_floatarg py ) -{ - if ( x->x_frame && ( px >= 0. ) && ( px <= 1.0 ) - && ( py > 0. ) && ( py < 1.0 ) ) - { - int xcur = px*x->x_width; - int ycur = py*x->x_height; - - x->x_colorR = x->x_frame[(ycur*x->x_width*3)+xcur*3]; - x->x_colorG = x->x_frame[(ycur*x->x_width*3)+xcur*3+1]; - x->x_colorB = x->x_frame[(ycur*x->x_width*3)+xcur*3+2]; - outlet_float( x->x_R, x->x_colorR ); - outlet_float( x->x_G, x->x_colorG ); - outlet_float( x->x_B, x->x_colorB ); - post( "pdp_opencv_colorfilt : picked up color : x=%d y=%d r=%d g=%d b=%d", xcur, ycur, x->x_colorR, x->x_colorG, x->x_colorB ); - - if (glist_isvisible(x->x_canvas)) pdp_opencv_colorfilt_draw_color( x ); - } -} - -static void pdp_opencv_colorfilt_allocate(t_pdp_opencv_colorfilt *x) -{ - x->x_frame = (unsigned char *) getbytes ( x->x_size*3*sizeof(unsigned char) ); - - if ( !x->x_frame ) - { - post( "pdp_binary : severe error : cannot allocate buffer !!! "); - return; - } -} - -static void pdp_opencv_colorfilt_free_ressources(t_pdp_opencv_colorfilt *x) -{ - if ( x->x_frame ) freebytes ( x->x_frame, x->x_size*3*sizeof(unsigned char) ); -} - -static void pdp_opencv_colorfilt_process_rgb(t_pdp_opencv_colorfilt *x) -{ - t_pdp *header = pdp_packet_header(x->x_packet0); - unsigned char *data = (unsigned char *)pdp_packet_data(x->x_packet0); - t_pdp *newheader = pdp_packet_header(x->x_packet1); - unsigned char *newdata = (unsigned char *)pdp_packet_data(x->x_packet1); - int i; - int px=0, py=0; - unsigned char r=0, g=0, b=0; - unsigned char *pf; - int diff; - - /* allocate all ressources */ - if ( ( (int)header->info.image.width != x->x_width ) || - ( (int)header->info.image.height != x->x_height ) ) - { - pdp_opencv_colorfilt_free_ressources( x ); - x->x_width = header->info.image.width; - x->x_height = header->info.image.height; - x->x_size = x->x_width*x->x_height; - pdp_opencv_colorfilt_allocate( x ); - post( "pdp_opencv_colorfilt : reallocated buffers" ); - } - - memcpy(x->x_frame, data, x->x_size*3*sizeof(unsigned char)); - memcpy(newdata, data, x->x_size*3*sizeof(unsigned char)); - - newheader->info.image.encoding = header->info.image.encoding; - newheader->info.image.width = x->x_width; - newheader->info.image.height = x->x_height; - - // filter - pf = newdata; - for ( py=0; pyx_height; py++ ) - { - for ( px=0; pxx_width; px++ ) - { - r = *(pf); - g = *(pf+1); - b = *(pf+2); - - diff = 0; - diff = abs(r-x->x_colorR ); - diff += abs(g-x->x_colorG ); - diff += abs(b-x->x_colorB ); - - if ( diff > x->x_tolerance ) - { - *(pf) = 0x0; - *(pf+1) = 0x0; - *(pf+2) = 0x0; - } - - pf+=3; - } - } - - return; -} - -static void pdp_opencv_colorfilt_sendpacket(t_pdp_opencv_colorfilt *x) -{ - /* release the packet */ - pdp_packet_mark_unused(x->x_packet0); - x->x_packet0 = -1; - - /* unregister and propagate if valid dest packet */ - pdp_packet_pass_if_valid(x->x_pdp_output, &x->x_packet1); -} - -static void pdp_opencv_colorfilt_process(t_pdp_opencv_colorfilt *x) -{ - int encoding; - t_pdp *header = 0; - - /* check if image data packets are compatible */ - if ( (header = pdp_packet_header(x->x_packet0)) - && (PDP_BITMAP == header->type)){ - - /* pdp_opencv_colorfilt_process inputs and write into active inlet */ - switch(pdp_packet_header(x->x_packet0)->info.image.encoding) - { - - case PDP_BITMAP_RGB: - x->x_packet1 = pdp_packet_clone_rw(x->x_packet0); - pdp_queue_add(x, pdp_opencv_colorfilt_process_rgb, pdp_opencv_colorfilt_sendpacket, &x->x_queue_id); - break; - - default: - /* don't know the type, so dont pdp_opencv_colorfilt_process */ - break; - - } - } - -} - -static void pdp_opencv_colorfilt_input_0(t_pdp_opencv_colorfilt *x, t_symbol *s, t_floatarg f) -{ - /* if this is a register_ro message or register_rw message, register with packet factory */ - - if (s== gensym("register_rw")) - { - x->x_dropped = pdp_packet_convert_ro_or_drop(&x->x_packet0, (int)f, pdp_gensym("bitmap/rgb/*") ); - } - - if ((s == gensym("process")) && (-1 != x->x_packet0) && (!x->x_dropped)) - { - pdp_opencv_colorfilt_process(x); - } -} - -static void pdp_opencv_colorfilt_free(t_pdp_opencv_colorfilt *x) -{ - int i; - - pdp_packet_mark_unused(x->x_packet0); - pdp_opencv_colorfilt_free_ressources( x ); -} - -t_class *pdp_opencv_colorfilt_class; - -void *pdp_opencv_colorfilt_new(void) -{ - int i; - - t_pdp_opencv_colorfilt *x = (t_pdp_opencv_colorfilt *)pd_new(pdp_opencv_colorfilt_class); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("R")); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("G")); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("B")); - - x->x_pdp_output = outlet_new(&x->x_obj, &s_anything); - x->x_R = outlet_new(&x->x_obj, &s_float); - x->x_G = outlet_new(&x->x_obj, &s_float); - x->x_B = outlet_new(&x->x_obj, &s_float); - - x->x_colorR = 128; - x->x_colorG = 128; - x->x_colorB = 128; - - outlet_float( x->x_R, x->x_colorR ); - outlet_float( x->x_G, x->x_colorG ); - outlet_float( x->x_B, x->x_colorB ); - - x->x_packet0 = -1; - x->x_packet1 = -1; - - x->x_tolerance = 50; - - x->x_width = -1; - x->x_height = -1; - x->x_size = -1; - x->x_frame = NULL; - - x->x_canvas = canvas_getcurrent(); - - return (void *)x; -} - - -#ifdef __cplusplus -extern "C" -{ -#endif - - -void pdp_opencv_colorfilt_setup(void) -{ - // post( pdp_opencv_colorfilt_version ); - pdp_opencv_colorfilt_class = class_new(gensym("pdp_opencv_colorfilt"), (t_newmethod)pdp_opencv_colorfilt_new, - (t_method)pdp_opencv_colorfilt_free, sizeof(t_pdp_opencv_colorfilt), 0, A_NULL); - - class_addmethod(pdp_opencv_colorfilt_class, (t_method)pdp_opencv_colorfilt_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL); - class_addmethod(pdp_opencv_colorfilt_class, (t_method)pdp_opencv_colorfilt_r, gensym("R"), A_FLOAT, A_NULL); - class_addmethod(pdp_opencv_colorfilt_class, (t_method)pdp_opencv_colorfilt_g, gensym("G"), A_FLOAT, A_NULL); - class_addmethod(pdp_opencv_colorfilt_class, (t_method)pdp_opencv_colorfilt_b, gensym("B"), A_FLOAT, A_NULL); - class_addmethod(pdp_opencv_colorfilt_class, (t_method)pdp_opencv_colorfilt_pick, gensym("pick"), A_FLOAT, A_FLOAT, A_NULL); - class_addmethod(pdp_opencv_colorfilt_class, (t_method)pdp_opencv_colorfilt_tolerance, gensym("tolerance"), A_FLOAT, A_NULL); - - class_sethelpsymbol( pdp_opencv_colorfilt_class, gensym("pdp_opencv_colorfilt.pd") ); -} - -#ifdef __cplusplus -} -#endif diff --git a/pdp_opencv_colorfilt.cc b/pdp_opencv_colorfilt.cc new file mode 100755 index 0000000..89eaecc --- /dev/null +++ b/pdp_opencv_colorfilt.cc @@ -0,0 +1,329 @@ +/* + * Pd OpenCV module + * Copyright (c) by Yves Degoyon ( ydegoyon@free.fr ) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +/* This object is a color filter + */ + +#include "pdp.h" +#include +#include +#include "g_canvas.h" + +typedef struct pdp_opencv_colorfilt_struct +{ + t_object x_obj; + + int x_packet0; + int x_packet1; + int x_queue_id; + int x_dropped; + + int x_width; + int x_height; + int x_size; + unsigned char x_colorR; // RGB components of binary mask + unsigned char x_colorG; + unsigned char x_colorB; + int x_tolerance; // tolerance + unsigned char *x_frame; // keep a copy of current frame for picking color + + t_outlet *x_pdp_output; // output packets + t_outlet *x_R; // output R component of selected color + t_outlet *x_G; // output G component of selected color + t_outlet *x_B; // output B component of selected color + + t_canvas *x_canvas; + +} t_pdp_opencv_colorfilt; + +static void pdp_opencv_colorfilt_draw_color(t_pdp_opencv_colorfilt *x) +{ + int width, height; + char color[32]; + + sprintf( color, "#%.2X%.2X%.2X", x->x_colorR, x->x_colorG, x->x_colorB ); + width = rtext_width( glist_findrtext( (t_glist*)x->x_canvas, (t_text *)x ) ); + height = rtext_height( glist_findrtext( (t_glist*)x->x_canvas, (t_text *)x ) ); + sys_vgui((char*)".x%x.c delete rectangle %xCOLOR\n", x->x_canvas, x ); + sys_vgui((char*)".x%x.c create rectangle %d %d %d %d -fill %s -tags %xCOLOR\n", + x->x_canvas, x->x_obj.te_xpix+width+5, x->x_obj.te_ypix, + x->x_obj.te_xpix+width+height+5, + x->x_obj.te_ypix+height, color, x ); +} + + +static void pdp_opencv_colorfilt_r(t_pdp_opencv_colorfilt *x, t_floatarg fr ) +{ + if ( fr <= 255. && fr >= 0. ) + { + x->x_colorR = (int)fr; + outlet_float( x->x_R, x->x_colorR ); + if (glist_isvisible(x->x_canvas)) pdp_opencv_colorfilt_draw_color( x ); + } +} + +static void pdp_opencv_colorfilt_g(t_pdp_opencv_colorfilt *x, t_floatarg fg ) +{ + if ( fg <= 255. && fg >= 0. ) + { + x->x_colorG = (int)fg; + outlet_float( x->x_G, x->x_colorG ); + if (glist_isvisible(x->x_canvas)) pdp_opencv_colorfilt_draw_color( x ); + } +} + +static void pdp_opencv_colorfilt_b(t_pdp_opencv_colorfilt *x, t_floatarg fb ) +{ + if ( fb < 255 && fb >= 0. ) + { + x->x_colorB = (int)fb; + outlet_float( x->x_B, x->x_colorB ); + if (glist_isvisible(x->x_canvas)) pdp_opencv_colorfilt_draw_color( x ); + } +} + +static void pdp_opencv_colorfilt_tolerance(t_pdp_opencv_colorfilt *x, t_floatarg ftolerance ) +{ + if ( ftolerance >= 0 ) + { + x->x_tolerance = (int)ftolerance; + } +} + +static void pdp_opencv_colorfilt_pick(t_pdp_opencv_colorfilt *x, t_floatarg px, t_floatarg py ) +{ + if ( x->x_frame && ( px >= 0. ) && ( px <= 1.0 ) + && ( py > 0. ) && ( py < 1.0 ) ) + { + int xcur = px*x->x_width; + int ycur = py*x->x_height; + + x->x_colorR = x->x_frame[(ycur*x->x_width*3)+xcur*3]; + x->x_colorG = x->x_frame[(ycur*x->x_width*3)+xcur*3+1]; + x->x_colorB = x->x_frame[(ycur*x->x_width*3)+xcur*3+2]; + outlet_float( x->x_R, x->x_colorR ); + outlet_float( x->x_G, x->x_colorG ); + outlet_float( x->x_B, x->x_colorB ); + post( "pdp_opencv_colorfilt : picked up color : x=%d y=%d r=%d g=%d b=%d", xcur, ycur, x->x_colorR, x->x_colorG, x->x_colorB ); + + if (glist_isvisible(x->x_canvas)) pdp_opencv_colorfilt_draw_color( x ); + } +} + +static void pdp_opencv_colorfilt_allocate(t_pdp_opencv_colorfilt *x) +{ + x->x_frame = (unsigned char *) getbytes ( x->x_size*3*sizeof(unsigned char) ); + + if ( !x->x_frame ) + { + post( "pdp_binary : severe error : cannot allocate buffer !!! "); + return; + } +} + +static void pdp_opencv_colorfilt_free_ressources(t_pdp_opencv_colorfilt *x) +{ + if ( x->x_frame ) freebytes ( x->x_frame, x->x_size*3*sizeof(unsigned char) ); +} + +static void pdp_opencv_colorfilt_process_rgb(t_pdp_opencv_colorfilt *x) +{ + t_pdp *header = pdp_packet_header(x->x_packet0); + unsigned char *data = (unsigned char *)pdp_packet_data(x->x_packet0); + t_pdp *newheader = pdp_packet_header(x->x_packet1); + unsigned char *newdata = (unsigned char *)pdp_packet_data(x->x_packet1); + int i; + int px=0, py=0; + unsigned char r=0, g=0, b=0; + unsigned char *pf; + int diff; + + /* allocate all ressources */ + if ( ( (int)header->info.image.width != x->x_width ) || + ( (int)header->info.image.height != x->x_height ) ) + { + pdp_opencv_colorfilt_free_ressources( x ); + x->x_width = header->info.image.width; + x->x_height = header->info.image.height; + x->x_size = x->x_width*x->x_height; + pdp_opencv_colorfilt_allocate( x ); + post( "pdp_opencv_colorfilt : reallocated buffers" ); + } + + memcpy(x->x_frame, data, x->x_size*3*sizeof(unsigned char)); + memcpy(newdata, data, x->x_size*3*sizeof(unsigned char)); + + newheader->info.image.encoding = header->info.image.encoding; + newheader->info.image.width = x->x_width; + newheader->info.image.height = x->x_height; + + // filter + pf = newdata; + for ( py=0; pyx_height; py++ ) + { + for ( px=0; pxx_width; px++ ) + { + r = *(pf); + g = *(pf+1); + b = *(pf+2); + + diff = 0; + diff = abs(r-x->x_colorR ); + diff += abs(g-x->x_colorG ); + diff += abs(b-x->x_colorB ); + + if ( diff > x->x_tolerance ) + { + *(pf) = 0x0; + *(pf+1) = 0x0; + *(pf+2) = 0x0; + } + + pf+=3; + } + } + + return; +} + +static void pdp_opencv_colorfilt_sendpacket(t_pdp_opencv_colorfilt *x) +{ + /* release the packet */ + pdp_packet_mark_unused(x->x_packet0); + x->x_packet0 = -1; + + /* unregister and propagate if valid dest packet */ + pdp_packet_pass_if_valid(x->x_pdp_output, &x->x_packet1); +} + +static void pdp_opencv_colorfilt_process(t_pdp_opencv_colorfilt *x) +{ + int encoding; + t_pdp *header = 0; + + /* check if image data packets are compatible */ + if ( (header = pdp_packet_header(x->x_packet0)) + && (PDP_BITMAP == header->type)){ + + /* pdp_opencv_colorfilt_process inputs and write into active inlet */ + switch(pdp_packet_header(x->x_packet0)->info.image.encoding) + { + + case PDP_BITMAP_RGB: + x->x_packet1 = pdp_packet_clone_rw(x->x_packet0); + pdp_queue_add(x, (void*)pdp_opencv_colorfilt_process_rgb, (void*)pdp_opencv_colorfilt_sendpacket, &x->x_queue_id); + break; + + default: + /* don't know the type, so dont pdp_opencv_colorfilt_process */ + break; + + } + } + +} + +static void pdp_opencv_colorfilt_input_0(t_pdp_opencv_colorfilt *x, t_symbol *s, t_floatarg f) +{ + /* if this is a register_ro message or register_rw message, register with packet factory */ + + if (s== gensym("register_rw")) + { + x->x_dropped = pdp_packet_convert_ro_or_drop(&x->x_packet0, (int)f, pdp_gensym((char*)"bitmap/rgb/*") ); + } + + if ((s == gensym("process")) && (-1 != x->x_packet0) && (!x->x_dropped)) + { + pdp_opencv_colorfilt_process(x); + } +} + +static void pdp_opencv_colorfilt_free(t_pdp_opencv_colorfilt *x) +{ + int i; + + pdp_packet_mark_unused(x->x_packet0); + pdp_opencv_colorfilt_free_ressources( x ); +} + +t_class *pdp_opencv_colorfilt_class; + +void *pdp_opencv_colorfilt_new(void) +{ + int i; + + t_pdp_opencv_colorfilt *x = (t_pdp_opencv_colorfilt *)pd_new(pdp_opencv_colorfilt_class); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("R")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("G")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("B")); + + x->x_pdp_output = outlet_new(&x->x_obj, &s_anything); + x->x_R = outlet_new(&x->x_obj, &s_float); + x->x_G = outlet_new(&x->x_obj, &s_float); + x->x_B = outlet_new(&x->x_obj, &s_float); + + x->x_colorR = 128; + x->x_colorG = 128; + x->x_colorB = 128; + + outlet_float( x->x_R, x->x_colorR ); + outlet_float( x->x_G, x->x_colorG ); + outlet_float( x->x_B, x->x_colorB ); + + x->x_packet0 = -1; + x->x_packet1 = -1; + + x->x_tolerance = 50; + + x->x_width = -1; + x->x_height = -1; + x->x_size = -1; + x->x_frame = NULL; + + x->x_canvas = canvas_getcurrent(); + + return (void *)x; +} + + +#ifdef __cplusplus +extern "C" +{ +#endif + + +void pdp_opencv_colorfilt_setup(void) +{ + pdp_opencv_colorfilt_class = class_new(gensym("pdp_opencv_colorfilt"), (t_newmethod)pdp_opencv_colorfilt_new, + (t_method)pdp_opencv_colorfilt_free, sizeof(t_pdp_opencv_colorfilt), 0, A_NULL); + + class_addmethod(pdp_opencv_colorfilt_class, (t_method)pdp_opencv_colorfilt_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL); + class_addmethod(pdp_opencv_colorfilt_class, (t_method)pdp_opencv_colorfilt_r, gensym("R"), A_FLOAT, A_NULL); + class_addmethod(pdp_opencv_colorfilt_class, (t_method)pdp_opencv_colorfilt_g, gensym("G"), A_FLOAT, A_NULL); + class_addmethod(pdp_opencv_colorfilt_class, (t_method)pdp_opencv_colorfilt_b, gensym("B"), A_FLOAT, A_NULL); + class_addmethod(pdp_opencv_colorfilt_class, (t_method)pdp_opencv_colorfilt_pick, gensym("pick"), A_FLOAT, A_FLOAT, A_NULL); + class_addmethod(pdp_opencv_colorfilt_class, (t_method)pdp_opencv_colorfilt_tolerance, gensym("tolerance"), A_FLOAT, A_NULL); + + class_sethelpsymbol( pdp_opencv_colorfilt_class, gensym("pdp_opencv_colorfilt.pd") ); +} + +#ifdef __cplusplus +} +#endif diff --git a/pdp_opencv_contours_boundingrect.c b/pdp_opencv_contours_boundingrect.c deleted file mode 100644 index 549fb6d..0000000 --- a/pdp_opencv_contours_boundingrect.c +++ /dev/null @@ -1,534 +0,0 @@ -/* - * Pure Data Packet module. - * Copyright (c) by Tom Schouten - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "pdp.h" - -#ifndef _EiC -#include "cv.h" -#endif - -#define MAX_MARKERS 100 - -typedef struct pdp_opencv_contours_boundingrect_struct -{ - t_object x_obj; - t_float x_f; - - t_outlet *x_outlet0; - t_outlet *x_dataout; - t_outlet *x_countout; - t_atom rlist[5]; - int x_packet0; - int x_packet1; - int x_dropped; - int x_queue_id; - int x_xmark[MAX_MARKERS]; - int x_ymark[MAX_MARKERS]; - int x_found[MAX_MARKERS]; - int x_ftolerance; - int x_mmove; - - // contours retrieval mode - int x_cmode; - // contours retrieval method - int x_cmethod; - - int x_width; - int x_height; - int x_size; - - int x_nightmode; // don't show the original image - int x_draw; // draw contours boundaries rectangles - int x_show; // show the real contour - - int minarea; - int maxarea; - IplImage *image, *gray, *cnt_img; - CvFont font; - -} t_pdp_opencv_contours_boundingrect; - -static int pdp_opencv_contours_boundingrect_mark(t_pdp_opencv_contours_boundingrect *x, t_floatarg fx, t_floatarg fy ) -{ - int i; - - if ( ( fx < 0.0 ) || ( fx > x->x_width ) || ( fy < 0 ) || ( fy > x->x_height ) ) - { - return -1; - } - - for ( i=0; ix_xmark[i] == -1 ) - { - x->x_xmark[i] = (int)fx; - x->x_ymark[i] = (int)fy; - x->x_found[i] = x->x_ftolerance; - return i; - } - } - - // post( "pdp_opencv_contours_boundingrect : max markers reached" ); - return -1; -} - -static void pdp_opencv_contours_boundingrect_process_rgb(t_pdp_opencv_contours_boundingrect *x) -{ - t_pdp *header = pdp_packet_header(x->x_packet0); - short int *data = (short int *)pdp_packet_data(x->x_packet0); - t_pdp *newheader = pdp_packet_header(x->x_packet1); - short int *newdata = (short int *)pdp_packet_data(x->x_packet1); - char tindex[4]; - int i = 0; // Indicator of cycles. - int im = 0; // Indicator of markers. - - if ((x->x_width != (t_int)header->info.image.width) || - (x->x_height != (t_int)header->info.image.height)) - { - - post("pdp_opencv_contours_boundingrect :: resizing plugins"); - - - x->x_width = header->info.image.width; - x->x_height = header->info.image.height; - x->x_size = x->x_width*x->x_height; - - //Destroy cv_images - cvReleaseImage(&x->image); - cvReleaseImage(&x->gray); - cvReleaseImage(&x->cnt_img); - - //create the orig image with new size - x->image = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 3); - - // Create the output images with new sizes - x->gray = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 1); - x->cnt_img = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 3); - - } - - newheader->info.image.encoding = header->info.image.encoding; - newheader->info.image.width = x->x_width; - newheader->info.image.height = x->x_height; - - memcpy( x->image->imageData, data, x->x_size*3 ); - - // Convert to grayscale - cvCvtColor(x->image, x->gray, CV_BGR2GRAY); - - CvSeq* contours; - CvMemStorage* stor02; - stor02 = cvCreateMemStorage(0); - - //TODO nous objectes ::: llegeixo el OpenCVRefenceManual i al capitol 11 Structural Analysis Reference - // m'en adono que - //de fet aquest objecte no s'ha de dir pdp_opencv_contours sino pdp_opencv_convexity - //el pdp_opencv_contours et donaria una llista de punts en els outles que serien els punts del contorn (poligonal o no)i - //i seria la base per a una serie de objectes basats en contorns - //el pdp_opencv_convexHull, el mateix pdp_opencv_convexity - //depres nhi ha un altre que surtiria d'aqui :: pdp_opencv_MinAreaRect i el pdp_opencv_MinEnclosingCircle - //ContourBoundingRect - // - - // Retrieval mode. - // CV_RETR_EXTERNAL || CV_RETR_LIST || CV_RETR_CCOMP || CV_RETR_TREE - // Approximation method. - // CV_CHAIN_CODE || CV_CHAIN_APPROX_NONE || CV_CHAIN_APPROX_SIMPLE || CV_CHAIN_APPROX_TC89_L1 || CV_CHAIN_APPROX_TC89_KCOS || CV_LINK_RUNS - cvFindContours( x->gray, stor02, &contours, sizeof(CvContour), x->x_cmode, x->x_cmethod, cvPoint(0,0) ); - - // TODO afegir parametres - // aqui es fa una aproximacio del contorn per a que sigui mes polinomic i no tingui tants punts - // els ultims dos parametres han de ser variables - // precision , recursive - if (contours) contours = cvApproxPoly( contours, sizeof(CvContour), stor02, CV_POLY_APPROX_DP, 3, 1 ); - - //TODO afegir parametre - //si volem veure la imatge original o un fons negre - cvCopy(x->image, x->cnt_img, NULL); - if ( x->x_nightmode ) - { - cvZero( x->cnt_img ); - } - - for ( im=0; imx_xmark[im] != -1.0 ) - { - x->x_found[im]--; - } - } - - for( ; contours != 0; contours = contours->h_next ) - { - int count = contours->total; // This is number point in contour - CvRect rect; - int oi, found; - - rect = cvContourBoundingRect( contours, 1); - if ( ( (rect.width*rect.height) > x->minarea ) && ( (rect.width*rect.height) < x->maxarea ) ) { - - found = 0; - oi = -1; - for ( im=0; imx_xmark[im] ) < x->x_mmove ) && ( abs( rect.y - x->x_ymark[im] ) < x->x_mmove ) ) - { - oi=im; - found=1; - x->x_found[im] = x->x_ftolerance; - x->x_xmark[im] = rect.x; - x->x_ymark[im] = rect.y; - break; - } - } - // new object detected - if ( !found ) - { - oi = pdp_opencv_contours_boundingrect_mark(x, rect.x, rect.y ); - } - - if ( x->x_draw ) - { - cvRectangle( x->cnt_img, cvPoint(rect.x,rect.y), cvPoint(rect.x+rect.width,rect.y+rect.height), CV_RGB(255,0,0), 2, 8 , 0 ); - sprintf( tindex, "%d", oi ); - cvPutText( x->cnt_img, tindex, cvPoint(rect.x,rect.y), &x->font, CV_RGB(255,255,255)); - } - - if ( x->x_show ) - { - cvDrawContours( x->cnt_img, contours, CV_RGB(255,255,255), CV_RGB(255,255,255), 0, 1, 8, cvPoint(0,0) ); - } - - SETFLOAT(&x->rlist[0], oi); - SETFLOAT(&x->rlist[1], rect.x); - SETFLOAT(&x->rlist[2], rect.y); - SETFLOAT(&x->rlist[3], rect.width); - SETFLOAT(&x->rlist[4], rect.height); - - outlet_list( x->x_dataout, 0, 5, x->rlist ); - i++; - } - } - outlet_float( x->x_countout, i ); - - // delete lost objects - for ( im=0; imx_found[im] < 0 ) - { - x->x_xmark[im] = -1.0; - x->x_ymark[im] = -1,0; - x->x_found[im] = x->x_ftolerance; - SETFLOAT(&x->rlist[0], im); - SETFLOAT(&x->rlist[1], -1.0); - SETFLOAT(&x->rlist[2], -1.0); - SETFLOAT(&x->rlist[3], 0.0); - SETFLOAT(&x->rlist[4], 0.0); - outlet_list( x->x_dataout, 0, 5, x->rlist ); - } - } - - cvReleaseMemStorage( &stor02 ); - - memcpy( newdata, x->cnt_img->imageData, x->x_size*3 ); - - return; -} - -static void pdp_opencv_contours_boundingrect_minarea(t_pdp_opencv_contours_boundingrect *x, t_floatarg f) -{ - x->minarea = (int)f; -} - -static void pdp_opencv_contours_boundingrect_maxarea(t_pdp_opencv_contours_boundingrect *x, t_floatarg f) -{ - x->maxarea = (int)f; -} - -static void pdp_opencv_contours_boundingrect_ftolerance(t_pdp_opencv_contours_boundingrect *x, t_floatarg f) -{ - if ((int)f>=1) x->x_ftolerance = (int)f; -} - -static void pdp_opencv_contours_boundingrect_nightmode(t_pdp_opencv_contours_boundingrect *x, t_floatarg f) -{ - if ( ((int)f==1) || ((int)f==0) ) x->x_nightmode = (int)f; -} - -static void pdp_opencv_contours_boundingrect_draw(t_pdp_opencv_contours_boundingrect *x, t_floatarg f) -{ - if ( ((int)f==1) || ((int)f==0) ) x->x_draw = (int)f; -} - -static void pdp_opencv_contours_boundingrect_show(t_pdp_opencv_contours_boundingrect *x, t_floatarg f) -{ - if ( ((int)f==1) || ((int)f==0) ) x->x_show = (int)f; -} - -static void pdp_opencv_contours_boundingrect_mmove(t_pdp_opencv_contours_boundingrect *x, t_floatarg f) -{ - if ((int)f>=1) x->x_mmove = (int)f; -} - -static void pdp_opencv_contours_boundingrect_cmode(t_pdp_opencv_contours_boundingrect *x, t_floatarg f) -{ - // CV_RETR_EXTERNAL || CV_RETR_LIST || CV_RETR_CCOMP || CV_RETR_TREE - int mode = (int)f; - - if ( mode == CV_RETR_EXTERNAL ) - { - x->x_cmode = CV_RETR_EXTERNAL; - post( "pdp_opencv_contours_boundingrect : mode set to CV_RETR_EXTERNAL" ); - } - if ( mode == CV_RETR_LIST ) - { - x->x_cmode = CV_RETR_LIST; - post( "pdp_opencv_contours_boundingrect : mode set to CV_RETR_LIST" ); - } - if ( mode == CV_RETR_CCOMP ) - { - x->x_cmode = CV_RETR_CCOMP; - post( "pdp_opencv_contours_boundingrect : mode set to CV_RETR_CCOMP" ); - } - if ( mode == CV_RETR_TREE ) - { - x->x_cmode = CV_RETR_TREE; - post( "pdp_opencv_contours_boundingrect : mode set to CV_RETR_TREE" ); - } -} - -static void pdp_opencv_contours_boundingrect_cmethod(t_pdp_opencv_contours_boundingrect *x, t_floatarg f) -{ - int method = (int)f; - - // CV_CHAIN_CODE || CV_CHAIN_APPROX_NONE || CV_CHAIN_APPROX_SIMPLE || CV_CHAIN_APPROX_TC89_L1 || CV_CHAIN_APPROX_TC89_KCOS || CV_LINK_RUNS - if ( method == CV_CHAIN_CODE ) - { - post( "pdp_opencv_contours_boundingrect : not supported method : CV_CHAIN_CODE" ); - } - if ( method == CV_CHAIN_APPROX_NONE ) - { - x->x_cmethod = CV_CHAIN_APPROX_NONE; - post( "pdp_opencv_contours_boundingrect : method set to CV_CHAIN_APPROX_NONE" ); - } - if ( method == CV_CHAIN_APPROX_SIMPLE ) - { - x->x_cmethod = CV_CHAIN_APPROX_SIMPLE; - post( "pdp_opencv_contours_boundingrect : method set to CV_CHAIN_APPROX_SIMPLE" ); - } - if ( method == CV_CHAIN_APPROX_TC89_L1 ) - { - x->x_cmethod = CV_CHAIN_APPROX_TC89_L1; - post( "pdp_opencv_contours_boundingrect : method set to CV_CHAIN_APPROX_TC89_L1" ); - } - if ( method == CV_CHAIN_APPROX_TC89_KCOS ) - { - x->x_cmethod = CV_CHAIN_APPROX_TC89_KCOS; - post( "pdp_opencv_contours_boundingrect : method set to CV_CHAIN_APPROX_TC89_KCOS" ); - } - if ( ( method == CV_LINK_RUNS ) && ( x->x_cmode == CV_RETR_LIST ) ) - { - x->x_cmethod = CV_LINK_RUNS; - post( "pdp_opencv_contours_boundingrect : method set to CV_LINK_RUNS" ); - } -} - -static void pdp_opencv_contours_boundingrect_delete(t_pdp_opencv_contours_boundingrect *x, t_floatarg findex ) -{ - int i; - - if ( ( findex < 1.0 ) || ( findex > MAX_MARKERS ) ) - { - return; - } - - x->x_xmark[(int)findex-1] = -1; - x->x_ymark[(int)findex-1] = -1; -} - -static void pdp_opencv_contours_boundingrect_clear(t_pdp_opencv_contours_boundingrect *x ) -{ - int i; - - for ( i=0; ix_xmark[i] = -1; - x->x_ymark[i] = -1; - x->x_found[i] = x->x_ftolerance; - } -} - - -static void pdp_opencv_contours_boundingrect_sendpacket(t_pdp_opencv_contours_boundingrect *x) -{ - /* release the packet */ - pdp_packet_mark_unused(x->x_packet0); - x->x_packet0 = -1; - - /* unregister and propagate if valid dest packet */ - pdp_packet_pass_if_valid(x->x_outlet0, &x->x_packet1); -} - -static void pdp_opencv_contours_boundingrect_process(t_pdp_opencv_contours_boundingrect *x) -{ - int encoding; - t_pdp *header = 0; - char *parname; - unsigned pi; - int partype; - float pardefault; - t_atom plist[2]; - t_atom tlist[2]; - t_atom vlist[2]; - - /* check if image data packets are compatible */ - if ( (header = pdp_packet_header(x->x_packet0)) - && (PDP_BITMAP == header->type)){ - - /* pdp_opencv_contours_boundingrect_process inputs and write into active inlet */ - switch(pdp_packet_header(x->x_packet0)->info.image.encoding){ - - case PDP_BITMAP_RGB: - x->x_packet1 = pdp_packet_clone_rw(x->x_packet0); - pdp_queue_add(x, pdp_opencv_contours_boundingrect_process_rgb, pdp_opencv_contours_boundingrect_sendpacket, &x->x_queue_id); - break; - - default: - /* don't know the type, so dont pdp_opencv_contours_boundingrect_process */ - break; - - } - } - -} - -static void pdp_opencv_contours_boundingrect_input_0(t_pdp_opencv_contours_boundingrect *x, t_symbol *s, t_floatarg f) -{ - /* if this is a register_ro message or register_rw message, register with packet factory */ - - if (s == gensym("register_rw")) - x->x_dropped = pdp_packet_convert_ro_or_drop(&x->x_packet0, (int)f, pdp_gensym("bitmap/rgb/*") ); - - if ((s == gensym("process")) && (-1 != x->x_packet0) && (!x->x_dropped)) - { - /* add the process method and callback to the process queue */ - pdp_opencv_contours_boundingrect_process(x); - } -} - -static void pdp_opencv_contours_boundingrect_free(t_pdp_opencv_contours_boundingrect *x) -{ - int i; - - pdp_queue_finish(x->x_queue_id); - pdp_packet_mark_unused(x->x_packet0); - - //Destroy cv_images - cvReleaseImage(&x->image); - cvReleaseImage(&x->gray); - cvReleaseImage(&x->cnt_img); -} - -t_class *pdp_opencv_contours_boundingrect_class; - - -void *pdp_opencv_contours_boundingrect_new(t_floatarg f) -{ - int i; - - t_pdp_opencv_contours_boundingrect *x = (t_pdp_opencv_contours_boundingrect *)pd_new(pdp_opencv_contours_boundingrect_class); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("minarea")); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("maxarea")); - - x->x_outlet0 = outlet_new(&x->x_obj, &s_anything); - x->x_dataout = outlet_new(&x->x_obj, &s_anything); - x->x_countout = outlet_new(&x->x_obj, &s_float); - - x->x_packet0 = -1; - x->x_packet1 = -1; - x->x_queue_id = -1; - - x->x_width = 320; - x->x_height = 240; - x->x_size = x->x_width * x->x_height; - - x->minarea = 10*10; - x->maxarea = 320*240; - - x->x_ftolerance = 5; - x->x_mmove = 10; - x->x_cmode = CV_RETR_LIST; - x->x_cmethod = CV_CHAIN_APPROX_SIMPLE; - - x->x_nightmode = 0; - x->x_draw = 1; - x->x_show = 0; - - x->image = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 3); - x->gray = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 1); - x->cnt_img = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 3); - - // initialize font - cvInitFont( &x->font, CV_FONT_HERSHEY_PLAIN, 1.0, 1.0, 0, 1, 8 ); - - //contours = 0; - return (void *)x; -} - - -#ifdef __cplusplus -extern "C" -{ -#endif - - -void pdp_opencv_contours_boundingrect_setup(void) -{ - - post( " pdp_opencv_contours_boundingrect"); - pdp_opencv_contours_boundingrect_class = class_new(gensym("pdp_opencv_contours_boundingrect"), (t_newmethod)pdp_opencv_contours_boundingrect_new, - (t_method)pdp_opencv_contours_boundingrect_free, sizeof(t_pdp_opencv_contours_boundingrect), 0, A_DEFFLOAT, A_NULL); - - class_addmethod(pdp_opencv_contours_boundingrect_class, (t_method)pdp_opencv_contours_boundingrect_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL); - class_addmethod(pdp_opencv_contours_boundingrect_class, (t_method)pdp_opencv_contours_boundingrect_minarea, gensym("minarea"), A_FLOAT, A_NULL ); - class_addmethod(pdp_opencv_contours_boundingrect_class, (t_method)pdp_opencv_contours_boundingrect_maxarea, gensym("maxarea"), A_FLOAT, A_NULL ); - class_addmethod(pdp_opencv_contours_boundingrect_class, (t_method)pdp_opencv_contours_boundingrect_ftolerance, gensym("ftolerance"), A_FLOAT, A_NULL ); - class_addmethod(pdp_opencv_contours_boundingrect_class, (t_method)pdp_opencv_contours_boundingrect_mmove, gensym("maxmove"), A_FLOAT, A_NULL ); - class_addmethod(pdp_opencv_contours_boundingrect_class, (t_method)pdp_opencv_contours_boundingrect_clear, gensym("clear"), A_NULL ); - class_addmethod(pdp_opencv_contours_boundingrect_class, (t_method)pdp_opencv_contours_boundingrect_cmode, gensym("mode"), A_FLOAT, A_NULL ); - class_addmethod(pdp_opencv_contours_boundingrect_class, (t_method)pdp_opencv_contours_boundingrect_cmethod, gensym("method"), A_FLOAT, A_NULL ); - class_addmethod(pdp_opencv_contours_boundingrect_class, (t_method)pdp_opencv_contours_boundingrect_nightmode, gensym("nightmode"), A_FLOAT, A_NULL ); - class_addmethod(pdp_opencv_contours_boundingrect_class, (t_method)pdp_opencv_contours_boundingrect_draw, gensym("draw"), A_FLOAT, A_NULL ); - class_addmethod(pdp_opencv_contours_boundingrect_class, (t_method)pdp_opencv_contours_boundingrect_show, gensym("show"), A_FLOAT, A_NULL ); - -} - -#ifdef __cplusplus -} -#endif diff --git a/pdp_opencv_contours_boundingrect.cc b/pdp_opencv_contours_boundingrect.cc new file mode 100755 index 0000000..c8b747d --- /dev/null +++ b/pdp_opencv_contours_boundingrect.cc @@ -0,0 +1,534 @@ +/* + * Pure Data Packet module. + * Copyright (c) by Tom Schouten + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "pdp.h" + +#ifndef _EiC +#include "cv.h" +#endif + +#define MAX_MARKERS 100 + +typedef struct pdp_opencv_contours_boundingrect_struct +{ + t_object x_obj; + t_float x_f; + + t_outlet *x_outlet0; + t_outlet *x_dataout; + t_outlet *x_countout; + t_atom rlist[5]; + int x_packet0; + int x_packet1; + int x_dropped; + int x_queue_id; + int x_xmark[MAX_MARKERS]; + int x_ymark[MAX_MARKERS]; + int x_found[MAX_MARKERS]; + int x_ftolerance; + int x_mmove; + + // contours retrieval mode + int x_cmode; + // contours retrieval method + int x_cmethod; + + int x_width; + int x_height; + int x_size; + + int x_nightmode; // don't show the original image + int x_draw; // draw contours boundaries rectangles + int x_show; // show the real contour + + int minarea; + int maxarea; + IplImage *image, *gray, *cnt_img; + CvFont font; + +} t_pdp_opencv_contours_boundingrect; + +static int pdp_opencv_contours_boundingrect_mark(t_pdp_opencv_contours_boundingrect *x, t_floatarg fx, t_floatarg fy ) +{ + int i; + + if ( ( fx < 0.0 ) || ( fx > x->x_width ) || ( fy < 0 ) || ( fy > x->x_height ) ) + { + return -1; + } + + for ( i=0; ix_xmark[i] == -1 ) + { + x->x_xmark[i] = (int)fx; + x->x_ymark[i] = (int)fy; + x->x_found[i] = x->x_ftolerance; + return i; + } + } + + // post( "pdp_opencv_contours_boundingrect : max markers reached" ); + return -1; +} + +static void pdp_opencv_contours_boundingrect_process_rgb(t_pdp_opencv_contours_boundingrect *x) +{ + t_pdp *header = pdp_packet_header(x->x_packet0); + short int *data = (short int *)pdp_packet_data(x->x_packet0); + t_pdp *newheader = pdp_packet_header(x->x_packet1); + short int *newdata = (short int *)pdp_packet_data(x->x_packet1); + char tindex[4]; + int i = 0; // Indicator of cycles. + int im = 0; // Indicator of markers. + + if ((x->x_width != (t_int)header->info.image.width) || + (x->x_height != (t_int)header->info.image.height)) + { + + post("pdp_opencv_contours_boundingrect :: resizing plugins"); + + + x->x_width = header->info.image.width; + x->x_height = header->info.image.height; + x->x_size = x->x_width*x->x_height; + + //Destroy cv_images + cvReleaseImage(&x->image); + cvReleaseImage(&x->gray); + cvReleaseImage(&x->cnt_img); + + //create the orig image with new size + x->image = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 3); + + // Create the output images with new sizes + x->gray = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 1); + x->cnt_img = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 3); + + } + + newheader->info.image.encoding = header->info.image.encoding; + newheader->info.image.width = x->x_width; + newheader->info.image.height = x->x_height; + + memcpy( x->image->imageData, data, x->x_size*3 ); + + // Convert to grayscale + cvCvtColor(x->image, x->gray, CV_BGR2GRAY); + + CvSeq* contours; + CvMemStorage* stor02; + stor02 = cvCreateMemStorage(0); + + //TODO nous objectes ::: llegeixo el OpenCVRefenceManual i al capitol 11 Structural Analysis Reference + // m'en adono que + //de fet aquest objecte no s'ha de dir pdp_opencv_contours sino pdp_opencv_convexity + //el pdp_opencv_contours et donaria una llista de punts en els outles que serien els punts del contorn (poligonal o no)i + //i seria la base per a una serie de objectes basats en contorns + //el pdp_opencv_convexHull, el mateix pdp_opencv_convexity + //depres nhi ha un altre que surtiria d'aqui :: pdp_opencv_MinAreaRect i el pdp_opencv_MinEnclosingCircle + //ContourBoundingRect + // + + // Retrieval mode. + // CV_RETR_EXTERNAL || CV_RETR_LIST || CV_RETR_CCOMP || CV_RETR_TREE + // Approximation method. + // CV_CHAIN_CODE || CV_CHAIN_APPROX_NONE || CV_CHAIN_APPROX_SIMPLE || CV_CHAIN_APPROX_TC89_L1 || CV_CHAIN_APPROX_TC89_KCOS || CV_LINK_RUNS + cvFindContours( x->gray, stor02, &contours, sizeof(CvContour), x->x_cmode, x->x_cmethod, cvPoint(0,0) ); + + // TODO afegir parametres + // aqui es fa una aproximacio del contorn per a que sigui mes polinomic i no tingui tants punts + // els ultims dos parametres han de ser variables + // precision , recursive + if (contours) contours = cvApproxPoly( contours, sizeof(CvContour), stor02, CV_POLY_APPROX_DP, 3, 1 ); + + //TODO afegir parametre + //si volem veure la imatge original o un fons negre + cvCopy(x->image, x->cnt_img, NULL); + if ( x->x_nightmode ) + { + cvZero( x->cnt_img ); + } + + for ( im=0; imx_xmark[im] != -1.0 ) + { + x->x_found[im]--; + } + } + + for( ; contours != 0; contours = contours->h_next ) + { + int count = contours->total; // This is number point in contour + CvRect rect; + int oi, found; + + rect = cvContourBoundingRect( contours, 1); + if ( ( (rect.width*rect.height) > x->minarea ) && ( (rect.width*rect.height) < x->maxarea ) ) { + + found = 0; + oi = -1; + for ( im=0; imx_xmark[im] ) < x->x_mmove ) && ( abs( rect.y - x->x_ymark[im] ) < x->x_mmove ) ) + { + oi=im; + found=1; + x->x_found[im] = x->x_ftolerance; + x->x_xmark[im] = rect.x; + x->x_ymark[im] = rect.y; + break; + } + } + // new object detected + if ( !found ) + { + oi = pdp_opencv_contours_boundingrect_mark(x, rect.x, rect.y ); + } + + if ( x->x_draw ) + { + cvRectangle( x->cnt_img, cvPoint(rect.x,rect.y), cvPoint(rect.x+rect.width,rect.y+rect.height), CV_RGB(255,0,0), 2, 8 , 0 ); + sprintf( tindex, "%d", oi ); + cvPutText( x->cnt_img, tindex, cvPoint(rect.x,rect.y), &x->font, CV_RGB(255,255,255)); + } + + if ( x->x_show ) + { + cvDrawContours( x->cnt_img, contours, CV_RGB(255,255,255), CV_RGB(255,255,255), 0, 1, 8, cvPoint(0,0) ); + } + + SETFLOAT(&x->rlist[0], oi); + SETFLOAT(&x->rlist[1], rect.x); + SETFLOAT(&x->rlist[2], rect.y); + SETFLOAT(&x->rlist[3], rect.width); + SETFLOAT(&x->rlist[4], rect.height); + + outlet_list( x->x_dataout, 0, 5, x->rlist ); + i++; + } + } + outlet_float( x->x_countout, i ); + + // delete lost objects + for ( im=0; imx_found[im] < 0 ) + { + x->x_xmark[im] = -1.0; + x->x_ymark[im] = -1,0; + x->x_found[im] = x->x_ftolerance; + SETFLOAT(&x->rlist[0], im); + SETFLOAT(&x->rlist[1], -1.0); + SETFLOAT(&x->rlist[2], -1.0); + SETFLOAT(&x->rlist[3], 0.0); + SETFLOAT(&x->rlist[4], 0.0); + outlet_list( x->x_dataout, 0, 5, x->rlist ); + } + } + + cvReleaseMemStorage( &stor02 ); + + memcpy( newdata, x->cnt_img->imageData, x->x_size*3 ); + + return; +} + +static void pdp_opencv_contours_boundingrect_minarea(t_pdp_opencv_contours_boundingrect *x, t_floatarg f) +{ + x->minarea = (int)f; +} + +static void pdp_opencv_contours_boundingrect_maxarea(t_pdp_opencv_contours_boundingrect *x, t_floatarg f) +{ + x->maxarea = (int)f; +} + +static void pdp_opencv_contours_boundingrect_ftolerance(t_pdp_opencv_contours_boundingrect *x, t_floatarg f) +{ + if ((int)f>=1) x->x_ftolerance = (int)f; +} + +static void pdp_opencv_contours_boundingrect_nightmode(t_pdp_opencv_contours_boundingrect *x, t_floatarg f) +{ + if ( ((int)f==1) || ((int)f==0) ) x->x_nightmode = (int)f; +} + +static void pdp_opencv_contours_boundingrect_draw(t_pdp_opencv_contours_boundingrect *x, t_floatarg f) +{ + if ( ((int)f==1) || ((int)f==0) ) x->x_draw = (int)f; +} + +static void pdp_opencv_contours_boundingrect_show(t_pdp_opencv_contours_boundingrect *x, t_floatarg f) +{ + if ( ((int)f==1) || ((int)f==0) ) x->x_show = (int)f; +} + +static void pdp_opencv_contours_boundingrect_mmove(t_pdp_opencv_contours_boundingrect *x, t_floatarg f) +{ + if ((int)f>=1) x->x_mmove = (int)f; +} + +static void pdp_opencv_contours_boundingrect_cmode(t_pdp_opencv_contours_boundingrect *x, t_floatarg f) +{ + // CV_RETR_EXTERNAL || CV_RETR_LIST || CV_RETR_CCOMP || CV_RETR_TREE + int mode = (int)f; + + if ( mode == CV_RETR_EXTERNAL ) + { + x->x_cmode = CV_RETR_EXTERNAL; + post( "pdp_opencv_contours_boundingrect : mode set to CV_RETR_EXTERNAL" ); + } + if ( mode == CV_RETR_LIST ) + { + x->x_cmode = CV_RETR_LIST; + post( "pdp_opencv_contours_boundingrect : mode set to CV_RETR_LIST" ); + } + if ( mode == CV_RETR_CCOMP ) + { + x->x_cmode = CV_RETR_CCOMP; + post( "pdp_opencv_contours_boundingrect : mode set to CV_RETR_CCOMP" ); + } + if ( mode == CV_RETR_TREE ) + { + x->x_cmode = CV_RETR_TREE; + post( "pdp_opencv_contours_boundingrect : mode set to CV_RETR_TREE" ); + } +} + +static void pdp_opencv_contours_boundingrect_cmethod(t_pdp_opencv_contours_boundingrect *x, t_floatarg f) +{ + int method = (int)f; + + // CV_CHAIN_CODE || CV_CHAIN_APPROX_NONE || CV_CHAIN_APPROX_SIMPLE || CV_CHAIN_APPROX_TC89_L1 || CV_CHAIN_APPROX_TC89_KCOS || CV_LINK_RUNS + if ( method == CV_CHAIN_CODE ) + { + post( "pdp_opencv_contours_boundingrect : not supported method : CV_CHAIN_CODE" ); + } + if ( method == CV_CHAIN_APPROX_NONE ) + { + x->x_cmethod = CV_CHAIN_APPROX_NONE; + post( "pdp_opencv_contours_boundingrect : method set to CV_CHAIN_APPROX_NONE" ); + } + if ( method == CV_CHAIN_APPROX_SIMPLE ) + { + x->x_cmethod = CV_CHAIN_APPROX_SIMPLE; + post( "pdp_opencv_contours_boundingrect : method set to CV_CHAIN_APPROX_SIMPLE" ); + } + if ( method == CV_CHAIN_APPROX_TC89_L1 ) + { + x->x_cmethod = CV_CHAIN_APPROX_TC89_L1; + post( "pdp_opencv_contours_boundingrect : method set to CV_CHAIN_APPROX_TC89_L1" ); + } + if ( method == CV_CHAIN_APPROX_TC89_KCOS ) + { + x->x_cmethod = CV_CHAIN_APPROX_TC89_KCOS; + post( "pdp_opencv_contours_boundingrect : method set to CV_CHAIN_APPROX_TC89_KCOS" ); + } + if ( ( method == CV_LINK_RUNS ) && ( x->x_cmode == CV_RETR_LIST ) ) + { + x->x_cmethod = CV_LINK_RUNS; + post( "pdp_opencv_contours_boundingrect : method set to CV_LINK_RUNS" ); + } +} + +static void pdp_opencv_contours_boundingrect_delete(t_pdp_opencv_contours_boundingrect *x, t_floatarg findex ) +{ + int i; + + if ( ( findex < 1.0 ) || ( findex > MAX_MARKERS ) ) + { + return; + } + + x->x_xmark[(int)findex-1] = -1; + x->x_ymark[(int)findex-1] = -1; +} + +static void pdp_opencv_contours_boundingrect_clear(t_pdp_opencv_contours_boundingrect *x ) +{ + int i; + + for ( i=0; ix_xmark[i] = -1; + x->x_ymark[i] = -1; + x->x_found[i] = x->x_ftolerance; + } +} + + +static void pdp_opencv_contours_boundingrect_sendpacket(t_pdp_opencv_contours_boundingrect *x) +{ + /* release the packet */ + pdp_packet_mark_unused(x->x_packet0); + x->x_packet0 = -1; + + /* unregister and propagate if valid dest packet */ + pdp_packet_pass_if_valid(x->x_outlet0, &x->x_packet1); +} + +static void pdp_opencv_contours_boundingrect_process(t_pdp_opencv_contours_boundingrect *x) +{ + int encoding; + t_pdp *header = 0; + char *parname; + unsigned pi; + int partype; + float pardefault; + t_atom plist[2]; + t_atom tlist[2]; + t_atom vlist[2]; + + /* check if image data packets are compatible */ + if ( (header = pdp_packet_header(x->x_packet0)) + && (PDP_BITMAP == header->type)){ + + /* pdp_opencv_contours_boundingrect_process inputs and write into active inlet */ + switch(pdp_packet_header(x->x_packet0)->info.image.encoding){ + + case PDP_BITMAP_RGB: + x->x_packet1 = pdp_packet_clone_rw(x->x_packet0); + pdp_queue_add(x, (void*)pdp_opencv_contours_boundingrect_process_rgb, (void*)pdp_opencv_contours_boundingrect_sendpacket, &x->x_queue_id); + break; + + default: + /* don't know the type, so dont pdp_opencv_contours_boundingrect_process */ + break; + + } + } + +} + +static void pdp_opencv_contours_boundingrect_input_0(t_pdp_opencv_contours_boundingrect *x, t_symbol *s, t_floatarg f) +{ + /* if this is a register_ro message or register_rw message, register with packet factory */ + + if (s == gensym("register_rw")) + x->x_dropped = pdp_packet_convert_ro_or_drop(&x->x_packet0, (int)f, pdp_gensym((char*)"bitmap/rgb/*") ); + + if ((s == gensym("process")) && (-1 != x->x_packet0) && (!x->x_dropped)) + { + /* add the process method and callback to the process queue */ + pdp_opencv_contours_boundingrect_process(x); + } +} + +static void pdp_opencv_contours_boundingrect_free(t_pdp_opencv_contours_boundingrect *x) +{ + int i; + + pdp_queue_finish(x->x_queue_id); + pdp_packet_mark_unused(x->x_packet0); + + //Destroy cv_images + cvReleaseImage(&x->image); + cvReleaseImage(&x->gray); + cvReleaseImage(&x->cnt_img); +} + +t_class *pdp_opencv_contours_boundingrect_class; + + +void *pdp_opencv_contours_boundingrect_new(t_floatarg f) +{ + int i; + + t_pdp_opencv_contours_boundingrect *x = (t_pdp_opencv_contours_boundingrect *)pd_new(pdp_opencv_contours_boundingrect_class); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("minarea")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("maxarea")); + + x->x_outlet0 = outlet_new(&x->x_obj, &s_anything); + x->x_dataout = outlet_new(&x->x_obj, &s_anything); + x->x_countout = outlet_new(&x->x_obj, &s_float); + + x->x_packet0 = -1; + x->x_packet1 = -1; + x->x_queue_id = -1; + + x->x_width = 320; + x->x_height = 240; + x->x_size = x->x_width * x->x_height; + + x->minarea = 10*10; + x->maxarea = 320*240; + + x->x_ftolerance = 5; + x->x_mmove = 10; + x->x_cmode = CV_RETR_LIST; + x->x_cmethod = CV_CHAIN_APPROX_SIMPLE; + + x->x_nightmode = 0; + x->x_draw = 1; + x->x_show = 0; + + x->image = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 3); + x->gray = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 1); + x->cnt_img = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 3); + + // initialize font + cvInitFont( &x->font, CV_FONT_HERSHEY_PLAIN, 1.0, 1.0, 0, 1, 8 ); + + //contours = 0; + return (void *)x; +} + + +#ifdef __cplusplus +extern "C" +{ +#endif + + +void pdp_opencv_contours_boundingrect_setup(void) +{ + + post( " pdp_opencv_contours_boundingrect"); + pdp_opencv_contours_boundingrect_class = class_new(gensym("pdp_opencv_contours_boundingrect"), (t_newmethod)pdp_opencv_contours_boundingrect_new, + (t_method)pdp_opencv_contours_boundingrect_free, sizeof(t_pdp_opencv_contours_boundingrect), 0, A_DEFFLOAT, A_NULL); + + class_addmethod(pdp_opencv_contours_boundingrect_class, (t_method)pdp_opencv_contours_boundingrect_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL); + class_addmethod(pdp_opencv_contours_boundingrect_class, (t_method)pdp_opencv_contours_boundingrect_minarea, gensym("minarea"), A_FLOAT, A_NULL ); + class_addmethod(pdp_opencv_contours_boundingrect_class, (t_method)pdp_opencv_contours_boundingrect_maxarea, gensym("maxarea"), A_FLOAT, A_NULL ); + class_addmethod(pdp_opencv_contours_boundingrect_class, (t_method)pdp_opencv_contours_boundingrect_ftolerance, gensym("ftolerance"), A_FLOAT, A_NULL ); + class_addmethod(pdp_opencv_contours_boundingrect_class, (t_method)pdp_opencv_contours_boundingrect_mmove, gensym("maxmove"), A_FLOAT, A_NULL ); + class_addmethod(pdp_opencv_contours_boundingrect_class, (t_method)pdp_opencv_contours_boundingrect_clear, gensym("clear"), A_NULL ); + class_addmethod(pdp_opencv_contours_boundingrect_class, (t_method)pdp_opencv_contours_boundingrect_cmode, gensym("mode"), A_FLOAT, A_NULL ); + class_addmethod(pdp_opencv_contours_boundingrect_class, (t_method)pdp_opencv_contours_boundingrect_cmethod, gensym("method"), A_FLOAT, A_NULL ); + class_addmethod(pdp_opencv_contours_boundingrect_class, (t_method)pdp_opencv_contours_boundingrect_nightmode, gensym("nightmode"), A_FLOAT, A_NULL ); + class_addmethod(pdp_opencv_contours_boundingrect_class, (t_method)pdp_opencv_contours_boundingrect_draw, gensym("draw"), A_FLOAT, A_NULL ); + class_addmethod(pdp_opencv_contours_boundingrect_class, (t_method)pdp_opencv_contours_boundingrect_show, gensym("show"), A_FLOAT, A_NULL ); + +} + +#ifdef __cplusplus +} +#endif diff --git a/pdp_opencv_contours_convexhull.c b/pdp_opencv_contours_convexhull.c deleted file mode 100644 index 59235d1..0000000 --- a/pdp_opencv_contours_convexhull.c +++ /dev/null @@ -1,411 +0,0 @@ -/* - * Pure Data Packet module. - * Copyright (c) by Tom Schouten - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "pdp.h" - -#ifndef _EiC -#include "cv.h" -#endif - -#define MAX_MARKERS 100 - -typedef struct pdp_opencv_contours_convexhull_struct -{ - t_object x_obj; - t_float x_f; - - t_outlet *x_outlet0; - t_outlet *x_dataout; - t_outlet *x_countout; - t_atom rlist[5]; - int x_packet0; - int x_packet1; - int x_dropped; - int x_queue_id; - - // contours retrieval mode - int x_cmode; - // contours retrieval method - int x_cmethod; - int x_accuracy; - - int x_width; - int x_height; - int x_size; - - int x_nightmode; // don't show the original image - - IplImage *image, *gray, *cnt_img; - -} t_pdp_opencv_contours_convexhull; - -static void pdp_opencv_contours_convexhull_process_rgb(t_pdp_opencv_contours_convexhull *x) -{ - t_pdp *header = pdp_packet_header(x->x_packet0); - short int *data = (short int *)pdp_packet_data(x->x_packet0); - t_pdp *newheader = pdp_packet_header(x->x_packet1); - short int *newdata = (short int *)pdp_packet_data(x->x_packet1); - char tindex[4]; - int i = 0; // Indicator of cycles. - int j=0; - int k = 0; - int area = 0; - int selected = -1; - CvSeq* first_contour; - CvSeq* defects; - CvSeq* contours; - int* hull; - int hullsize; - CvPoint* PointArray; - CvConvexityDefect* defectArray; - CvMemStorage* stor02; - CvMemStorage* stor03; - - stor02 = cvCreateMemStorage(0); - stor03 = cvCreateMemStorage(0); - - if ((x->x_width != (t_int)header->info.image.width) || - (x->x_height != (t_int)header->info.image.height)) - { - - post("pdp_opencv_contours_convexhull :: resizing plugins"); - - - x->x_width = header->info.image.width; - x->x_height = header->info.image.height; - x->x_size = x->x_width*x->x_height; - - //Destroy cv_images - cvReleaseImage(&x->image); - cvReleaseImage(&x->gray); - cvReleaseImage(&x->cnt_img); - - //create the orig image with new size - x->image = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 3); - - // Create the output images with new sizes - x->gray = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 1); - x->cnt_img = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 3); - - } - - newheader->info.image.encoding = header->info.image.encoding; - newheader->info.image.width = x->x_width; - newheader->info.image.height = x->x_height; - - memcpy( x->image->imageData, data, x->x_size*3 ); - - // Convert to grayscale - cvCvtColor(x->image, x->gray, CV_BGR2GRAY); - - // Retrieval mode. - // CV_RETR_EXTERNAL || CV_RETR_LIST || CV_RETR_CCOMP || CV_RETR_TREE - // Approximation method. - // CV_CHAIN_CODE || CV_CHAIN_APPROX_NONE || CV_CHAIN_APPROX_SIMPLE || CV_CHAIN_APPROX_TC89_L1 || CV_CHAIN_APPROX_TC89_KCOS || CV_LINK_RUNS - - cvFindContours( x->gray, stor02, &contours, sizeof(CvContour), x->x_cmode, x->x_cmethod, cvPoint(0,0) ); - if (contours) contours = cvApproxPoly( contours, sizeof(CvContour), stor02, CV_POLY_APPROX_DP, x->x_accuracy, 1 ); - - cvCopy(x->image, x->cnt_img, NULL); - if ( x->x_nightmode ) - { - cvZero( x->cnt_img ); - } - - first_contour = contours; - - // searching for biggest contour - for( ; contours != 0; contours = contours->h_next ) - { - CvRect rect; - rect = cvContourBoundingRect(contours, 1); - if ( (rect.width*rect.height) > area ) - { - selected = i; - area = rect.width*rect.height; - } - i++; - } - - contours = first_contour; - for( ; contours != 0; contours = contours->h_next ) - { - int count = contours->total; // This is number point in contour - CvPoint center; - CvSize size; - CvRect rect; - - rect = cvContourBoundingRect( contours, 1); - if ( (k==selected) ) - { - PointArray = (CvPoint*)malloc( count*sizeof(CvPoint) ); - hull = (int*)malloc(sizeof(int)*count); - cvCvtSeqToArray(contours, PointArray, CV_WHOLE_SEQ); - - cvConvexHull( PointArray, - count, - NULL, - CV_COUNTER_CLOCKWISE, - hull, - &hullsize); - - outlet_float( x->x_countout, hullsize ); - - t_atom rlist[hullsize*2]; - - // Draw convex hull for current contour. - for(i=0; icnt_img, PointArray[hull[i]], PointArray[hull[i+1]],CV_RGB(0,0,255),3, CV_AA, 0 ); - SETFLOAT(&rlist[j], PointArray[hull[i]].x); - SETFLOAT(&rlist[j+1], PointArray[hull[i]].y); - j = j + 2; - } - - cvLine(x->cnt_img, PointArray[hull[hullsize-1]], PointArray[hull[0]],CV_RGB(0,0,255),3, CV_AA, 0 ); - SETFLOAT(&rlist[j], PointArray[hull[i]].x); - SETFLOAT(&rlist[j+1], PointArray[hull[i]].y); - outlet_list( x->x_dataout, 0, hullsize*2, rlist ); - - free(PointArray); - free(hull); - } - k++; - } - - cvReleaseMemStorage( &stor03 ); - cvReleaseMemStorage( &stor02 ); - - memcpy( newdata, x->cnt_img->imageData, x->x_size*3 ); - - return; -} - -static void pdp_opencv_contours_convexhull_nightmode(t_pdp_opencv_contours_convexhull *x, t_floatarg f) -{ - if ( ((int)f==1) || ((int)f==0) ) x->x_nightmode = (int)f; -} - -static void pdp_opencv_contours_convexhull_accuracy(t_pdp_opencv_contours_convexhull *x, t_floatarg f) -{ - if ((int)f>=0) x->x_accuracy = (int)f; -} - -static void pdp_opencv_contours_convexhull_cmode(t_pdp_opencv_contours_convexhull *x, t_floatarg f) -{ - // CV_RETR_EXTERNAL || CV_RETR_LIST || CV_RETR_CCOMP || CV_RETR_TREE - int mode = (int)f; - - if ( mode == CV_RETR_EXTERNAL ) - { - x->x_cmode = CV_RETR_EXTERNAL; - post( "pdp_opencv_contours_convexhull : mode set to CV_RETR_EXTERNAL" ); - } - if ( mode == CV_RETR_LIST ) - { - x->x_cmode = CV_RETR_LIST; - post( "pdp_opencv_contours_convexhull : mode set to CV_RETR_LIST" ); - } - if ( mode == CV_RETR_CCOMP ) - { - x->x_cmode = CV_RETR_CCOMP; - post( "pdp_opencv_contours_convexhull : mode set to CV_RETR_CCOMP" ); - } - if ( mode == CV_RETR_TREE ) - { - x->x_cmode = CV_RETR_TREE; - post( "pdp_opencv_contours_convexhull : mode set to CV_RETR_TREE" ); - } -} - -static void pdp_opencv_contours_convexhull_cmethod(t_pdp_opencv_contours_convexhull *x, t_floatarg f) -{ - int method = (int)f; - - // CV_CHAIN_CODE || CV_CHAIN_APPROX_NONE || CV_CHAIN_APPROX_SIMPLE || CV_CHAIN_APPROX_TC89_L1 || CV_CHAIN_APPROX_TC89_KCOS || CV_LINK_RUNS - if ( method == CV_CHAIN_CODE ) - { - post( "pdp_opencv_contours_convexhull : not supported method : CV_CHAIN_CODE" ); - } - if ( method == CV_CHAIN_APPROX_NONE ) - { - x->x_cmethod = CV_CHAIN_APPROX_NONE; - post( "pdp_opencv_contours_convexhull : method set to CV_CHAIN_APPROX_NONE" ); - } - if ( method == CV_CHAIN_APPROX_SIMPLE ) - { - x->x_cmethod = CV_CHAIN_APPROX_SIMPLE; - post( "pdp_opencv_contours_convexhull : method set to CV_CHAIN_APPROX_SIMPLE" ); - } - if ( method == CV_CHAIN_APPROX_TC89_L1 ) - { - x->x_cmethod = CV_CHAIN_APPROX_TC89_L1; - post( "pdp_opencv_contours_convexhull : method set to CV_CHAIN_APPROX_TC89_L1" ); - } - if ( method == CV_CHAIN_APPROX_TC89_KCOS ) - { - x->x_cmethod = CV_CHAIN_APPROX_TC89_KCOS; - post( "pdp_opencv_contours_convexhull : method set to CV_CHAIN_APPROX_TC89_KCOS" ); - } - if ( ( method == CV_LINK_RUNS ) && ( x->x_cmode == CV_RETR_LIST ) ) - { - x->x_cmethod = CV_LINK_RUNS; - post( "pdp_opencv_contours_convexhull : method set to CV_LINK_RUNS" ); - } -} - -static void pdp_opencv_contours_convexhull_sendpacket(t_pdp_opencv_contours_convexhull *x) -{ - /* release the packet */ - pdp_packet_mark_unused(x->x_packet0); - x->x_packet0 = -1; - - /* unregister and propagate if valid dest packet */ - pdp_packet_pass_if_valid(x->x_outlet0, &x->x_packet1); -} - -static void pdp_opencv_contours_convexhull_process(t_pdp_opencv_contours_convexhull *x) -{ - int encoding; - t_pdp *header = 0; - char *parname; - unsigned pi; - int partype; - float pardefault; - t_atom plist[2]; - t_atom tlist[2]; - t_atom vlist[2]; - - /* check if image data packets are compatible */ - if ( (header = pdp_packet_header(x->x_packet0)) - && (PDP_BITMAP == header->type)){ - - /* pdp_opencv_contours_convexhull_process inputs and write into active inlet */ - switch(pdp_packet_header(x->x_packet0)->info.image.encoding){ - - case PDP_BITMAP_RGB: - x->x_packet1 = pdp_packet_clone_rw(x->x_packet0); - pdp_queue_add(x, pdp_opencv_contours_convexhull_process_rgb, pdp_opencv_contours_convexhull_sendpacket, &x->x_queue_id); - break; - - default: - /* don't know the type, so dont pdp_opencv_contours_convexhull_process */ - break; - - } - } - -} - -static void pdp_opencv_contours_convexhull_input_0(t_pdp_opencv_contours_convexhull *x, t_symbol *s, t_floatarg f) -{ - /* if this is a register_ro message or register_rw message, register with packet factory */ - - if (s == gensym("register_rw")) - x->x_dropped = pdp_packet_convert_ro_or_drop(&x->x_packet0, (int)f, pdp_gensym("bitmap/rgb/*") ); - - if ((s == gensym("process")) && (-1 != x->x_packet0) && (!x->x_dropped)) - { - /* add the process method and callback to the process queue */ - pdp_opencv_contours_convexhull_process(x); - } -} - -static void pdp_opencv_contours_convexhull_free(t_pdp_opencv_contours_convexhull *x) -{ - int i; - - pdp_queue_finish(x->x_queue_id); - pdp_packet_mark_unused(x->x_packet0); - - //Destroy cv_images - cvReleaseImage(&x->image); - cvReleaseImage(&x->gray); - cvReleaseImage(&x->cnt_img); -} - -t_class *pdp_opencv_contours_convexhull_class; - - -void *pdp_opencv_contours_convexhull_new(t_floatarg f) -{ - int i; - - t_pdp_opencv_contours_convexhull *x = (t_pdp_opencv_contours_convexhull *)pd_new(pdp_opencv_contours_convexhull_class); - - x->x_outlet0 = outlet_new(&x->x_obj, &s_anything); - x->x_countout = outlet_new(&x->x_obj, &s_float); - x->x_dataout = outlet_new(&x->x_obj, &s_anything); - - x->x_packet0 = -1; - x->x_packet1 = -1; - x->x_queue_id = -1; - - x->x_width = 320; - x->x_height = 240; - x->x_size = x->x_width * x->x_height; - - x->x_cmode = CV_RETR_LIST; - x->x_cmethod = CV_CHAIN_APPROX_SIMPLE; - - x->x_nightmode = 0; - x->x_accuracy = 3; - - x->image = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 3); - x->gray = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 1); - x->cnt_img = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 3); - - //contours = 0; - return (void *)x; -} - - -#ifdef __cplusplus -extern "C" -{ -#endif - - -void pdp_opencv_contours_convexhull_setup(void) -{ - - post( " pdp_opencv_contours_convexhull"); - pdp_opencv_contours_convexhull_class = class_new(gensym("pdp_opencv_contours_convexhull"), (t_newmethod)pdp_opencv_contours_convexhull_new, - (t_method)pdp_opencv_contours_convexhull_free, sizeof(t_pdp_opencv_contours_convexhull), 0, A_DEFFLOAT, A_NULL); - - class_addmethod(pdp_opencv_contours_convexhull_class, (t_method)pdp_opencv_contours_convexhull_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL); - class_addmethod(pdp_opencv_contours_convexhull_class, (t_method)pdp_opencv_contours_convexhull_cmode, gensym("mode"), A_FLOAT, A_NULL ); - class_addmethod(pdp_opencv_contours_convexhull_class, (t_method)pdp_opencv_contours_convexhull_cmethod, gensym("method"), A_FLOAT, A_NULL ); - class_addmethod(pdp_opencv_contours_convexhull_class, (t_method)pdp_opencv_contours_convexhull_nightmode, gensym("nightmode"), A_FLOAT, A_NULL ); - class_addmethod(pdp_opencv_contours_convexhull_class, (t_method)pdp_opencv_contours_convexhull_accuracy, gensym("accuracy"), A_FLOAT, A_NULL ); - -} - -#ifdef __cplusplus -} -#endif diff --git a/pdp_opencv_contours_convexhull.cc b/pdp_opencv_contours_convexhull.cc new file mode 100644 index 0000000..f57515f --- /dev/null +++ b/pdp_opencv_contours_convexhull.cc @@ -0,0 +1,411 @@ +/* + * Pure Data Packet module. + * Copyright (c) by Tom Schouten + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "pdp.h" + +#ifndef _EiC +#include "cv.h" +#endif + +#define MAX_MARKERS 100 + +typedef struct pdp_opencv_contours_convexhull_struct +{ + t_object x_obj; + t_float x_f; + + t_outlet *x_outlet0; + t_outlet *x_dataout; + t_outlet *x_countout; + t_atom rlist[5]; + int x_packet0; + int x_packet1; + int x_dropped; + int x_queue_id; + + // contours retrieval mode + int x_cmode; + // contours retrieval method + int x_cmethod; + int x_accuracy; + + int x_width; + int x_height; + int x_size; + + int x_nightmode; // don't show the original image + + IplImage *image, *gray, *cnt_img; + +} t_pdp_opencv_contours_convexhull; + +static void pdp_opencv_contours_convexhull_process_rgb(t_pdp_opencv_contours_convexhull *x) +{ + t_pdp *header = pdp_packet_header(x->x_packet0); + short int *data = (short int *)pdp_packet_data(x->x_packet0); + t_pdp *newheader = pdp_packet_header(x->x_packet1); + short int *newdata = (short int *)pdp_packet_data(x->x_packet1); + char tindex[4]; + int i = 0; // Indicator of cycles. + int j=0; + int k = 0; + int area = 0; + int selected = -1; + CvSeq* first_contour; + CvSeq* defects; + CvSeq* contours; + int* hull; + int hullsize; + CvPoint* PointArray; + CvConvexityDefect* defectArray; + CvMemStorage* stor02; + CvMemStorage* stor03; + + stor02 = cvCreateMemStorage(0); + stor03 = cvCreateMemStorage(0); + + if ((x->x_width != (t_int)header->info.image.width) || + (x->x_height != (t_int)header->info.image.height)) + { + + post("pdp_opencv_contours_convexhull :: resizing plugins"); + + + x->x_width = header->info.image.width; + x->x_height = header->info.image.height; + x->x_size = x->x_width*x->x_height; + + //Destroy cv_images + cvReleaseImage(&x->image); + cvReleaseImage(&x->gray); + cvReleaseImage(&x->cnt_img); + + //create the orig image with new size + x->image = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 3); + + // Create the output images with new sizes + x->gray = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 1); + x->cnt_img = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 3); + + } + + newheader->info.image.encoding = header->info.image.encoding; + newheader->info.image.width = x->x_width; + newheader->info.image.height = x->x_height; + + memcpy( x->image->imageData, data, x->x_size*3 ); + + // Convert to grayscale + cvCvtColor(x->image, x->gray, CV_BGR2GRAY); + + // Retrieval mode. + // CV_RETR_EXTERNAL || CV_RETR_LIST || CV_RETR_CCOMP || CV_RETR_TREE + // Approximation method. + // CV_CHAIN_CODE || CV_CHAIN_APPROX_NONE || CV_CHAIN_APPROX_SIMPLE || CV_CHAIN_APPROX_TC89_L1 || CV_CHAIN_APPROX_TC89_KCOS || CV_LINK_RUNS + + cvFindContours( x->gray, stor02, &contours, sizeof(CvContour), x->x_cmode, x->x_cmethod, cvPoint(0,0) ); + if (contours) contours = cvApproxPoly( contours, sizeof(CvContour), stor02, CV_POLY_APPROX_DP, x->x_accuracy, 1 ); + + cvCopy(x->image, x->cnt_img, NULL); + if ( x->x_nightmode ) + { + cvZero( x->cnt_img ); + } + + first_contour = contours; + + // searching for biggest contour + for( ; contours != 0; contours = contours->h_next ) + { + CvRect rect; + rect = cvContourBoundingRect(contours, 1); + if ( (rect.width*rect.height) > area ) + { + selected = i; + area = rect.width*rect.height; + } + i++; + } + + contours = first_contour; + for( ; contours != 0; contours = contours->h_next ) + { + int count = contours->total; // This is number point in contour + CvPoint center; + CvSize size; + CvRect rect; + + rect = cvContourBoundingRect( contours, 1); + if ( (k==selected) ) + { + PointArray = (CvPoint*)malloc( count*sizeof(CvPoint) ); + hull = (int*)malloc(sizeof(int)*count); + cvCvtSeqToArray(contours, PointArray, CV_WHOLE_SEQ); + + cvConvexHull( PointArray, + count, + NULL, + CV_COUNTER_CLOCKWISE, + hull, + &hullsize); + + outlet_float( x->x_countout, hullsize ); + + t_atom rlist[hullsize*2]; + + // Draw convex hull for current contour. + for(i=0; icnt_img, PointArray[hull[i]], PointArray[hull[i+1]],CV_RGB(0,0,255),3, CV_AA, 0 ); + SETFLOAT(&rlist[j], PointArray[hull[i]].x); + SETFLOAT(&rlist[j+1], PointArray[hull[i]].y); + j = j + 2; + } + + cvLine(x->cnt_img, PointArray[hull[hullsize-1]], PointArray[hull[0]],CV_RGB(0,0,255),3, CV_AA, 0 ); + SETFLOAT(&rlist[j], PointArray[hull[i]].x); + SETFLOAT(&rlist[j+1], PointArray[hull[i]].y); + outlet_list( x->x_dataout, 0, hullsize*2, rlist ); + + free(PointArray); + free(hull); + } + k++; + } + + cvReleaseMemStorage( &stor03 ); + cvReleaseMemStorage( &stor02 ); + + memcpy( newdata, x->cnt_img->imageData, x->x_size*3 ); + + return; +} + +static void pdp_opencv_contours_convexhull_nightmode(t_pdp_opencv_contours_convexhull *x, t_floatarg f) +{ + if ( ((int)f==1) || ((int)f==0) ) x->x_nightmode = (int)f; +} + +static void pdp_opencv_contours_convexhull_accuracy(t_pdp_opencv_contours_convexhull *x, t_floatarg f) +{ + if ((int)f>=0) x->x_accuracy = (int)f; +} + +static void pdp_opencv_contours_convexhull_cmode(t_pdp_opencv_contours_convexhull *x, t_floatarg f) +{ + // CV_RETR_EXTERNAL || CV_RETR_LIST || CV_RETR_CCOMP || CV_RETR_TREE + int mode = (int)f; + + if ( mode == CV_RETR_EXTERNAL ) + { + x->x_cmode = CV_RETR_EXTERNAL; + post( "pdp_opencv_contours_convexhull : mode set to CV_RETR_EXTERNAL" ); + } + if ( mode == CV_RETR_LIST ) + { + x->x_cmode = CV_RETR_LIST; + post( "pdp_opencv_contours_convexhull : mode set to CV_RETR_LIST" ); + } + if ( mode == CV_RETR_CCOMP ) + { + x->x_cmode = CV_RETR_CCOMP; + post( "pdp_opencv_contours_convexhull : mode set to CV_RETR_CCOMP" ); + } + if ( mode == CV_RETR_TREE ) + { + x->x_cmode = CV_RETR_TREE; + post( "pdp_opencv_contours_convexhull : mode set to CV_RETR_TREE" ); + } +} + +static void pdp_opencv_contours_convexhull_cmethod(t_pdp_opencv_contours_convexhull *x, t_floatarg f) +{ + int method = (int)f; + + // CV_CHAIN_CODE || CV_CHAIN_APPROX_NONE || CV_CHAIN_APPROX_SIMPLE || CV_CHAIN_APPROX_TC89_L1 || CV_CHAIN_APPROX_TC89_KCOS || CV_LINK_RUNS + if ( method == CV_CHAIN_CODE ) + { + post( "pdp_opencv_contours_convexhull : not supported method : CV_CHAIN_CODE" ); + } + if ( method == CV_CHAIN_APPROX_NONE ) + { + x->x_cmethod = CV_CHAIN_APPROX_NONE; + post( "pdp_opencv_contours_convexhull : method set to CV_CHAIN_APPROX_NONE" ); + } + if ( method == CV_CHAIN_APPROX_SIMPLE ) + { + x->x_cmethod = CV_CHAIN_APPROX_SIMPLE; + post( "pdp_opencv_contours_convexhull : method set to CV_CHAIN_APPROX_SIMPLE" ); + } + if ( method == CV_CHAIN_APPROX_TC89_L1 ) + { + x->x_cmethod = CV_CHAIN_APPROX_TC89_L1; + post( "pdp_opencv_contours_convexhull : method set to CV_CHAIN_APPROX_TC89_L1" ); + } + if ( method == CV_CHAIN_APPROX_TC89_KCOS ) + { + x->x_cmethod = CV_CHAIN_APPROX_TC89_KCOS; + post( "pdp_opencv_contours_convexhull : method set to CV_CHAIN_APPROX_TC89_KCOS" ); + } + if ( ( method == CV_LINK_RUNS ) && ( x->x_cmode == CV_RETR_LIST ) ) + { + x->x_cmethod = CV_LINK_RUNS; + post( "pdp_opencv_contours_convexhull : method set to CV_LINK_RUNS" ); + } +} + +static void pdp_opencv_contours_convexhull_sendpacket(t_pdp_opencv_contours_convexhull *x) +{ + /* release the packet */ + pdp_packet_mark_unused(x->x_packet0); + x->x_packet0 = -1; + + /* unregister and propagate if valid dest packet */ + pdp_packet_pass_if_valid(x->x_outlet0, &x->x_packet1); +} + +static void pdp_opencv_contours_convexhull_process(t_pdp_opencv_contours_convexhull *x) +{ + int encoding; + t_pdp *header = 0; + char *parname; + unsigned pi; + int partype; + float pardefault; + t_atom plist[2]; + t_atom tlist[2]; + t_atom vlist[2]; + + /* check if image data packets are compatible */ + if ( (header = pdp_packet_header(x->x_packet0)) + && (PDP_BITMAP == header->type)){ + + /* pdp_opencv_contours_convexhull_process inputs and write into active inlet */ + switch(pdp_packet_header(x->x_packet0)->info.image.encoding){ + + case PDP_BITMAP_RGB: + x->x_packet1 = pdp_packet_clone_rw(x->x_packet0); + pdp_queue_add(x, (void*)pdp_opencv_contours_convexhull_process_rgb, (void*)pdp_opencv_contours_convexhull_sendpacket, &x->x_queue_id); + break; + + default: + /* don't know the type, so dont pdp_opencv_contours_convexhull_process */ + break; + + } + } + +} + +static void pdp_opencv_contours_convexhull_input_0(t_pdp_opencv_contours_convexhull *x, t_symbol *s, t_floatarg f) +{ + /* if this is a register_ro message or register_rw message, register with packet factory */ + + if (s == gensym("register_rw")) + x->x_dropped = pdp_packet_convert_ro_or_drop(&x->x_packet0, (int)f, pdp_gensym((char*)"bitmap/rgb/*") ); + + if ((s == gensym("process")) && (-1 != x->x_packet0) && (!x->x_dropped)) + { + /* add the process method and callback to the process queue */ + pdp_opencv_contours_convexhull_process(x); + } +} + +static void pdp_opencv_contours_convexhull_free(t_pdp_opencv_contours_convexhull *x) +{ + int i; + + pdp_queue_finish(x->x_queue_id); + pdp_packet_mark_unused(x->x_packet0); + + //Destroy cv_images + cvReleaseImage(&x->image); + cvReleaseImage(&x->gray); + cvReleaseImage(&x->cnt_img); +} + +t_class *pdp_opencv_contours_convexhull_class; + + +void *pdp_opencv_contours_convexhull_new(t_floatarg f) +{ + int i; + + t_pdp_opencv_contours_convexhull *x = (t_pdp_opencv_contours_convexhull *)pd_new(pdp_opencv_contours_convexhull_class); + + x->x_outlet0 = outlet_new(&x->x_obj, &s_anything); + x->x_countout = outlet_new(&x->x_obj, &s_float); + x->x_dataout = outlet_new(&x->x_obj, &s_anything); + + x->x_packet0 = -1; + x->x_packet1 = -1; + x->x_queue_id = -1; + + x->x_width = 320; + x->x_height = 240; + x->x_size = x->x_width * x->x_height; + + x->x_cmode = CV_RETR_LIST; + x->x_cmethod = CV_CHAIN_APPROX_SIMPLE; + + x->x_nightmode = 0; + x->x_accuracy = 3; + + x->image = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 3); + x->gray = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 1); + x->cnt_img = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 3); + + //contours = 0; + return (void *)x; +} + + +#ifdef __cplusplus +extern "C" +{ +#endif + + +void pdp_opencv_contours_convexhull_setup(void) +{ + + post( " pdp_opencv_contours_convexhull"); + pdp_opencv_contours_convexhull_class = class_new(gensym("pdp_opencv_contours_convexhull"), (t_newmethod)pdp_opencv_contours_convexhull_new, + (t_method)pdp_opencv_contours_convexhull_free, sizeof(t_pdp_opencv_contours_convexhull), 0, A_DEFFLOAT, A_NULL); + + class_addmethod(pdp_opencv_contours_convexhull_class, (t_method)pdp_opencv_contours_convexhull_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL); + class_addmethod(pdp_opencv_contours_convexhull_class, (t_method)pdp_opencv_contours_convexhull_cmode, gensym("mode"), A_FLOAT, A_NULL ); + class_addmethod(pdp_opencv_contours_convexhull_class, (t_method)pdp_opencv_contours_convexhull_cmethod, gensym("method"), A_FLOAT, A_NULL ); + class_addmethod(pdp_opencv_contours_convexhull_class, (t_method)pdp_opencv_contours_convexhull_nightmode, gensym("nightmode"), A_FLOAT, A_NULL ); + class_addmethod(pdp_opencv_contours_convexhull_class, (t_method)pdp_opencv_contours_convexhull_accuracy, gensym("accuracy"), A_FLOAT, A_NULL ); + +} + +#ifdef __cplusplus +} +#endif diff --git a/pdp_opencv_contours_convexity.c b/pdp_opencv_contours_convexity.c deleted file mode 100644 index f9ce1cb..0000000 --- a/pdp_opencv_contours_convexity.c +++ /dev/null @@ -1,455 +0,0 @@ -/* - * Pure Data Packet module. - * Copyright (c) by Tom Schouten - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "pdp.h" - -#ifndef _EiC -#include "cv.h" -#endif - -#define w 500 - - -typedef struct pdp_opencv_contours_convexity_struct -{ - t_object x_obj; - t_float x_f; - - t_outlet *x_outlet0; - t_outlet *x_nomdef; - t_outlet *x_dataout; - int x_packet0; - int x_packet1; - int x_dropped; - int x_queue_id; - - int x_width; - int x_height; - int x_size; - - int x_infosok; - - int levels; - int area; - int minarea; - int maxarea; - int selected; - IplImage *image, *gray; - -} t_pdp_opencv_contours_convexity; - -static void pdp_opencv_contours_convexity_process_rgb(t_pdp_opencv_contours_convexity *x) -{ - t_pdp *header = pdp_packet_header(x->x_packet0); - short int *data = (short int *)pdp_packet_data(x->x_packet0); - t_pdp *newheader = pdp_packet_header(x->x_packet1); - short int *newdata = (short int *)pdp_packet_data(x->x_packet1); - - - if ((x->x_width != (t_int)header->info.image.width) || - (x->x_height != (t_int)header->info.image.height)) - { - - post("pdp_opencv_contours_convexity :: resizing plugins"); - - //cv_freeplugins(x); - - x->x_width = header->info.image.width; - x->x_height = header->info.image.height; - x->x_size = x->x_width*x->x_height; - - //Destroy cv_images - cvReleaseImage(&x->image); - cvReleaseImage(&x->gray); - - //create the orig image with new size - x->image = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 3); - - // Create the output images with new sizes - x->gray = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 1); - - } - - newheader->info.image.encoding = header->info.image.encoding; - newheader->info.image.width = x->x_width; - newheader->info.image.height = x->x_height; - - memcpy( newdata, data, x->x_size*3 ); - - // 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( x->image->imageData, data, x->x_size*3 ); - - // Convert to grayscale - cvCvtColor(x->image, x->gray, CV_BGR2GRAY); - - CvSeq* seqhull; - CvSeq* defects; - CvSeq* contours; - int* hull; - int hullsize; - CvPoint* PointArray; - CvConvexityDefect* defectArray; - CvMemStorage* stor02; - CvMemStorage* stor03; - stor02 = cvCreateMemStorage(0); - stor03 = cvCreateMemStorage(0); - - //TODO nous objectes ::: llegeixo el OpenCVRefenceManual i al capitol 11 Structural Analysis Reference - // m'en adono que - //de fet aquest objecte no s'ha de dir pdp_opencv_contours_convexity sino pdp_opencv_convexity - //el pdp_opencv_contours_convexity et donaria una llista de punts en els outles que serien els punts del contorn (poligonal o no)i - //i seria la base per a una serie de objectes basats en contorns - //el pdp_opencv_convexHull, el mateix pdp_opencv_convexity - //depres nhi ha un altre que surtiria d'aqui :: pdp_opencv_MinAreaRect i el pdp_opencv_MinEnclosingCircle - //ContourBoundingRect - // - - - // TODO afegir parametres - // Retrieval mode. - // CV_RETR_TREE || CV_RETR_CCOMP || CV_RETR_LIST || CV_RETR_EXTERNAL - // Approximation method. - // CV_CHAIN_APPROX_SIMPLE || CV_CHAIN_CODE || CV_CHAIN_APPROX_NONE || CV_CHAIN_APPROX_TC89_L1 || CV_CHAIN_APPROX_TC89_KCOS || CV_LINK_RUNS - cvFindContours( x->gray, stor02, &contours, sizeof(CvContour), CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0) ); - // TODO afegir parametres - // aqui es fa una aproximacio del contorn per a que sigui mes polinomic i no tingui tants punts - // els ultims dos parametres han de ser variables - // precision , recursive - if (contours) contours = cvApproxPoly( contours, sizeof(CvContour), stor02, CV_POLY_APPROX_DP, 3, 1 ); - - int i = 0; - - //busquem el contorn mes gran - x->area = 0; - CvSeq* first_contour; - first_contour = contours; - for( ; contours != 0; contours = contours->h_next ) - { - CvRect rect; - int count = contours->total; - rect = cvContourBoundingRect(contours, 1); - if ( (rect.width*rect.height) > x->area ) - { - x->selected = i; - x->area = rect.width*rect.height; - } - i++; - } - - //cvSeqSort(contours, sort_contour, NULL); - contours = first_contour; - - int k = 0; - for( ; contours != 0; contours = contours->h_next ) - { - int i; // Indicator of cycles. - int count = contours->total; // This is number point in contour - CvPoint center; - CvSize size; - CvRect rect; - - rect = cvContourBoundingRect( contours, 1); - if ( (k==x->selected) ) { - - - //fprintf(stderr,"malloc\n"); - // Alloc memory for contour point set. - PointArray = malloc( count*sizeof(CvPoint) ); - - // Alloc memory for indices of convex hull vertices. - hull = malloc(sizeof(int)*count); - - // Get contour point set. - //fprintf(stderr,"cvCvtSeqToArray\n"); - cvCvtSeqToArray(contours, PointArray, CV_WHOLE_SEQ); - - - // Find convex hull for curent contour. - //fprintf(stderr,"cvConvexHull\n"); - cvConvexHull( PointArray, - count, - NULL, - CV_COUNTER_CLOCKWISE, - hull, - &hullsize); - - // Find convex hull for current contour. - // This required for cvConvexityDefects(). - //fprintf(stderr,"cvConvexHull2\n"); - seqhull = cvConvexHull2( contours,0, - CV_COUNTER_CLOCKWISE, - 0); - - // This required for cvConvexityDefects(). - // Otherwise cvConvexityDefects() falled. - if( hullsize < 4 ) - continue; - - // Find defects of convexity of current contours. - //fprintf(stderr,"cvConvexityDefects\n"); - defects = cvConvexityDefects( contours, - seqhull, - stor03); - int j=0; - // This cycle marks all defects of convexity of current contours. - for(;defects;defects = defects->h_next) - { - int nomdef = defects->total; // defect amount - outlet_float( x->x_nomdef, nomdef ); - - if(nomdef == 0) - continue; - - // Alloc memory for defect set. - //fprintf(stderr,"malloc\n"); - defectArray = malloc(sizeof(CvConvexityDefect)*nomdef); - - // Get defect set. - //fprintf(stderr,"cvCvtSeqToArray\n"); - cvCvtSeqToArray(defects,defectArray, CV_WHOLE_SEQ); - - - // Draw marks for all defects. - for(i=0; iimage, *(defectArray[i].start), *(defectArray[i].depth_point),CV_RGB(0,0,255),1, CV_AA, 0 ); - cvCircle( x->image, *(defectArray[i].depth_point), 5, CV_RGB(0,255,0), -1, 8,0); - cvCircle( x->image, *(defectArray[i].start), 5, CV_RGB(0,255,0), -1, 8,0); - cvLine(x->image, *(defectArray[i].depth_point), *(defectArray[i].end),CV_RGB(0,0,255),1, CV_AA, 0 ); - t_atom rlist[7]; - SETFLOAT(&rlist[0], i); - SETFLOAT(&rlist[1], defectArray[i].start->x); - SETFLOAT(&rlist[2], defectArray[i].start->y); - SETFLOAT(&rlist[3], defectArray[i].depth_point->x); - SETFLOAT(&rlist[4], defectArray[i].depth_point->y); - SETFLOAT(&rlist[5], defectArray[i].end->x); - SETFLOAT(&rlist[6], defectArray[i].end->y); - outlet_list( x->x_dataout, 0, 7, rlist ); - } - - j++; - - // Free memory. - free(defectArray); - } - - // Draw current contour. - //cvDrawContours(x->cnt_img,contours,CV_RGB(255,255,255),CV_RGB(255,255,255),0,1, 8); - cvDrawContours( x->image, contours, CV_RGB(255,0,0), CV_RGB(0,255,0), x->levels, 2, CV_AA, cvPoint(0,0) ); - - // Draw convex hull for current contour. - for(i=0; iimage, PointArray[hull[i]], - PointArray[hull[i+1]],CV_RGB(255,255,255),1, CV_AA, 0 ); - } - cvLine(x->image, PointArray[hull[hullsize-1]], - PointArray[hull[0]],CV_RGB(255,255,255),1, CV_AA, 0 ); - - - // Free memory. - free(PointArray); - free(hull); - /* replace CV_FILLED with 1 to see the outlines */ - //cvDrawContours( x->cnt_img, contours, CV_RGB(255,0,0), CV_RGB(0,255,0), x->levels, 3, CV_AA, cvPoint(0,0) ); - //cvConvexityDefects( contours, cvConvexHull2( contours, 0, CV_CLOCKWISE, 0 ), stor022 ); - } - k++; - } - - cvReleaseMemStorage( &stor03 ); - cvReleaseMemStorage( &stor02 ); - //if (defects) cvClearSeq(defects); - //if (seqhull) cvClearSeq(seqhull); - - - memcpy( newdata, x->image->imageData, x->x_size*3 ); - - - return; -} - -static void pdp_opencv_contours_convexity_param(t_pdp_opencv_contours_convexity *x, t_floatarg f1, t_floatarg f2) -{ - -} - -static void pdp_opencv_contours_convexity_minarea(t_pdp_opencv_contours_convexity *x, t_floatarg f) -{ - if (f>0) x->minarea = (int)f; -} - -static void pdp_opencv_contours_convexity_maxarea(t_pdp_opencv_contours_convexity *x, t_floatarg f) -{ - if (f>0) x->maxarea = (int)f; -} - -static void pdp_opencv_contours_convexity_levels(t_pdp_opencv_contours_convexity *x, t_floatarg f) -{ - //x->levels = (int)f; -} - -static void pdp_opencv_contours_convexity_sendpacket(t_pdp_opencv_contours_convexity *x) -{ - /* release the packet */ - pdp_packet_mark_unused(x->x_packet0); - x->x_packet0 = -1; - - /* unregister and propagate if valid dest packet */ - pdp_packet_pass_if_valid(x->x_outlet0, &x->x_packet1); -} - -static void pdp_opencv_contours_convexity_process(t_pdp_opencv_contours_convexity *x) -{ - int encoding; - t_pdp *header = 0; - char *parname; - unsigned pi; - int partype; - float pardefault; - t_atom plist[2]; - t_atom tlist[2]; - t_atom vlist[2]; - - /* check if image data packets are compatible */ - if ( (header = pdp_packet_header(x->x_packet0)) - && (PDP_BITMAP == header->type)){ - - /* pdp_opencv_contours_convexity_process inputs and write into active inlet */ - switch(pdp_packet_header(x->x_packet0)->info.image.encoding){ - - case PDP_BITMAP_RGB: - x->x_packet1 = pdp_packet_clone_rw(x->x_packet0); - pdp_queue_add(x, pdp_opencv_contours_convexity_process_rgb, pdp_opencv_contours_convexity_sendpacket, &x->x_queue_id); - break; - - default: - /* don't know the type, so dont pdp_opencv_contours_convexity_process */ - break; - - } - } - -} - -static void pdp_opencv_contours_convexity_input_0(t_pdp_opencv_contours_convexity *x, t_symbol *s, t_floatarg f) -{ - /* if this is a register_ro message or register_rw message, register with packet factory */ - - if (s == gensym("register_rw")) - x->x_dropped = pdp_packet_convert_ro_or_drop(&x->x_packet0, (int)f, pdp_gensym("bitmap/rgb/*") ); - - if ((s == gensym("process")) && (-1 != x->x_packet0) && (!x->x_dropped)) - { - /* add the process method and callback to the process queue */ - pdp_opencv_contours_convexity_process(x); - } -} - -static void pdp_opencv_contours_convexity_free(t_pdp_opencv_contours_convexity *x) -{ - int i; - - pdp_queue_finish(x->x_queue_id); - pdp_packet_mark_unused(x->x_packet0); - //cv_freeplugins(x); - - //Destroy cv_images - cvReleaseImage(&x->image); - cvReleaseImage(&x->gray); -} - -t_class *pdp_opencv_contours_convexity_class; - - -void *pdp_opencv_contours_convexity_new(t_floatarg f) -{ - int i; - - t_pdp_opencv_contours_convexity *x = (t_pdp_opencv_contours_convexity *)pd_new(pdp_opencv_contours_convexity_class); - //inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("minarea")); - //inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("maxarea")); - - x->x_outlet0 = outlet_new(&x->x_obj, &s_anything); - x->x_nomdef = outlet_new(&x->x_obj, &s_float); - x->x_dataout = outlet_new(&x->x_obj, &s_anything); - - x->x_packet0 = -1; - x->x_packet1 = -1; - x->x_queue_id = -1; - - x->x_width = 320; - x->x_height = 240; - x->x_size = x->x_width * x->x_height; - - //load the plugins - x->x_infosok = 0; - //cv_loadplugins(x, FF_PLUGIN_DIR); - - //pdp_opencv_contours_convexity_plugin(x, f); - x->levels = 1; - x->area = 1; - x->minarea = 1; - x->maxarea = 76800; - x->selected = 0; - - - - - x->image = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 3); - x->gray = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 1); - - //contours = 0; - return (void *)x; -} - - -#ifdef __cplusplus -extern "C" -{ -#endif - - -void pdp_opencv_contours_convexity_setup(void) -{ - - post( " pdp_opencv_contours_convexity"); - pdp_opencv_contours_convexity_class = class_new(gensym("pdp_opencv_contours_convexity"), (t_newmethod)pdp_opencv_contours_convexity_new, - (t_method)pdp_opencv_contours_convexity_free, sizeof(t_pdp_opencv_contours_convexity), 0, A_DEFFLOAT, A_NULL); - - class_addmethod(pdp_opencv_contours_convexity_class, (t_method)pdp_opencv_contours_convexity_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL); - //class_addmethod(pdp_opencv_contours_convexity_class, (t_method)pdp_opencv_contours_convexity_levels, gensym("levels"), A_FLOAT, A_NULL ); - //class_addmethod(pdp_opencv_contours_convexity_class, (t_method)pdp_opencv_contours_convexity_minarea, gensym("minarea"), A_FLOAT, A_NULL ); - //class_addmethod(pdp_opencv_contours_convexity_class, (t_method)pdp_opencv_contours_convexity_maxarea, gensym("maxarea"), A_FLOAT, A_NULL ); - - -} - -#ifdef __cplusplus -} -#endif diff --git a/pdp_opencv_contours_convexity.cc b/pdp_opencv_contours_convexity.cc new file mode 100755 index 0000000..58ee306 --- /dev/null +++ b/pdp_opencv_contours_convexity.cc @@ -0,0 +1,455 @@ +/* + * Pure Data Packet module. + * Copyright (c) by Tom Schouten + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "pdp.h" + +#ifndef _EiC +#include "cv.h" +#endif + +#define w 500 + + +typedef struct pdp_opencv_contours_convexity_struct +{ + t_object x_obj; + t_float x_f; + + t_outlet *x_outlet0; + t_outlet *x_nomdef; + t_outlet *x_dataout; + int x_packet0; + int x_packet1; + int x_dropped; + int x_queue_id; + + int x_width; + int x_height; + int x_size; + + int x_infosok; + + int levels; + int area; + int minarea; + int maxarea; + int selected; + IplImage *image, *gray; + +} t_pdp_opencv_contours_convexity; + +static void pdp_opencv_contours_convexity_process_rgb(t_pdp_opencv_contours_convexity *x) +{ + t_pdp *header = pdp_packet_header(x->x_packet0); + short int *data = (short int *)pdp_packet_data(x->x_packet0); + t_pdp *newheader = pdp_packet_header(x->x_packet1); + short int *newdata = (short int *)pdp_packet_data(x->x_packet1); + + + if ((x->x_width != (t_int)header->info.image.width) || + (x->x_height != (t_int)header->info.image.height)) + { + + post("pdp_opencv_contours_convexity :: resizing plugins"); + + //cv_freeplugins(x); + + x->x_width = header->info.image.width; + x->x_height = header->info.image.height; + x->x_size = x->x_width*x->x_height; + + //Destroy cv_images + cvReleaseImage(&x->image); + cvReleaseImage(&x->gray); + + //create the orig image with new size + x->image = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 3); + + // Create the output images with new sizes + x->gray = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 1); + + } + + newheader->info.image.encoding = header->info.image.encoding; + newheader->info.image.width = x->x_width; + newheader->info.image.height = x->x_height; + + memcpy( newdata, data, x->x_size*3 ); + + // 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( x->image->imageData, data, x->x_size*3 ); + + // Convert to grayscale + cvCvtColor(x->image, x->gray, CV_BGR2GRAY); + + CvSeq* seqhull; + CvSeq* defects; + CvSeq* contours; + int* hull; + int hullsize; + CvPoint* PointArray; + CvConvexityDefect* defectArray; + CvMemStorage* stor02; + CvMemStorage* stor03; + stor02 = cvCreateMemStorage(0); + stor03 = cvCreateMemStorage(0); + + //TODO nous objectes ::: llegeixo el OpenCVRefenceManual i al capitol 11 Structural Analysis Reference + // m'en adono que + //de fet aquest objecte no s'ha de dir pdp_opencv_contours_convexity sino pdp_opencv_convexity + //el pdp_opencv_contours_convexity et donaria una llista de punts en els outles que serien els punts del contorn (poligonal o no)i + //i seria la base per a una serie de objectes basats en contorns + //el pdp_opencv_convexHull, el mateix pdp_opencv_convexity + //depres nhi ha un altre que surtiria d'aqui :: pdp_opencv_MinAreaRect i el pdp_opencv_MinEnclosingCircle + //ContourBoundingRect + // + + + // TODO afegir parametres + // Retrieval mode. + // CV_RETR_TREE || CV_RETR_CCOMP || CV_RETR_LIST || CV_RETR_EXTERNAL + // Approximation method. + // CV_CHAIN_APPROX_SIMPLE || CV_CHAIN_CODE || CV_CHAIN_APPROX_NONE || CV_CHAIN_APPROX_TC89_L1 || CV_CHAIN_APPROX_TC89_KCOS || CV_LINK_RUNS + cvFindContours( x->gray, stor02, &contours, sizeof(CvContour), CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0) ); + // TODO afegir parametres + // aqui es fa una aproximacio del contorn per a que sigui mes polinomic i no tingui tants punts + // els ultims dos parametres han de ser variables + // precision , recursive + if (contours) contours = cvApproxPoly( contours, sizeof(CvContour), stor02, CV_POLY_APPROX_DP, 3, 1 ); + + int i = 0; + + //busquem el contorn mes gran + x->area = 0; + CvSeq* first_contour; + first_contour = contours; + for( ; contours != 0; contours = contours->h_next ) + { + CvRect rect; + int count = contours->total; + rect = cvContourBoundingRect(contours, 1); + if ( (rect.width*rect.height) > x->area ) + { + x->selected = i; + x->area = rect.width*rect.height; + } + i++; + } + + //cvSeqSort(contours, sort_contour, NULL); + contours = first_contour; + + int k = 0; + for( ; contours != 0; contours = contours->h_next ) + { + int i; // Indicator of cycles. + int count = contours->total; // This is number point in contour + CvPoint center; + CvSize size; + CvRect rect; + + rect = cvContourBoundingRect( contours, 1); + if ( (k==x->selected) ) { + + + //fprintf(stderr,"malloc\n"); + // Alloc memory for contour point set. + PointArray = (CvPoint*)malloc( count*sizeof(CvPoint) ); + + // Alloc memory for indices of convex hull vertices. + hull = (int*)malloc(sizeof(int)*count); + + // Get contour point set. + //fprintf(stderr,"cvCvtSeqToArray\n"); + cvCvtSeqToArray(contours, PointArray, CV_WHOLE_SEQ); + + + // Find convex hull for curent contour. + //fprintf(stderr,"cvConvexHull\n"); + cvConvexHull( PointArray, + count, + NULL, + CV_COUNTER_CLOCKWISE, + hull, + &hullsize); + + // Find convex hull for current contour. + // This required for cvConvexityDefects(). + //fprintf(stderr,"cvConvexHull2\n"); + seqhull = cvConvexHull2( contours,0, + CV_COUNTER_CLOCKWISE, + 0); + + // This required for cvConvexityDefects(). + // Otherwise cvConvexityDefects() falled. + if( hullsize < 4 ) + continue; + + // Find defects of convexity of current contours. + //fprintf(stderr,"cvConvexityDefects\n"); + defects = cvConvexityDefects( contours, + seqhull, + stor03); + int j=0; + // This cycle marks all defects of convexity of current contours. + for(;defects;defects = defects->h_next) + { + int nomdef = defects->total; // defect amount + outlet_float( x->x_nomdef, nomdef ); + + if(nomdef == 0) + continue; + + // Alloc memory for defect set. + //fprintf(stderr,"malloc\n"); + defectArray = (CvConvexityDefect*)malloc(sizeof(CvConvexityDefect)*nomdef); + + // Get defect set. + //fprintf(stderr,"cvCvtSeqToArray\n"); + cvCvtSeqToArray(defects,defectArray, CV_WHOLE_SEQ); + + + // Draw marks for all defects. + for(i=0; iimage, *(defectArray[i].start), *(defectArray[i].depth_point),CV_RGB(0,0,255),1, CV_AA, 0 ); + cvCircle( x->image, *(defectArray[i].depth_point), 5, CV_RGB(0,255,0), -1, 8,0); + cvCircle( x->image, *(defectArray[i].start), 5, CV_RGB(0,255,0), -1, 8,0); + cvLine(x->image, *(defectArray[i].depth_point), *(defectArray[i].end),CV_RGB(0,0,255),1, CV_AA, 0 ); + t_atom rlist[7]; + SETFLOAT(&rlist[0], i); + SETFLOAT(&rlist[1], defectArray[i].start->x); + SETFLOAT(&rlist[2], defectArray[i].start->y); + SETFLOAT(&rlist[3], defectArray[i].depth_point->x); + SETFLOAT(&rlist[4], defectArray[i].depth_point->y); + SETFLOAT(&rlist[5], defectArray[i].end->x); + SETFLOAT(&rlist[6], defectArray[i].end->y); + outlet_list( x->x_dataout, 0, 7, rlist ); + } + + j++; + + // Free memory. + free(defectArray); + } + + // Draw current contour. + //cvDrawContours(x->cnt_img,contours,CV_RGB(255,255,255),CV_RGB(255,255,255),0,1, 8); + cvDrawContours( x->image, contours, CV_RGB(255,0,0), CV_RGB(0,255,0), x->levels, 2, CV_AA, cvPoint(0,0) ); + + // Draw convex hull for current contour. + for(i=0; iimage, PointArray[hull[i]], + PointArray[hull[i+1]],CV_RGB(255,255,255),1, CV_AA, 0 ); + } + cvLine(x->image, PointArray[hull[hullsize-1]], + PointArray[hull[0]],CV_RGB(255,255,255),1, CV_AA, 0 ); + + + // Free memory. + free(PointArray); + free(hull); + /* replace CV_FILLED with 1 to see the outlines */ + //cvDrawContours( x->cnt_img, contours, CV_RGB(255,0,0), CV_RGB(0,255,0), x->levels, 3, CV_AA, cvPoint(0,0) ); + //cvConvexityDefects( contours, cvConvexHull2( contours, 0, CV_CLOCKWISE, 0 ), stor022 ); + } + k++; + } + + cvReleaseMemStorage( &stor03 ); + cvReleaseMemStorage( &stor02 ); + //if (defects) cvClearSeq(defects); + //if (seqhull) cvClearSeq(seqhull); + + + memcpy( newdata, x->image->imageData, x->x_size*3 ); + + + return; +} + +static void pdp_opencv_contours_convexity_param(t_pdp_opencv_contours_convexity *x, t_floatarg f1, t_floatarg f2) +{ + +} + +static void pdp_opencv_contours_convexity_minarea(t_pdp_opencv_contours_convexity *x, t_floatarg f) +{ + if (f>0) x->minarea = (int)f; +} + +static void pdp_opencv_contours_convexity_maxarea(t_pdp_opencv_contours_convexity *x, t_floatarg f) +{ + if (f>0) x->maxarea = (int)f; +} + +static void pdp_opencv_contours_convexity_levels(t_pdp_opencv_contours_convexity *x, t_floatarg f) +{ + //x->levels = (int)f; +} + +static void pdp_opencv_contours_convexity_sendpacket(t_pdp_opencv_contours_convexity *x) +{ + /* release the packet */ + pdp_packet_mark_unused(x->x_packet0); + x->x_packet0 = -1; + + /* unregister and propagate if valid dest packet */ + pdp_packet_pass_if_valid(x->x_outlet0, &x->x_packet1); +} + +static void pdp_opencv_contours_convexity_process(t_pdp_opencv_contours_convexity *x) +{ + int encoding; + t_pdp *header = 0; + char *parname; + unsigned pi; + int partype; + float pardefault; + t_atom plist[2]; + t_atom tlist[2]; + t_atom vlist[2]; + + /* check if image data packets are compatible */ + if ( (header = pdp_packet_header(x->x_packet0)) + && (PDP_BITMAP == header->type)){ + + /* pdp_opencv_contours_convexity_process inputs and write into active inlet */ + switch(pdp_packet_header(x->x_packet0)->info.image.encoding){ + + case PDP_BITMAP_RGB: + x->x_packet1 = pdp_packet_clone_rw(x->x_packet0); + pdp_queue_add(x, (void*)pdp_opencv_contours_convexity_process_rgb, (void*)pdp_opencv_contours_convexity_sendpacket, &x->x_queue_id); + break; + + default: + /* don't know the type, so dont pdp_opencv_contours_convexity_process */ + break; + + } + } + +} + +static void pdp_opencv_contours_convexity_input_0(t_pdp_opencv_contours_convexity *x, t_symbol *s, t_floatarg f) +{ + /* if this is a register_ro message or register_rw message, register with packet factory */ + + if (s == gensym("register_rw")) + x->x_dropped = pdp_packet_convert_ro_or_drop(&x->x_packet0, (int)f, pdp_gensym((char*)"bitmap/rgb/*") ); + + if ((s == gensym("process")) && (-1 != x->x_packet0) && (!x->x_dropped)) + { + /* add the process method and callback to the process queue */ + pdp_opencv_contours_convexity_process(x); + } +} + +static void pdp_opencv_contours_convexity_free(t_pdp_opencv_contours_convexity *x) +{ + int i; + + pdp_queue_finish(x->x_queue_id); + pdp_packet_mark_unused(x->x_packet0); + //cv_freeplugins(x); + + //Destroy cv_images + cvReleaseImage(&x->image); + cvReleaseImage(&x->gray); +} + +t_class *pdp_opencv_contours_convexity_class; + + +void *pdp_opencv_contours_convexity_new(t_floatarg f) +{ + int i; + + t_pdp_opencv_contours_convexity *x = (t_pdp_opencv_contours_convexity *)pd_new(pdp_opencv_contours_convexity_class); + //inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("minarea")); + //inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("maxarea")); + + x->x_outlet0 = outlet_new(&x->x_obj, &s_anything); + x->x_nomdef = outlet_new(&x->x_obj, &s_float); + x->x_dataout = outlet_new(&x->x_obj, &s_anything); + + x->x_packet0 = -1; + x->x_packet1 = -1; + x->x_queue_id = -1; + + x->x_width = 320; + x->x_height = 240; + x->x_size = x->x_width * x->x_height; + + //load the plugins + x->x_infosok = 0; + //cv_loadplugins(x, FF_PLUGIN_DIR); + + //pdp_opencv_contours_convexity_plugin(x, f); + x->levels = 1; + x->area = 1; + x->minarea = 1; + x->maxarea = 76800; + x->selected = 0; + + + + + x->image = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 3); + x->gray = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 1); + + //contours = 0; + return (void *)x; +} + + +#ifdef __cplusplus +extern "C" +{ +#endif + + +void pdp_opencv_contours_convexity_setup(void) +{ + + post( " pdp_opencv_contours_convexity"); + pdp_opencv_contours_convexity_class = class_new(gensym("pdp_opencv_contours_convexity"), (t_newmethod)pdp_opencv_contours_convexity_new, + (t_method)pdp_opencv_contours_convexity_free, sizeof(t_pdp_opencv_contours_convexity), 0, A_DEFFLOAT, A_NULL); + + class_addmethod(pdp_opencv_contours_convexity_class, (t_method)pdp_opencv_contours_convexity_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL); + //class_addmethod(pdp_opencv_contours_convexity_class, (t_method)pdp_opencv_contours_convexity_levels, gensym("levels"), A_FLOAT, A_NULL ); + //class_addmethod(pdp_opencv_contours_convexity_class, (t_method)pdp_opencv_contours_convexity_minarea, gensym("minarea"), A_FLOAT, A_NULL ); + //class_addmethod(pdp_opencv_contours_convexity_class, (t_method)pdp_opencv_contours_convexity_maxarea, gensym("maxarea"), A_FLOAT, A_NULL ); + + +} + +#ifdef __cplusplus +} +#endif diff --git a/pdp_opencv_dft.c b/pdp_opencv_dft.c deleted file mode 100755 index 4cfac5f..0000000 --- a/pdp_opencv_dft.c +++ /dev/null @@ -1,397 +0,0 @@ -/* - * Pure Data Packet module. - * Copyright (c) by Tom Schouten - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include -#include -#include -#include -#include -#include - -#include "pdp.h" - -#ifndef _EiC -#include "cv.h" -#endif - -typedef struct pdp_opencv_dft_struct -{ - t_object x_obj; - t_float x_f; - - t_outlet *x_outlet0; - t_outlet *x_outlet1; - int x_packet0; - int x_packet1; - int x_packet2; - int x_dropped; - int x_queue_id; - - int x_width; - int x_height; - int x_size; - int x_calculate; - int dft_M; - int dft_N; - - // The output and temporary images - IplImage *image; - IplImage *gray; - IplImage *input_re; - IplImage *input_im; - IplImage *input_co; - CvMat *dft_A; - IplImage *image_re; - IplImage *image_im; - IplImage *image_mout; - IplImage *image_pout; - -} t_pdp_opencv_dft; - -// rearrange the quadrants of Fourier image so that the origin is at -// the image center - -void pdp_opencv_dft_shift_dft(CvArr * src_arr, CvArr * dst_arr ) -{ - CvMat *tmp=NULL; - CvMat q1stub, q2stub; - CvMat q3stub, q4stub; - CvMat d1stub, d2stub; - CvMat d3stub, d4stub; - CvMat * q1, * q2, * q3, * q4; - CvMat * d1, * d2, * d3, * d4; - - CvSize size = cvGetSize(src_arr); - CvSize dst_size = cvGetSize(dst_arr); - int cx, cy; - - if(dst_size.width != size.width || - dst_size.height != size.height){ - error( "pdp_opencv_dft : source and destination arrays must have the same size" ); - } - - if(src_arr==dst_arr){ - tmp = cvCreateMat(size.height/2, size.width/2, cvGetElemType(src_arr)); - } - - cx = size.width/2; - cy = size.height/2; // image center - - q1 = cvGetSubRect( src_arr, &q1stub, cvRect(0,0,cx, cy) ); - q2 = cvGetSubRect( src_arr, &q2stub, cvRect(cx,0,cx,cy) ); - q3 = cvGetSubRect( src_arr, &q3stub, cvRect(cx,cy,cx,cy) ); - q4 = cvGetSubRect( src_arr, &q4stub, cvRect(0,cy,cx,cy) ); - d1 = cvGetSubRect( src_arr, &d1stub, cvRect(0,0,cx,cy) ); - d2 = cvGetSubRect( src_arr, &d2stub, cvRect(cx,0,cx,cy) ); - d3 = cvGetSubRect( src_arr, &d3stub, cvRect(cx,cy,cx,cy) ); - d4 = cvGetSubRect( src_arr, &d4stub, cvRect(0,cy,cx,cy) ); - - if(src_arr!=dst_arr){ - if( !CV_ARE_TYPES_EQ( q1, d1 )){ - error( "pdp_opencv_dft : source and destination arrays must have the same format" ); - } - cvCopy(q3, d1, 0); - cvCopy(q4, d2, 0); - cvCopy(q1, d3, 0); - cvCopy(q2, d4, 0); - } - else{ - cvCopy(q3, tmp, 0); - cvCopy(q1, q3, 0); - cvCopy(tmp, q1, 0); - cvCopy(q4, tmp, 0); - cvCopy(q2, q4, 0); - cvCopy(tmp, q2, 0); - } - if(src_arr==dst_arr){ - cvReleaseMat( &tmp ); - } -} - -static void pdp_opencv_dft_process_rgb(t_pdp_opencv_dft *x) -{ - t_pdp *header = pdp_packet_header(x->x_packet0); - short int *data = (short int *)pdp_packet_data(x->x_packet0); - t_pdp *newheader = pdp_packet_header(x->x_packet1); - short int *newdata = (short int *)pdp_packet_data(x->x_packet1); - t_pdp *phaseheader = pdp_packet_header(x->x_packet2); - short int *phasedata = (short int *)pdp_packet_data(x->x_packet2); - CvMat tmp; - double m,M; - int px,py; - - if ((x->x_width != (t_int)header->info.image.width) || - (x->x_height != (t_int)header->info.image.height)) - { - post("pdp_opencv_dft :: resizing"); - - x->x_width = header->info.image.width; - x->x_height = header->info.image.height; - x->x_size = x->x_width*x->x_height; - - //Destroy cv_images - cvReleaseImage( &x->image ); - //cvReleaseImage( &x->gray ); - cvReleaseImage( &x->input_re ); - cvReleaseImage( &x->input_im ); - cvReleaseImage( &x->input_co ); - cvReleaseMat( &x->dft_A ); - //cvReleaseImage( &x->image_re ); - //cvReleaseImage( &x->image_im ); - //cvReleaseImage( &x->image_mout ); - //cvReleaseImage( &x->image_pout ); - - x->image = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 3); - x->gray = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 1); - x->input_re = cvCreateImage( cvGetSize(x->image), IPL_DEPTH_64F, 1); - x->input_im = cvCreateImage( cvGetSize(x->image), IPL_DEPTH_64F, 1); - x->input_co = cvCreateImage( cvGetSize(x->image), IPL_DEPTH_64F, 2); - x->dft_M = cvGetOptimalDFTSize( x->gray->height - 1 ); - x->dft_N = cvGetOptimalDFTSize( x->gray->width - 1 ); - x->dft_A = cvCreateMat( x->dft_M, x->dft_N, CV_64FC2 ); - x->image_re = cvCreateImage( cvSize(x->dft_N, x->dft_M), IPL_DEPTH_64F, 1); - x->image_im = cvCreateImage( cvSize(x->dft_N, x->dft_M), IPL_DEPTH_64F, 1); - x->image_mout = cvCreateImage( cvSize(x->image->width, x->image->height), IPL_DEPTH_8U, 1); - x->image_pout = cvCreateImage( cvSize(x->image->width, x->image->height), IPL_DEPTH_8U, 1); - } - - newheader->info.image.encoding = PDP_BITMAP_GREY; - newheader->info.image.width = x->x_width; - newheader->info.image.height = x->x_height; - - memcpy( x->image->imageData, data, x->x_size*3 ); - cvCvtColor(x->image, x->gray, CV_BGR2GRAY); - - if ( x->x_calculate ) - { - // discrete fourier transform - cvScale(x->gray, x->input_re, 1.0, 0.0); - cvZero(x->input_im); - cvMerge(x->input_re, x->input_im, NULL, NULL, x->input_co); - - // copy A to dft_A and pad dft_A with zeros - cvGetSubRect( x->dft_A, &tmp, cvRect(0,0, x->gray->width, x->gray->height)); - cvCopy( x->input_co, &tmp, NULL ); - if( x->dft_A->cols > x->gray->width ) - { - cvGetSubRect( x->dft_A, &tmp, cvRect(x->gray->width,0, x->dft_A->cols - x->gray->width, x->gray->height)); - cvZero( &tmp ); - } - - // no need to pad bottom part of dft_A with zeros because of - // use nonzero_rows parameter in cvDFT() call below - cvDFT( x->dft_A, x->dft_A, CV_DXT_FORWARD, x->input_co->height ); - - // Split Fourier in real and imaginary parts - cvSplit( x->dft_A, x->image_re, x->image_im, 0, 0 ); - - // calculate phase - for( py=0; pyimage_re->height; py++ ) { - double* ptrr = (double*) ( x->image_re->imageData + py * x->image_re->widthStep); - double* ptri = (double*) ( x->image_im->imageData + py * x->image_im->widthStep); - float* ptrp = (float*) ( x->image_pout->imageData + py * x->image_pout->widthStep); - for( px=0; pximage_re->width; px++ ) { - (*(ptrp+px)) = cvFastArctan( (float)*(ptri+px), (float)*(ptrr+px) ); - } - } - - // Compute the magnitude of the spectrum Mag = sqrt(Re^2 + Im^2) - cvPow( x->image_re, x->image_re, 2.0); - cvPow( x->image_im, x->image_im, 2.0); - cvAdd( x->image_re, x->image_im, x->image_re, NULL); - cvPow( x->image_re, x->image_re, 0.5 ); - - // Compute log(1 + Mag) - cvAddS( x->image_re, cvScalarAll(1.0), x->image_re, NULL ); // 1 + Mag - cvLog( x->image_re, x->image_re ); // log(1 + Mag) - - // Rearrange the quadrants of Fourier image so that the origin is at - // the image center - pdp_opencv_dft_shift_dft( x->image_re, x->image_re ); - - // normalize image - cvMinMaxLoc(x->image_re, &m, &M, NULL, NULL, NULL); - cvScale(x->image_re, x->image_re, 255.0/(M-m), 255.0*(-m)/(M-m)); - - for( py=0; pyimage_re->height; py++ ) { - double* ptri = (double*) ( x->image_re->imageData + py * x->image_re->widthStep); - unsigned char* ptrp = (unsigned char*) ( x->image_mout->imageData + py * x->image_mout->widthStep); - for( px=0; pximage_re->width; px++ ) { - if ( *(ptrp+px) > 255.0 ) post( "pdp_opencv_dft : error value over 255" ); - (*(ptrp+px)) = (unsigned char)( (*(ptri+px)) ); - } - } - - x->x_calculate=0; - } - - cvCvtColor(x->image_mout, x->image, CV_GRAY2RGB); - memcpy( newdata, x->image->imageData, x->x_size*3 ); - cvCvtColor(x->image_pout, x->image, CV_GRAY2RGB); - memcpy( phasedata, x->image->imageData, x->x_size*3 ); - - return; -} - -static void pdp_opencv_dft_sendpacket(t_pdp_opencv_dft *x) -{ - /* release the packet */ - pdp_packet_mark_unused(x->x_packet0); - x->x_packet0 = -1; - - /* unregister and propagate if valid dest packet */ - pdp_packet_pass_if_valid(x->x_outlet0, &x->x_packet1); - - /* unregister and propagate if valid dest packet */ - pdp_packet_pass_if_valid(x->x_outlet1, &x->x_packet2); - - pdp_packet_mark_unused(x->x_packet1); - pdp_packet_mark_unused(x->x_packet2); -} - -static void pdp_opencv_dft_process(t_pdp_opencv_dft *x) -{ - int encoding; - t_pdp *header = 0; - - /* check if image data packets are compatible */ - if ( (header = pdp_packet_header(x->x_packet0)) - && (PDP_BITMAP == header->type)){ - - /* pdp_opencv_dft_process inputs and write into active inlet */ - switch(pdp_packet_header(x->x_packet0)->info.image.encoding){ - - case PDP_BITMAP_RGB: - x->x_packet1 = pdp_packet_clone_rw(x->x_packet0); - x->x_packet2 = pdp_packet_clone_rw(x->x_packet0); - pdp_queue_add(x, pdp_opencv_dft_process_rgb, pdp_opencv_dft_sendpacket, &x->x_queue_id); - break; - - default: - /* don't know the type, so dont pdp_opencv_dft_process */ - break; - - } - } - -} - -static void pdp_opencv_dft_calculate(t_pdp_opencv_dft *x) -{ - x->x_calculate=1; -} - -static void pdp_opencv_dft_input_0(t_pdp_opencv_dft *x, t_symbol *s, t_floatarg f) -{ - /* if this is a register_ro message or register_rw message, register with packet factory */ - - if (s == gensym("register_rw")) - x->x_dropped = pdp_packet_convert_ro_or_drop(&x->x_packet0, (int)f, pdp_gensym("bitmap/rgb/*") ); - - if ((s == gensym("process")) && (-1 != x->x_packet0) && (!x->x_dropped)) - { - /* add the process method and callback to the process queue */ - pdp_opencv_dft_process(x); - } -} - -static void pdp_opencv_dft_free(t_pdp_opencv_dft *x) -{ - int i; - - //destroy cv structures - cvReleaseImage( &x->image ); - //cvReleaseImage( &x->gray ); - cvReleaseImage( &x->input_re ); - cvReleaseImage( &x->input_im ); - cvReleaseImage( &x->input_co ); - cvReleaseMat( &x->dft_A ); - //cvReleaseImage( &x->image_re ); - //cvReleaseImage( &x->image_im ); - //cvReleaseImage( &x->image_mout ); - //cvReleaseImage( &x->image_pout ); - - pdp_queue_finish(x->x_queue_id); - pdp_packet_mark_unused(x->x_packet0); - -} - -t_class *pdp_opencv_dft_class; - - -void *pdp_opencv_dft_new(t_floatarg f) -{ - int i; - - t_pdp_opencv_dft *x = (t_pdp_opencv_dft *)pd_new(pdp_opencv_dft_class); - - x->x_outlet0 = outlet_new(&x->x_obj, &s_anything); - x->x_outlet1 = outlet_new(&x->x_obj, &s_anything); - - x->x_packet0 = -1; - x->x_packet1 = -1; - x->x_packet2 = -1; - x->x_queue_id = -1; - - x->x_width = 320; - x->x_height = 240; - x->x_size = x->x_width * x->x_height; - - x->image = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 3); - x->gray = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 1); - x->input_re = cvCreateImage( cvGetSize(x->image), IPL_DEPTH_64F, 1); - x->input_im = cvCreateImage( cvGetSize(x->image), IPL_DEPTH_64F, 1); - x->input_co = cvCreateImage( cvGetSize(x->image), IPL_DEPTH_64F, 2); - x->dft_M = cvGetOptimalDFTSize( x->gray->height - 1 ); - x->dft_N = cvGetOptimalDFTSize( x->gray->width - 1 ); - x->dft_A = cvCreateMat( x->dft_M, x->dft_N, CV_64FC2 ); - x->image_re = cvCreateImage( cvSize(x->dft_N, x->dft_M), IPL_DEPTH_64F, 1); - x->image_im = cvCreateImage( cvSize(x->dft_N, x->dft_M), IPL_DEPTH_64F, 1); - x->image_mout = cvCreateImage( cvSize(x->dft_N, x->dft_M), IPL_DEPTH_8U, 1); - x->image_pout = cvCreateImage( cvSize(x->dft_N, x->dft_M), IPL_DEPTH_8U, 1); - - // calculate first dft - x->x_calculate=1; - - return (void *)x; -} - - -#ifdef __cplusplus -extern "C" -{ -#endif - - -void pdp_opencv_dft_setup(void) -{ - - post( " pdp_opencv_dft"); - pdp_opencv_dft_class = class_new(gensym("pdp_opencv_dft"), (t_newmethod)pdp_opencv_dft_new, - (t_method)pdp_opencv_dft_free, sizeof(t_pdp_opencv_dft), 0, A_DEFFLOAT, A_NULL); - - class_addmethod(pdp_opencv_dft_class, (t_method)pdp_opencv_dft_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL); - class_addmethod(pdp_opencv_dft_class, (t_method)pdp_opencv_dft_calculate, gensym("bang"), A_NULL); - -} - -#ifdef __cplusplus -} -#endif diff --git a/pdp_opencv_dft.cc b/pdp_opencv_dft.cc new file mode 100755 index 0000000..e9f72b2 --- /dev/null +++ b/pdp_opencv_dft.cc @@ -0,0 +1,397 @@ +/* + * Pure Data Packet module. + * Copyright (c) by Tom Schouten + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include + +#include "pdp.h" + +#ifndef _EiC +#include "cv.h" +#endif + +typedef struct pdp_opencv_dft_struct +{ + t_object x_obj; + t_float x_f; + + t_outlet *x_outlet0; + t_outlet *x_outlet1; + int x_packet0; + int x_packet1; + int x_packet2; + int x_dropped; + int x_queue_id; + + int x_width; + int x_height; + int x_size; + int x_calculate; + int dft_M; + int dft_N; + + // The output and temporary images + IplImage *image; + IplImage *gray; + IplImage *input_re; + IplImage *input_im; + IplImage *input_co; + CvMat *dft_A; + IplImage *image_re; + IplImage *image_im; + IplImage *image_mout; + IplImage *image_pout; + +} t_pdp_opencv_dft; + +// rearrange the quadrants of Fourier image so that the origin is at +// the image center + +void pdp_opencv_dft_shift_dft(CvArr * src_arr, CvArr * dst_arr ) +{ + CvMat *tmp=NULL; + CvMat q1stub, q2stub; + CvMat q3stub, q4stub; + CvMat d1stub, d2stub; + CvMat d3stub, d4stub; + CvMat * q1, * q2, * q3, * q4; + CvMat * d1, * d2, * d3, * d4; + + CvSize size = cvGetSize(src_arr); + CvSize dst_size = cvGetSize(dst_arr); + int cx, cy; + + if(dst_size.width != size.width || + dst_size.height != size.height){ + error( "pdp_opencv_dft : source and destination arrays must have the same size" ); + } + + if(src_arr==dst_arr){ + tmp = cvCreateMat(size.height/2, size.width/2, cvGetElemType(src_arr)); + } + + cx = size.width/2; + cy = size.height/2; // image center + + q1 = cvGetSubRect( src_arr, &q1stub, cvRect(0,0,cx, cy) ); + q2 = cvGetSubRect( src_arr, &q2stub, cvRect(cx,0,cx,cy) ); + q3 = cvGetSubRect( src_arr, &q3stub, cvRect(cx,cy,cx,cy) ); + q4 = cvGetSubRect( src_arr, &q4stub, cvRect(0,cy,cx,cy) ); + d1 = cvGetSubRect( src_arr, &d1stub, cvRect(0,0,cx,cy) ); + d2 = cvGetSubRect( src_arr, &d2stub, cvRect(cx,0,cx,cy) ); + d3 = cvGetSubRect( src_arr, &d3stub, cvRect(cx,cy,cx,cy) ); + d4 = cvGetSubRect( src_arr, &d4stub, cvRect(0,cy,cx,cy) ); + + if(src_arr!=dst_arr){ + if( !CV_ARE_TYPES_EQ( q1, d1 )){ + error( "pdp_opencv_dft : source and destination arrays must have the same format" ); + } + cvCopy(q3, d1, 0); + cvCopy(q4, d2, 0); + cvCopy(q1, d3, 0); + cvCopy(q2, d4, 0); + } + else{ + cvCopy(q3, tmp, 0); + cvCopy(q1, q3, 0); + cvCopy(tmp, q1, 0); + cvCopy(q4, tmp, 0); + cvCopy(q2, q4, 0); + cvCopy(tmp, q2, 0); + } + if(src_arr==dst_arr){ + cvReleaseMat( &tmp ); + } +} + +static void pdp_opencv_dft_process_rgb(t_pdp_opencv_dft *x) +{ + t_pdp *header = pdp_packet_header(x->x_packet0); + short int *data = (short int *)pdp_packet_data(x->x_packet0); + t_pdp *newheader = pdp_packet_header(x->x_packet1); + short int *newdata = (short int *)pdp_packet_data(x->x_packet1); + t_pdp *phaseheader = pdp_packet_header(x->x_packet2); + short int *phasedata = (short int *)pdp_packet_data(x->x_packet2); + CvMat tmp; + double m,M; + int px,py; + + if ((x->x_width != (t_int)header->info.image.width) || + (x->x_height != (t_int)header->info.image.height)) + { + post("pdp_opencv_dft :: resizing"); + + x->x_width = header->info.image.width; + x->x_height = header->info.image.height; + x->x_size = x->x_width*x->x_height; + + //Destroy cv_images + cvReleaseImage( &x->image ); + //cvReleaseImage( &x->gray ); + cvReleaseImage( &x->input_re ); + cvReleaseImage( &x->input_im ); + cvReleaseImage( &x->input_co ); + cvReleaseMat( &x->dft_A ); + //cvReleaseImage( &x->image_re ); + //cvReleaseImage( &x->image_im ); + //cvReleaseImage( &x->image_mout ); + //cvReleaseImage( &x->image_pout ); + + x->image = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 3); + x->gray = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 1); + x->input_re = cvCreateImage( cvGetSize(x->image), IPL_DEPTH_64F, 1); + x->input_im = cvCreateImage( cvGetSize(x->image), IPL_DEPTH_64F, 1); + x->input_co = cvCreateImage( cvGetSize(x->image), IPL_DEPTH_64F, 2); + x->dft_M = cvGetOptimalDFTSize( x->gray->height - 1 ); + x->dft_N = cvGetOptimalDFTSize( x->gray->width - 1 ); + x->dft_A = cvCreateMat( x->dft_M, x->dft_N, CV_64FC2 ); + x->image_re = cvCreateImage( cvSize(x->dft_N, x->dft_M), IPL_DEPTH_64F, 1); + x->image_im = cvCreateImage( cvSize(x->dft_N, x->dft_M), IPL_DEPTH_64F, 1); + x->image_mout = cvCreateImage( cvSize(x->image->width, x->image->height), IPL_DEPTH_8U, 1); + x->image_pout = cvCreateImage( cvSize(x->image->width, x->image->height), IPL_DEPTH_8U, 1); + } + + newheader->info.image.encoding = PDP_BITMAP_GREY; + newheader->info.image.width = x->x_width; + newheader->info.image.height = x->x_height; + + memcpy( x->image->imageData, data, x->x_size*3 ); + cvCvtColor(x->image, x->gray, CV_BGR2GRAY); + + if ( x->x_calculate ) + { + // discrete fourier transform + cvScale(x->gray, x->input_re, 1.0, 0.0); + cvZero(x->input_im); + cvMerge(x->input_re, x->input_im, NULL, NULL, x->input_co); + + // copy A to dft_A and pad dft_A with zeros + cvGetSubRect( x->dft_A, &tmp, cvRect(0,0, x->gray->width, x->gray->height)); + cvCopy( x->input_co, &tmp, NULL ); + if( x->dft_A->cols > x->gray->width ) + { + cvGetSubRect( x->dft_A, &tmp, cvRect(x->gray->width,0, x->dft_A->cols - x->gray->width, x->gray->height)); + cvZero( &tmp ); + } + + // no need to pad bottom part of dft_A with zeros because of + // use nonzero_rows parameter in cvDFT() call below + cvDFT( x->dft_A, x->dft_A, CV_DXT_FORWARD, x->input_co->height ); + + // Split Fourier in real and imaginary parts + cvSplit( x->dft_A, x->image_re, x->image_im, 0, 0 ); + + // calculate phase + for( py=0; pyimage_re->height; py++ ) { + double* ptrr = (double*) ( x->image_re->imageData + py * x->image_re->widthStep); + double* ptri = (double*) ( x->image_im->imageData + py * x->image_im->widthStep); + float* ptrp = (float*) ( x->image_pout->imageData + py * x->image_pout->widthStep); + for( px=0; pximage_re->width; px++ ) { + (*(ptrp+px)) = cvFastArctan( (float)*(ptri+px), (float)*(ptrr+px) ); + } + } + + // Compute the magnitude of the spectrum Mag = sqrt(Re^2 + Im^2) + cvPow( x->image_re, x->image_re, 2.0); + cvPow( x->image_im, x->image_im, 2.0); + cvAdd( x->image_re, x->image_im, x->image_re, NULL); + cvPow( x->image_re, x->image_re, 0.5 ); + + // Compute log(1 + Mag) + cvAddS( x->image_re, cvScalarAll(1.0), x->image_re, NULL ); // 1 + Mag + cvLog( x->image_re, x->image_re ); // log(1 + Mag) + + // Rearrange the quadrants of Fourier image so that the origin is at + // the image center + pdp_opencv_dft_shift_dft( x->image_re, x->image_re ); + + // normalize image + cvMinMaxLoc(x->image_re, &m, &M, NULL, NULL, NULL); + cvScale(x->image_re, x->image_re, 255.0/(M-m), 255.0*(-m)/(M-m)); + + for( py=0; pyimage_re->height; py++ ) { + double* ptri = (double*) ( x->image_re->imageData + py * x->image_re->widthStep); + unsigned char* ptrp = (unsigned char*) ( x->image_mout->imageData + py * x->image_mout->widthStep); + for( px=0; pximage_re->width; px++ ) { + if ( *(ptrp+px) > 255.0 ) post( "pdp_opencv_dft : error value over 255" ); + (*(ptrp+px)) = (unsigned char)( (*(ptri+px)) ); + } + } + + x->x_calculate=0; + } + + cvCvtColor(x->image_mout, x->image, CV_GRAY2RGB); + memcpy( newdata, x->image->imageData, x->x_size*3 ); + cvCvtColor(x->image_pout, x->image, CV_GRAY2RGB); + memcpy( phasedata, x->image->imageData, x->x_size*3 ); + + return; +} + +static void pdp_opencv_dft_sendpacket(t_pdp_opencv_dft *x) +{ + /* release the packet */ + pdp_packet_mark_unused(x->x_packet0); + x->x_packet0 = -1; + + /* unregister and propagate if valid dest packet */ + pdp_packet_pass_if_valid(x->x_outlet0, &x->x_packet1); + + /* unregister and propagate if valid dest packet */ + pdp_packet_pass_if_valid(x->x_outlet1, &x->x_packet2); + + pdp_packet_mark_unused(x->x_packet1); + pdp_packet_mark_unused(x->x_packet2); +} + +static void pdp_opencv_dft_process(t_pdp_opencv_dft *x) +{ + int encoding; + t_pdp *header = 0; + + /* check if image data packets are compatible */ + if ( (header = pdp_packet_header(x->x_packet0)) + && (PDP_BITMAP == header->type)){ + + /* pdp_opencv_dft_process inputs and write into active inlet */ + switch(pdp_packet_header(x->x_packet0)->info.image.encoding){ + + case PDP_BITMAP_RGB: + x->x_packet1 = pdp_packet_clone_rw(x->x_packet0); + x->x_packet2 = pdp_packet_clone_rw(x->x_packet0); + pdp_queue_add(x, (void*)pdp_opencv_dft_process_rgb, (void*)pdp_opencv_dft_sendpacket, &x->x_queue_id); + break; + + default: + /* don't know the type, so dont pdp_opencv_dft_process */ + break; + + } + } + +} + +static void pdp_opencv_dft_calculate(t_pdp_opencv_dft *x) +{ + x->x_calculate=1; +} + +static void pdp_opencv_dft_input_0(t_pdp_opencv_dft *x, t_symbol *s, t_floatarg f) +{ + /* if this is a register_ro message or register_rw message, register with packet factory */ + + if (s == gensym("register_rw")) + x->x_dropped = pdp_packet_convert_ro_or_drop(&x->x_packet0, (int)f, pdp_gensym((char*)"bitmap/rgb/*") ); + + if ((s == gensym("process")) && (-1 != x->x_packet0) && (!x->x_dropped)) + { + /* add the process method and callback to the process queue */ + pdp_opencv_dft_process(x); + } +} + +static void pdp_opencv_dft_free(t_pdp_opencv_dft *x) +{ + int i; + + //destroy cv structures + cvReleaseImage( &x->image ); + //cvReleaseImage( &x->gray ); + cvReleaseImage( &x->input_re ); + cvReleaseImage( &x->input_im ); + cvReleaseImage( &x->input_co ); + cvReleaseMat( &x->dft_A ); + //cvReleaseImage( &x->image_re ); + //cvReleaseImage( &x->image_im ); + //cvReleaseImage( &x->image_mout ); + //cvReleaseImage( &x->image_pout ); + + pdp_queue_finish(x->x_queue_id); + pdp_packet_mark_unused(x->x_packet0); + +} + +t_class *pdp_opencv_dft_class; + + +void *pdp_opencv_dft_new(t_floatarg f) +{ + int i; + + t_pdp_opencv_dft *x = (t_pdp_opencv_dft *)pd_new(pdp_opencv_dft_class); + + x->x_outlet0 = outlet_new(&x->x_obj, &s_anything); + x->x_outlet1 = outlet_new(&x->x_obj, &s_anything); + + x->x_packet0 = -1; + x->x_packet1 = -1; + x->x_packet2 = -1; + x->x_queue_id = -1; + + x->x_width = 320; + x->x_height = 240; + x->x_size = x->x_width * x->x_height; + + x->image = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 3); + x->gray = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 1); + x->input_re = cvCreateImage( cvGetSize(x->image), IPL_DEPTH_64F, 1); + x->input_im = cvCreateImage( cvGetSize(x->image), IPL_DEPTH_64F, 1); + x->input_co = cvCreateImage( cvGetSize(x->image), IPL_DEPTH_64F, 2); + x->dft_M = cvGetOptimalDFTSize( x->gray->height - 1 ); + x->dft_N = cvGetOptimalDFTSize( x->gray->width - 1 ); + x->dft_A = cvCreateMat( x->dft_M, x->dft_N, CV_64FC2 ); + x->image_re = cvCreateImage( cvSize(x->dft_N, x->dft_M), IPL_DEPTH_64F, 1); + x->image_im = cvCreateImage( cvSize(x->dft_N, x->dft_M), IPL_DEPTH_64F, 1); + x->image_mout = cvCreateImage( cvSize(x->dft_N, x->dft_M), IPL_DEPTH_8U, 1); + x->image_pout = cvCreateImage( cvSize(x->dft_N, x->dft_M), IPL_DEPTH_8U, 1); + + // calculate first dft + x->x_calculate=1; + + return (void *)x; +} + + +#ifdef __cplusplus +extern "C" +{ +#endif + + +void pdp_opencv_dft_setup(void) +{ + + post( " pdp_opencv_dft"); + pdp_opencv_dft_class = class_new(gensym("pdp_opencv_dft"), (t_newmethod)pdp_opencv_dft_new, + (t_method)pdp_opencv_dft_free, sizeof(t_pdp_opencv_dft), 0, A_DEFFLOAT, A_NULL); + + class_addmethod(pdp_opencv_dft_class, (t_method)pdp_opencv_dft_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL); + class_addmethod(pdp_opencv_dft_class, (t_method)pdp_opencv_dft_calculate, gensym("bang"), A_NULL); + +} + +#ifdef __cplusplus +} +#endif diff --git a/pdp_opencv_distrans.c b/pdp_opencv_distrans.c deleted file mode 100644 index 4fa2aba..0000000 --- a/pdp_opencv_distrans.c +++ /dev/null @@ -1,357 +0,0 @@ -/* - * Pure Data Packet module. - * Copyright (c) by Tom Schouten - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include -#include -#include -#include -#include -#include - -#include "pdp.h" - -#ifndef _EiC -#include "cv.h" -#endif - - - -typedef struct pdp_opencv_distrans_struct -{ - t_object x_obj; - t_float x_f; - - t_outlet *x_outlet0; - int x_packet0; - int x_packet1; - int x_dropped; - int x_queue_id; - - int x_width; - int x_height; - int x_size; - - int x_infosok; - - int edge_thresh; - int build_voronoi; - int mask_size; - - // The output and temporary images - IplImage* dist; - IplImage* dist8u1; - IplImage* dist8u2; - IplImage* dist8u; - IplImage* dist32s; - - IplImage* image; - IplImage* gray; - IplImage* edge; - IplImage* labels; - - -} t_pdp_opencv_distrans; - - - -static void pdp_opencv_distrans_process_rgb(t_pdp_opencv_distrans *x) -{ - t_pdp *header = pdp_packet_header(x->x_packet0); - short int *data = (short int *)pdp_packet_data(x->x_packet0); - t_pdp *newheader = pdp_packet_header(x->x_packet1); - short int *newdata = (short int *)pdp_packet_data(x->x_packet1); - static const uchar colors[][3] = - { - {0,0,0}, - {255,0,0}, - {255,128,0}, - {255,255,0}, - {0,255,0}, - {0,128,255}, - {0,255,255}, - {0,0,255}, - {255,0,255} - }; - - int msize = x->mask_size; - - - if ((x->x_width != (t_int)header->info.image.width) || - (x->x_height != (t_int)header->info.image.height)) - { - - post("pdp_opencv_distrans :: resizing plugins"); - - //cv_freeplugins(x); - - x->x_width = header->info.image.width; - x->x_height = header->info.image.height; - x->x_size = x->x_width*x->x_height; - - //Destroy cv_images - cvReleaseImage( &x->image ); - cvReleaseImage( &x->gray ); - cvReleaseImage( &x->edge ); - cvReleaseImage( &x->dist ); - cvReleaseImage( &x->dist8u ); - cvReleaseImage( &x->dist8u1 ); - cvReleaseImage( &x->dist8u2 ); - cvReleaseImage( &x->dist32s ); - cvReleaseImage( &x->labels ); - - x->image = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 3); - x->gray = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 1); - x->dist = cvCreateImage( cvGetSize(x->gray), IPL_DEPTH_32F, 1 ); - x->dist8u1 = cvCloneImage( x->gray ); - x->dist8u2 = cvCloneImage( x->gray ); - x->dist8u = cvCreateImage( cvGetSize(x->gray), IPL_DEPTH_8U, 3 ); - x->dist32s = cvCreateImage( cvGetSize(x->gray), IPL_DEPTH_32S, 1 ); - x->edge = cvCloneImage( x->gray ); - x->labels = cvCreateImage( cvGetSize(x->gray), IPL_DEPTH_32S, 1 ); - } - - newheader->info.image.encoding = header->info.image.encoding; - newheader->info.image.width = x->x_width; - newheader->info.image.height = x->x_height; - - memcpy( newdata, data, x->x_size*3 ); - - memcpy( x->image->imageData, data, x->x_size*3 ); - cvCvtColor(x->image, x->gray, CV_BGR2GRAY); - - cvThreshold( x->gray, x->edge, (float)x->edge_thresh, (float)x->edge_thresh, CV_THRESH_BINARY ); - - if( x->build_voronoi ) - msize = CV_DIST_MASK_5; - - cvDistTransform( x->edge, x->dist, CV_DIST_L2, msize, NULL, x->build_voronoi ? x->labels : NULL ); - - if( !x->build_voronoi ) - { - // begin "painting" the distance transform result - cvConvertScale( x->dist, x->dist, 5000.0, 0 ); - cvPow( x->dist, x->dist, 0.5 ); - - cvConvertScale( x->dist, x->dist32s, 1.0, 0.5 ); - cvAndS( x->dist32s, cvScalarAll(255), x->dist32s, 0 ); - cvConvertScale( x->dist32s, x->dist8u1, 1, 0 ); - cvConvertScale( x->dist32s, x->dist32s, -1, 0 ); - cvAddS( x->dist32s, cvScalarAll(255), x->dist32s, 0 ); - cvConvertScale( x->dist32s, x->dist8u2, 1, 0 ); - cvMerge( x->dist8u1, x->dist8u2, x->dist8u2, 0, x->dist8u ); - // end "painting" the distance transform result - } - else - { - int i, j; - for( i = 0; i < x->labels->height; i++ ) - { - int* ll = (int*)(x->labels->imageData + i*x->labels->widthStep); - float* dd = (float*)(x->dist->imageData + i*x->dist->widthStep); - uchar* d = (uchar*)(x->dist8u->imageData + i*x->dist8u->widthStep); - for( j = 0; j < x->labels->width; j++ ) - { - int idx = ll[j] == 0 || dd[j] == 0 ? 0 : (ll[j]-1)%8 + 1; - int b = cvRound(colors[idx][0]); - int g = cvRound(colors[idx][1]); - int r = cvRound(colors[idx][2]); - d[j*3] = (uchar)b; - d[j*3+1] = (uchar)g; - d[j*3+2] = (uchar)r; - } - } - } - - memcpy( newdata, x->dist8u->imageData, x->x_size*3 ); - - return; -} - -static void pdp_opencv_distrans_type(t_pdp_opencv_distrans *x, t_floatarg f) -{ - if( (int)f == 3 ) - x->mask_size = CV_DIST_MASK_3; - else if( (int)f == 5 ) - x->mask_size = CV_DIST_MASK_5; - else if( (int)f == 0 ) - x->mask_size = CV_DIST_MASK_PRECISE; - -} - -static void pdp_opencv_distrans_voronoi(t_pdp_opencv_distrans *x, t_floatarg f) -{ - int v = (int)f; - if (v<0) v=0; - else if (v>1) v=1; - - x->build_voronoi=(int)v; -} - -static void pdp_opencv_distrans_thresh(t_pdp_opencv_distrans *x, t_floatarg f) -{ - x->edge_thresh = (int)f; -} - -static void pdp_opencv_distrans_sendpacket(t_pdp_opencv_distrans *x) -{ - /* release the packet */ - pdp_packet_mark_unused(x->x_packet0); - x->x_packet0 = -1; - - /* unregister and propagate if valid dest packet */ - pdp_packet_pass_if_valid(x->x_outlet0, &x->x_packet1); -} - -static void pdp_opencv_distrans_process(t_pdp_opencv_distrans *x) -{ - int encoding; - t_pdp *header = 0; - char *parname; - unsigned pi; - int partype; - float pardefault; - t_atom plist[2]; - t_atom tlist[2]; - t_atom vlist[2]; - - /* check if image data packets are compatible */ - if ( (header = pdp_packet_header(x->x_packet0)) - && (PDP_BITMAP == header->type)){ - - /* pdp_opencv_distrans_process inputs and write into active inlet */ - switch(pdp_packet_header(x->x_packet0)->info.image.encoding){ - - case PDP_BITMAP_RGB: - x->x_packet1 = pdp_packet_clone_rw(x->x_packet0); - pdp_queue_add(x, pdp_opencv_distrans_process_rgb, pdp_opencv_distrans_sendpacket, &x->x_queue_id); - break; - - default: - /* don't know the type, so dont pdp_opencv_distrans_process */ - break; - - } - } - -} - -static void pdp_opencv_distrans_input_0(t_pdp_opencv_distrans *x, t_symbol *s, t_floatarg f) -{ - /* if this is a register_ro message or register_rw message, register with packet factory */ - - if (s == gensym("register_rw")) - x->x_dropped = pdp_packet_convert_ro_or_drop(&x->x_packet0, (int)f, pdp_gensym("bitmap/rgb/*") ); - - if ((s == gensym("process")) && (-1 != x->x_packet0) && (!x->x_dropped)) - { - /* add the process method and callback to the process queue */ - pdp_opencv_distrans_process(x); - } -} - -static void pdp_opencv_distrans_free(t_pdp_opencv_distrans *x) -{ - int i; - - pdp_queue_finish(x->x_queue_id); - pdp_packet_mark_unused(x->x_packet0); - //cv_freeplugins(x); - - //Destroy cv_images - cvReleaseImage( &x->image ); - cvReleaseImage( &x->gray ); - cvReleaseImage( &x->edge ); - cvReleaseImage( &x->dist ); - cvReleaseImage( &x->dist8u ); - cvReleaseImage( &x->dist8u1 ); - cvReleaseImage( &x->dist8u2 ); - cvReleaseImage( &x->dist32s ); - cvReleaseImage( &x->labels ); -} - -t_class *pdp_opencv_distrans_class; - - -void *pdp_opencv_distrans_new(t_floatarg f) -{ - int i; - - t_pdp_opencv_distrans *x = (t_pdp_opencv_distrans *)pd_new(pdp_opencv_distrans_class); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("edge_thresh")); - - x->x_outlet0 = outlet_new(&x->x_obj, &s_anything); - - x->x_packet0 = -1; - x->x_packet1 = -1; - x->x_queue_id = -1; - - x->x_width = 320; - x->x_height = 240; - x->x_size = x->x_width * x->x_height; - - //load the plugins - x->x_infosok = 0; - //cv_loadplugins(x, FF_PLUGIN_DIR); - - //pdp_opencv_distrans_plugin(x, f); - x->edge_thresh = 100; - x->build_voronoi = 0; - x->mask_size = CV_DIST_MASK_5; - - - - x->image = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 3); - x->gray = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 1); - cvCvtColor(x->image, x->gray, CV_BGR2GRAY); - x->dist = cvCreateImage( cvSize(x->x_width,x->x_height), IPL_DEPTH_32F, 1 ); - x->dist8u1 = cvCloneImage( x->gray ); - x->dist8u2 = cvCloneImage( x->gray ); - x->dist8u = cvCreateImage( cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 3 ); - x->dist32s = cvCreateImage( cvSize(x->x_width,x->x_height), IPL_DEPTH_32S, 1 ); - x->edge = cvCloneImage( x->gray ); - x->labels = cvCreateImage( cvSize(x->x_width,x->x_height), IPL_DEPTH_32S, 1 ); - - return (void *)x; -} - - -#ifdef __cplusplus -extern "C" -{ -#endif - - -void pdp_opencv_distrans_setup(void) -{ - - post( " pdp_opencv_distrans"); - pdp_opencv_distrans_class = class_new(gensym("pdp_opencv_distrans"), (t_newmethod)pdp_opencv_distrans_new, - (t_method)pdp_opencv_distrans_free, sizeof(t_pdp_opencv_distrans), 0, A_DEFFLOAT, A_NULL); - - class_addmethod(pdp_opencv_distrans_class, (t_method)pdp_opencv_distrans_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL); - class_addmethod(pdp_opencv_distrans_class, (t_method)pdp_opencv_distrans_thresh, gensym("edge_thresh"), A_FLOAT, A_NULL ); - class_addmethod(pdp_opencv_distrans_class, (t_method)pdp_opencv_distrans_type, gensym("type"), A_FLOAT, A_NULL); - class_addmethod(pdp_opencv_distrans_class, (t_method)pdp_opencv_distrans_voronoi, gensym("voronoi"), A_FLOAT, A_NULL); - -} - -#ifdef __cplusplus -} -#endif diff --git a/pdp_opencv_distrans.cc b/pdp_opencv_distrans.cc new file mode 100755 index 0000000..21c868b --- /dev/null +++ b/pdp_opencv_distrans.cc @@ -0,0 +1,357 @@ +/* + * Pure Data Packet module. + * Copyright (c) by Tom Schouten + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include + +#include "pdp.h" + +#ifndef _EiC +#include "cv.h" +#endif + + + +typedef struct pdp_opencv_distrans_struct +{ + t_object x_obj; + t_float x_f; + + t_outlet *x_outlet0; + int x_packet0; + int x_packet1; + int x_dropped; + int x_queue_id; + + int x_width; + int x_height; + int x_size; + + int x_infosok; + + int edge_thresh; + int build_voronoi; + int mask_size; + + // The output and temporary images + IplImage* dist; + IplImage* dist8u1; + IplImage* dist8u2; + IplImage* dist8u; + IplImage* dist32s; + + IplImage* image; + IplImage* gray; + IplImage* edge; + IplImage* labels; + + +} t_pdp_opencv_distrans; + + + +static void pdp_opencv_distrans_process_rgb(t_pdp_opencv_distrans *x) +{ + t_pdp *header = pdp_packet_header(x->x_packet0); + short int *data = (short int *)pdp_packet_data(x->x_packet0); + t_pdp *newheader = pdp_packet_header(x->x_packet1); + short int *newdata = (short int *)pdp_packet_data(x->x_packet1); + static const uchar colors[][3] = + { + {0,0,0}, + {255,0,0}, + {255,128,0}, + {255,255,0}, + {0,255,0}, + {0,128,255}, + {0,255,255}, + {0,0,255}, + {255,0,255} + }; + + int msize = x->mask_size; + + + if ((x->x_width != (t_int)header->info.image.width) || + (x->x_height != (t_int)header->info.image.height)) + { + + post("pdp_opencv_distrans :: resizing plugins"); + + //cv_freeplugins(x); + + x->x_width = header->info.image.width; + x->x_height = header->info.image.height; + x->x_size = x->x_width*x->x_height; + + //Destroy cv_images + cvReleaseImage( &x->image ); + cvReleaseImage( &x->gray ); + cvReleaseImage( &x->edge ); + cvReleaseImage( &x->dist ); + cvReleaseImage( &x->dist8u ); + cvReleaseImage( &x->dist8u1 ); + cvReleaseImage( &x->dist8u2 ); + cvReleaseImage( &x->dist32s ); + cvReleaseImage( &x->labels ); + + x->image = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 3); + x->gray = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 1); + x->dist = cvCreateImage( cvGetSize(x->gray), IPL_DEPTH_32F, 1 ); + x->dist8u1 = cvCloneImage( x->gray ); + x->dist8u2 = cvCloneImage( x->gray ); + x->dist8u = cvCreateImage( cvGetSize(x->gray), IPL_DEPTH_8U, 3 ); + x->dist32s = cvCreateImage( cvGetSize(x->gray), IPL_DEPTH_32S, 1 ); + x->edge = cvCloneImage( x->gray ); + x->labels = cvCreateImage( cvGetSize(x->gray), IPL_DEPTH_32S, 1 ); + } + + newheader->info.image.encoding = header->info.image.encoding; + newheader->info.image.width = x->x_width; + newheader->info.image.height = x->x_height; + + memcpy( newdata, data, x->x_size*3 ); + + memcpy( x->image->imageData, data, x->x_size*3 ); + cvCvtColor(x->image, x->gray, CV_BGR2GRAY); + + cvThreshold( x->gray, x->edge, (float)x->edge_thresh, (float)x->edge_thresh, CV_THRESH_BINARY ); + + if( x->build_voronoi ) + msize = CV_DIST_MASK_5; + + cvDistTransform( x->edge, x->dist, CV_DIST_L2, msize, NULL, x->build_voronoi ? x->labels : NULL ); + + if( !x->build_voronoi ) + { + // begin "painting" the distance transform result + cvConvertScale( x->dist, x->dist, 5000.0, 0 ); + cvPow( x->dist, x->dist, 0.5 ); + + cvConvertScale( x->dist, x->dist32s, 1.0, 0.5 ); + cvAndS( x->dist32s, cvScalarAll(255), x->dist32s, 0 ); + cvConvertScale( x->dist32s, x->dist8u1, 1, 0 ); + cvConvertScale( x->dist32s, x->dist32s, -1, 0 ); + cvAddS( x->dist32s, cvScalarAll(255), x->dist32s, 0 ); + cvConvertScale( x->dist32s, x->dist8u2, 1, 0 ); + cvMerge( x->dist8u1, x->dist8u2, x->dist8u2, 0, x->dist8u ); + // end "painting" the distance transform result + } + else + { + int i, j; + for( i = 0; i < x->labels->height; i++ ) + { + int* ll = (int*)(x->labels->imageData + i*x->labels->widthStep); + float* dd = (float*)(x->dist->imageData + i*x->dist->widthStep); + uchar* d = (uchar*)(x->dist8u->imageData + i*x->dist8u->widthStep); + for( j = 0; j < x->labels->width; j++ ) + { + int idx = ll[j] == 0 || dd[j] == 0 ? 0 : (ll[j]-1)%8 + 1; + int b = cvRound(colors[idx][0]); + int g = cvRound(colors[idx][1]); + int r = cvRound(colors[idx][2]); + d[j*3] = (uchar)b; + d[j*3+1] = (uchar)g; + d[j*3+2] = (uchar)r; + } + } + } + + memcpy( newdata, x->dist8u->imageData, x->x_size*3 ); + + return; +} + +static void pdp_opencv_distrans_type(t_pdp_opencv_distrans *x, t_floatarg f) +{ + if( (int)f == 3 ) + x->mask_size = CV_DIST_MASK_3; + else if( (int)f == 5 ) + x->mask_size = CV_DIST_MASK_5; + else if( (int)f == 0 ) + x->mask_size = CV_DIST_MASK_PRECISE; + +} + +static void pdp_opencv_distrans_voronoi(t_pdp_opencv_distrans *x, t_floatarg f) +{ + int v = (int)f; + if (v<0) v=0; + else if (v>1) v=1; + + x->build_voronoi=(int)v; +} + +static void pdp_opencv_distrans_thresh(t_pdp_opencv_distrans *x, t_floatarg f) +{ + x->edge_thresh = (int)f; +} + +static void pdp_opencv_distrans_sendpacket(t_pdp_opencv_distrans *x) +{ + /* release the packet */ + pdp_packet_mark_unused(x->x_packet0); + x->x_packet0 = -1; + + /* unregister and propagate if valid dest packet */ + pdp_packet_pass_if_valid(x->x_outlet0, &x->x_packet1); +} + +static void pdp_opencv_distrans_process(t_pdp_opencv_distrans *x) +{ + int encoding; + t_pdp *header = 0; + char *parname; + unsigned pi; + int partype; + float pardefault; + t_atom plist[2]; + t_atom tlist[2]; + t_atom vlist[2]; + + /* check if image data packets are compatible */ + if ( (header = pdp_packet_header(x->x_packet0)) + && (PDP_BITMAP == header->type)){ + + /* pdp_opencv_distrans_process inputs and write into active inlet */ + switch(pdp_packet_header(x->x_packet0)->info.image.encoding){ + + case PDP_BITMAP_RGB: + x->x_packet1 = pdp_packet_clone_rw(x->x_packet0); + pdp_queue_add(x, (void*)pdp_opencv_distrans_process_rgb, (void*)pdp_opencv_distrans_sendpacket, &x->x_queue_id); + break; + + default: + /* don't know the type, so dont pdp_opencv_distrans_process */ + break; + + } + } + +} + +static void pdp_opencv_distrans_input_0(t_pdp_opencv_distrans *x, t_symbol *s, t_floatarg f) +{ + /* if this is a register_ro message or register_rw message, register with packet factory */ + + if (s == gensym("register_rw")) + x->x_dropped = pdp_packet_convert_ro_or_drop(&x->x_packet0, (int)f, pdp_gensym((char*)"bitmap/rgb/*") ); + + if ((s == gensym("process")) && (-1 != x->x_packet0) && (!x->x_dropped)) + { + /* add the process method and callback to the process queue */ + pdp_opencv_distrans_process(x); + } +} + +static void pdp_opencv_distrans_free(t_pdp_opencv_distrans *x) +{ + int i; + + pdp_queue_finish(x->x_queue_id); + pdp_packet_mark_unused(x->x_packet0); + //cv_freeplugins(x); + + //Destroy cv_images + cvReleaseImage( &x->image ); + cvReleaseImage( &x->gray ); + cvReleaseImage( &x->edge ); + cvReleaseImage( &x->dist ); + cvReleaseImage( &x->dist8u ); + cvReleaseImage( &x->dist8u1 ); + cvReleaseImage( &x->dist8u2 ); + cvReleaseImage( &x->dist32s ); + cvReleaseImage( &x->labels ); +} + +t_class *pdp_opencv_distrans_class; + + +void *pdp_opencv_distrans_new(t_floatarg f) +{ + int i; + + t_pdp_opencv_distrans *x = (t_pdp_opencv_distrans *)pd_new(pdp_opencv_distrans_class); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("edge_thresh")); + + x->x_outlet0 = outlet_new(&x->x_obj, &s_anything); + + x->x_packet0 = -1; + x->x_packet1 = -1; + x->x_queue_id = -1; + + x->x_width = 320; + x->x_height = 240; + x->x_size = x->x_width * x->x_height; + + //load the plugins + x->x_infosok = 0; + //cv_loadplugins(x, FF_PLUGIN_DIR); + + //pdp_opencv_distrans_plugin(x, f); + x->edge_thresh = 100; + x->build_voronoi = 0; + x->mask_size = CV_DIST_MASK_5; + + + + x->image = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 3); + x->gray = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 1); + cvCvtColor(x->image, x->gray, CV_BGR2GRAY); + x->dist = cvCreateImage( cvSize(x->x_width,x->x_height), IPL_DEPTH_32F, 1 ); + x->dist8u1 = cvCloneImage( x->gray ); + x->dist8u2 = cvCloneImage( x->gray ); + x->dist8u = cvCreateImage( cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 3 ); + x->dist32s = cvCreateImage( cvSize(x->x_width,x->x_height), IPL_DEPTH_32S, 1 ); + x->edge = cvCloneImage( x->gray ); + x->labels = cvCreateImage( cvSize(x->x_width,x->x_height), IPL_DEPTH_32S, 1 ); + + return (void *)x; +} + + +#ifdef __cplusplus +extern "C" +{ +#endif + + +void pdp_opencv_distrans_setup(void) +{ + + post( " pdp_opencv_distrans"); + pdp_opencv_distrans_class = class_new(gensym("pdp_opencv_distrans"), (t_newmethod)pdp_opencv_distrans_new, + (t_method)pdp_opencv_distrans_free, sizeof(t_pdp_opencv_distrans), 0, A_DEFFLOAT, A_NULL); + + class_addmethod(pdp_opencv_distrans_class, (t_method)pdp_opencv_distrans_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL); + class_addmethod(pdp_opencv_distrans_class, (t_method)pdp_opencv_distrans_thresh, gensym("edge_thresh"), A_FLOAT, A_NULL ); + class_addmethod(pdp_opencv_distrans_class, (t_method)pdp_opencv_distrans_type, gensym("type"), A_FLOAT, A_NULL); + class_addmethod(pdp_opencv_distrans_class, (t_method)pdp_opencv_distrans_voronoi, gensym("voronoi"), A_FLOAT, A_NULL); + +} + +#ifdef __cplusplus +} +#endif diff --git a/pdp_opencv_edge.c b/pdp_opencv_edge.c deleted file mode 100644 index d227381..0000000 --- a/pdp_opencv_edge.c +++ /dev/null @@ -1,272 +0,0 @@ -/* - * Pure Data Packet module. - * Copyright (c) by Tom Schouten - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include -#include -#include -#include -#include -#include - -#include "pdp.h" - -#ifndef _EiC -#include "cv.h" -#endif - - - -typedef struct pdp_opencv_edge_struct -{ - t_object x_obj; - t_float x_f; - - t_outlet *x_outlet0; - int x_packet0; - int x_packet1; - int x_dropped; - int x_queue_id; - - int x_width; - int x_height; - int x_size; - - int x_infosok; - - int edge_thresh; - IplImage *image, *cedge, *gray, *edge; - - -} t_pdp_opencv_edge; - - -void panic(const char *panicstr, ...) -{ - post("pdp_opencv_edge :: PANIC!! %s\n", panicstr); - exit(1); -} - -static void pdp_opencv_edge_process_rgb(t_pdp_opencv_edge *x) -{ - t_pdp *header = pdp_packet_header(x->x_packet0); - short int *data = (short int *)pdp_packet_data(x->x_packet0); - t_pdp *newheader = pdp_packet_header(x->x_packet1); - short int *newdata = (short int *)pdp_packet_data(x->x_packet1); - - - if ((x->x_width != (t_int)header->info.image.width) || - (x->x_height != (t_int)header->info.image.height)) - { - - post("pdp_opencv_edge :: resizing buffers"); - - //cv_freeplugins(x); - - x->x_width = header->info.image.width; - x->x_height = header->info.image.height; - x->x_size = x->x_width*x->x_height; - - //Destroy cv_images - cvReleaseImage(&x->image); - cvReleaseImage(&x->gray); - cvReleaseImage(&x->edge); - cvReleaseImage(&x->cedge); - - //create the orig image with new size - x->image = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 3); - - // Create the output images with new sizes - x->cedge = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 3); - - x->gray = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 1); - x->edge = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 1); - } - - newheader->info.image.encoding = header->info.image.encoding; - newheader->info.image.width = x->x_width; - newheader->info.image.height = x->x_height; - - - // We make here a copy of the PDP packet in image->imageData ... - // take a look on the IplImage data structure - // http://www.cs.iit.edu/~agam/cs512/lect-notes/opencv-intro/opencv-intro.html - memcpy( x->image->imageData, data, x->x_size*3 ); - - // Convert to grayscale - cvCvtColor(x->image, x->gray, CV_BGR2GRAY); - - cvSmooth( x->gray, x->edge, CV_BLUR, 3, 3, 0, 0 ); - cvNot( x->gray, x->edge ); - - // Run the edge detector on grayscale - cvCanny(x->gray, x->edge, (float)x->edge_thresh, (float)x->edge_thresh*3, 3); - - cvZero( x->cedge ); - - // copy edge points - cvCopy( x->image, x->cedge, x->edge ); - - //memory copy again, now from x->cedge->imageData to the new data pdp packet - memcpy( newdata, x->cedge->imageData, x->x_size*3 ); - - - return; -} - -static void pdp_opencv_edge_thresh(t_pdp_opencv_edge *x, t_floatarg f) -{ - x->edge_thresh = (int)f; -} - -static void pdp_opencv_edge_sendpacket(t_pdp_opencv_edge *x) -{ - /* release the packet */ - pdp_packet_mark_unused(x->x_packet0); - x->x_packet0 = -1; - - /* unregister and propagate if valid dest packet */ - pdp_packet_pass_if_valid(x->x_outlet0, &x->x_packet1); -} - -static void pdp_opencv_edge_process(t_pdp_opencv_edge *x) -{ - int encoding; - t_pdp *header = 0; - char *parname; - unsigned pi; - int partype; - float pardefault; - t_atom plist[2]; - t_atom tlist[2]; - t_atom vlist[2]; - - /* check if image data packets are compatible */ - if ( (header = pdp_packet_header(x->x_packet0)) - && (PDP_BITMAP == header->type)){ - - /* pdp_opencv_edge_process inputs and write into active inlet */ - switch(pdp_packet_header(x->x_packet0)->info.image.encoding){ - - case PDP_BITMAP_RGB: - x->x_packet1 = pdp_packet_clone_rw(x->x_packet0); - pdp_queue_add(x, pdp_opencv_edge_process_rgb, pdp_opencv_edge_sendpacket, &x->x_queue_id); - break; - - default: - /* don't know the type, so dont pdp_opencv_edge_process */ - break; - - } - } - -} - -static void pdp_opencv_edge_input_0(t_pdp_opencv_edge *x, t_symbol *s, t_floatarg f) -{ - /* if this is a register_ro message or register_rw message, register with packet factory */ - - if (s == gensym("register_rw")) - x->x_dropped = pdp_packet_convert_ro_or_drop(&x->x_packet0, (int)f, pdp_gensym("bitmap/rgb/*") ); - - if ((s == gensym("process")) && (-1 != x->x_packet0) && (!x->x_dropped)) - { - /* add the process method and callback to the process queue */ - pdp_opencv_edge_process(x); - } -} - -static void pdp_opencv_edge_free(t_pdp_opencv_edge *x) -{ - int i; - - pdp_queue_finish(x->x_queue_id); - pdp_packet_mark_unused(x->x_packet0); - //cv_freeplugins(x); - - //Destroy cv_images - cvReleaseImage(&x->image); - cvReleaseImage(&x->gray); - cvReleaseImage(&x->edge); - cvReleaseImage(&x->cedge); -} - -t_class *pdp_opencv_edge_class; - - -void *pdp_opencv_edge_new(t_floatarg f) -{ - int i; - - t_pdp_opencv_edge *x = (t_pdp_opencv_edge *)pd_new(pdp_opencv_edge_class); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("edge_thresh")); - - x->x_outlet0 = outlet_new(&x->x_obj, &s_anything); - - x->x_packet0 = -1; - x->x_packet1 = -1; - x->x_queue_id = -1; - - x->x_width = 320; - x->x_height = 240; - x->x_size = x->x_width * x->x_height; - - x->x_infosok = 0; - x->edge_thresh = 1; - - - - - x->image = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 3); - - -// Create the output image - x->cedge = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 3); - - // Convert to grayscale - x->gray = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 1); - x->edge = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 1); - cvCvtColor(x->image, x->gray, CV_BGR2GRAY); - - return (void *)x; -} - - -#ifdef __cplusplus -extern "C" -{ -#endif - - -void pdp_opencv_edge_setup(void) -{ - - post( " pdp_opencv_edge"); - pdp_opencv_edge_class = class_new(gensym("pdp_opencv_edge"), (t_newmethod)pdp_opencv_edge_new, - (t_method)pdp_opencv_edge_free, sizeof(t_pdp_opencv_edge), 0, A_DEFFLOAT, A_NULL); - - class_addmethod(pdp_opencv_edge_class, (t_method)pdp_opencv_edge_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL); - class_addmethod(pdp_opencv_edge_class, (t_method)pdp_opencv_edge_thresh, gensym("edge_thresh"), A_FLOAT, A_NULL ); - - -} - -#ifdef __cplusplus -} -#endif diff --git a/pdp_opencv_edge.cc b/pdp_opencv_edge.cc new file mode 100755 index 0000000..fd2d3a3 --- /dev/null +++ b/pdp_opencv_edge.cc @@ -0,0 +1,272 @@ +/* + * Pure Data Packet module. + * Copyright (c) by Tom Schouten + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include + +#include "pdp.h" + +#ifndef _EiC +#include "cv.h" +#endif + + + +typedef struct pdp_opencv_edge_struct +{ + t_object x_obj; + t_float x_f; + + t_outlet *x_outlet0; + int x_packet0; + int x_packet1; + int x_dropped; + int x_queue_id; + + int x_width; + int x_height; + int x_size; + + int x_infosok; + + int edge_thresh; + IplImage *image, *cedge, *gray, *edge; + + +} t_pdp_opencv_edge; + + +void panic(const char *panicstr, ...) +{ + post("pdp_opencv_edge :: PANIC!! %s\n", panicstr); + exit(1); +} + +static void pdp_opencv_edge_process_rgb(t_pdp_opencv_edge *x) +{ + t_pdp *header = pdp_packet_header(x->x_packet0); + short int *data = (short int *)pdp_packet_data(x->x_packet0); + t_pdp *newheader = pdp_packet_header(x->x_packet1); + short int *newdata = (short int *)pdp_packet_data(x->x_packet1); + + + if ((x->x_width != (t_int)header->info.image.width) || + (x->x_height != (t_int)header->info.image.height)) + { + + post("pdp_opencv_edge :: resizing buffers"); + + //cv_freeplugins(x); + + x->x_width = header->info.image.width; + x->x_height = header->info.image.height; + x->x_size = x->x_width*x->x_height; + + //Destroy cv_images + cvReleaseImage(&x->image); + cvReleaseImage(&x->gray); + cvReleaseImage(&x->edge); + cvReleaseImage(&x->cedge); + + //create the orig image with new size + x->image = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 3); + + // Create the output images with new sizes + x->cedge = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 3); + + x->gray = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 1); + x->edge = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 1); + } + + newheader->info.image.encoding = header->info.image.encoding; + newheader->info.image.width = x->x_width; + newheader->info.image.height = x->x_height; + + + // We make here a copy of the PDP packet in image->imageData ... + // take a look on the IplImage data structure + // http://www.cs.iit.edu/~agam/cs512/lect-notes/opencv-intro/opencv-intro.html + memcpy( x->image->imageData, data, x->x_size*3 ); + + // Convert to grayscale + cvCvtColor(x->image, x->gray, CV_BGR2GRAY); + + cvSmooth( x->gray, x->edge, CV_BLUR, 3, 3, 0, 0 ); + cvNot( x->gray, x->edge ); + + // Run the edge detector on grayscale + cvCanny(x->gray, x->edge, (float)x->edge_thresh, (float)x->edge_thresh*3, 3); + + cvZero( x->cedge ); + + // copy edge points + cvCopy( x->image, x->cedge, x->edge ); + + //memory copy again, now from x->cedge->imageData to the new data pdp packet + memcpy( newdata, x->cedge->imageData, x->x_size*3 ); + + + return; +} + +static void pdp_opencv_edge_thresh(t_pdp_opencv_edge *x, t_floatarg f) +{ + x->edge_thresh = (int)f; +} + +static void pdp_opencv_edge_sendpacket(t_pdp_opencv_edge *x) +{ + /* release the packet */ + pdp_packet_mark_unused(x->x_packet0); + x->x_packet0 = -1; + + /* unregister and propagate if valid dest packet */ + pdp_packet_pass_if_valid(x->x_outlet0, &x->x_packet1); +} + +static void pdp_opencv_edge_process(t_pdp_opencv_edge *x) +{ + int encoding; + t_pdp *header = 0; + char *parname; + unsigned pi; + int partype; + float pardefault; + t_atom plist[2]; + t_atom tlist[2]; + t_atom vlist[2]; + + /* check if image data packets are compatible */ + if ( (header = pdp_packet_header(x->x_packet0)) + && (PDP_BITMAP == header->type)){ + + /* pdp_opencv_edge_process inputs and write into active inlet */ + switch(pdp_packet_header(x->x_packet0)->info.image.encoding){ + + case PDP_BITMAP_RGB: + x->x_packet1 = pdp_packet_clone_rw(x->x_packet0); + pdp_queue_add(x, (void*)pdp_opencv_edge_process_rgb, (void*)pdp_opencv_edge_sendpacket, &x->x_queue_id); + break; + + default: + /* don't know the type, so dont pdp_opencv_edge_process */ + break; + + } + } + +} + +static void pdp_opencv_edge_input_0(t_pdp_opencv_edge *x, t_symbol *s, t_floatarg f) +{ + /* if this is a register_ro message or register_rw message, register with packet factory */ + + if (s == gensym("register_rw")) + x->x_dropped = pdp_packet_convert_ro_or_drop(&x->x_packet0, (int)f, pdp_gensym((char*)"bitmap/rgb/*") ); + + if ((s == gensym("process")) && (-1 != x->x_packet0) && (!x->x_dropped)) + { + /* add the process method and callback to the process queue */ + pdp_opencv_edge_process(x); + } +} + +static void pdp_opencv_edge_free(t_pdp_opencv_edge *x) +{ + int i; + + pdp_queue_finish(x->x_queue_id); + pdp_packet_mark_unused(x->x_packet0); + //cv_freeplugins(x); + + //Destroy cv_images + cvReleaseImage(&x->image); + cvReleaseImage(&x->gray); + cvReleaseImage(&x->edge); + cvReleaseImage(&x->cedge); +} + +t_class *pdp_opencv_edge_class; + + +void *pdp_opencv_edge_new(t_floatarg f) +{ + int i; + + t_pdp_opencv_edge *x = (t_pdp_opencv_edge *)pd_new(pdp_opencv_edge_class); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("edge_thresh")); + + x->x_outlet0 = outlet_new(&x->x_obj, &s_anything); + + x->x_packet0 = -1; + x->x_packet1 = -1; + x->x_queue_id = -1; + + x->x_width = 320; + x->x_height = 240; + x->x_size = x->x_width * x->x_height; + + x->x_infosok = 0; + x->edge_thresh = 1; + + + + + x->image = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 3); + + +// Create the output image + x->cedge = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 3); + + // Convert to grayscale + x->gray = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 1); + x->edge = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 1); + cvCvtColor(x->image, x->gray, CV_BGR2GRAY); + + return (void *)x; +} + + +#ifdef __cplusplus +extern "C" +{ +#endif + + +void pdp_opencv_edge_setup(void) +{ + + post( " pdp_opencv_edge"); + pdp_opencv_edge_class = class_new(gensym("pdp_opencv_edge"), (t_newmethod)pdp_opencv_edge_new, + (t_method)pdp_opencv_edge_free, sizeof(t_pdp_opencv_edge), 0, A_DEFFLOAT, A_NULL); + + class_addmethod(pdp_opencv_edge_class, (t_method)pdp_opencv_edge_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL); + class_addmethod(pdp_opencv_edge_class, (t_method)pdp_opencv_edge_thresh, gensym("edge_thresh"), A_FLOAT, A_NULL ); + + +} + +#ifdef __cplusplus +} +#endif diff --git a/pdp_opencv_floodfill.c b/pdp_opencv_floodfill.c deleted file mode 100644 index c1c6b76..0000000 --- a/pdp_opencv_floodfill.c +++ /dev/null @@ -1,402 +0,0 @@ -/* - * Pure Data Packet module. - * Copyright (c) by Tom Schouten - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include -#include -#include -#include -#include -#include - -#include "pdp.h" - -#ifndef _EiC -#include "cv.h" -#endif - -#define MAX_COMPONENTS 10 - -typedef struct pdp_opencv_floodfill_struct -{ - t_object x_obj; - t_float x_f; - - t_outlet *x_outlet0; - t_outlet *x_outlet1; - t_atom x_list[5]; - int x_packet0; - int x_packet1; - int x_dropped; - int x_queue_id; - - int x_width; - int x_height; - int x_size; - - int x_infosok; - - int x_up; - int x_lo; - int x_connectivity; - int x_color; - - // tracked components - int x_xcomp[MAX_COMPONENTS]; - int x_ycomp[MAX_COMPONENTS]; - - // fill color - int x_r[MAX_COMPONENTS]; - int x_g[MAX_COMPONENTS]; - int x_b[MAX_COMPONENTS]; - - // opencv data - IplImage* color_img; - IplImage* gray_img; - -} t_pdp_opencv_floodfill; - - - -static void pdp_opencv_floodfill_process_rgb(t_pdp_opencv_floodfill *x) -{ - t_pdp *header = pdp_packet_header(x->x_packet0); - short int *data = (short int *)pdp_packet_data(x->x_packet0); - t_pdp *newheader = pdp_packet_header(x->x_packet1); - short int *newdata = (short int *)pdp_packet_data(x->x_packet1); - int i; - CvConnectedComp comp; - int flags = x->x_connectivity + ( 255 << 8 ) + CV_FLOODFILL_FIXED_RANGE; - - if ((x->x_width != (t_int)header->info.image.width) || - (x->x_height != (t_int)header->info.image.height)) - { - - post("pdp_opencv_floodfill :: resizing plugins"); - - x->x_width = header->info.image.width; - x->x_height = header->info.image.height; - x->x_size = x->x_width*x->x_height; - - //Destroy cv_images - cvReleaseImage( &x->color_img ); - cvReleaseImage( &x->gray_img ); - - //Create cv_images - x->color_img = cvCreateImage( cvSize(x->x_width,x->x_height), 8, 3 ); - x->gray_img = cvCreateImage( cvSize(x->x_width, x->x_height), 8, 1 ); - } - - newheader->info.image.encoding = header->info.image.encoding; - newheader->info.image.width = x->x_width; - newheader->info.image.height = x->x_height; - - memcpy( newdata, data, x->x_size*3 ); - memcpy( x->color_img->imageData, data, x->x_size*3 ); - - if ( !x->x_color ) - { - cvCvtColor(x->color_img, x->gray_img, CV_BGR2GRAY); - } - - // mark recognized components - for ( i=0; ix_xcomp[i] != -1 ) - { - if ( x->x_color ) - { - CvPoint seed = cvPoint(x->x_xcomp[i],x->x_ycomp[i]); - CvScalar color = CV_RGB( x->x_r[i], x->x_g[i], x->x_b[i] ); - cvFloodFill( x->color_img, seed, color, CV_RGB( x->x_lo, x->x_lo, x->x_lo ), - CV_RGB( x->x_up, x->x_up, x->x_up ), &comp, flags, NULL ); - } - else - { - CvPoint seed = cvPoint(x->x_xcomp[i],x->x_ycomp[i]); - CvScalar brightness = cvRealScalar((x->x_r[i]*2 + x->x_g[i]*7 + x->x_b[i] + 5)/10); - cvFloodFill( x->gray_img, seed, brightness, cvRealScalar(x->x_lo), - cvRealScalar(x->x_up), &comp, flags, NULL ); - } - SETFLOAT(&x->x_list[0], i); - SETFLOAT(&x->x_list[1], comp.rect.x); - SETFLOAT(&x->x_list[2], comp.rect.y); - SETFLOAT(&x->x_list[3], comp.rect.width); - SETFLOAT(&x->x_list[4], comp.rect.height); - outlet_list( x->x_outlet1, 0, 5, x->x_list ); - } - } - - if ( !x->x_color ) - { - cvCvtColor(x->gray_img, x->color_img, CV_GRAY2RGB); - } - - memcpy( newdata, x->color_img->imageData, x->x_size*3 ); - return; -} - - -static void pdp_opencv_floodfill_sendpacket(t_pdp_opencv_floodfill *x) -{ - /* release the packet */ - pdp_packet_mark_unused(x->x_packet0); - x->x_packet0 = -1; - - /* unregister and propagate if valid dest packet */ - pdp_packet_pass_if_valid(x->x_outlet0, &x->x_packet1); -} - -static void pdp_opencv_floodfill_process(t_pdp_opencv_floodfill *x) -{ - int encoding; - t_pdp *header = 0; - - /* check if image data packets are compatible */ - if ( (header = pdp_packet_header(x->x_packet0)) - && (PDP_BITMAP == header->type)){ - - /* pdp_opencv_floodfill_process inputs and write into active inlet */ - switch(pdp_packet_header(x->x_packet0)->info.image.encoding){ - - case PDP_BITMAP_RGB: - x->x_packet1 = pdp_packet_clone_rw(x->x_packet0); - pdp_queue_add(x, pdp_opencv_floodfill_process_rgb, pdp_opencv_floodfill_sendpacket, &x->x_queue_id); - break; - - default: - /* don't know the type, so dont pdp_opencv_floodfill_process */ - break; - - } - } - -} - -static void pdp_opencv_floodfill_input_0(t_pdp_opencv_floodfill *x, t_symbol *s, t_floatarg f) -{ - /* if this is a register_ro message or register_rw message, register with packet factory */ - - if (s == gensym("register_rw")) - x->x_dropped = pdp_packet_convert_ro_or_drop(&x->x_packet0, (int)f, pdp_gensym("bitmap/rgb/*") ); - - if ((s == gensym("process")) && (-1 != x->x_packet0) && (!x->x_dropped)) - { - /* add the process method and callback to the process queue */ - pdp_opencv_floodfill_process(x); - } -} - -static void pdp_opencv_floodfill_free(t_pdp_opencv_floodfill *x) -{ - int i; - - pdp_queue_finish(x->x_queue_id); - pdp_packet_mark_unused(x->x_packet0); - - //Destroy cv_images - cvReleaseImage( &x->color_img ); - cvReleaseImage( &x->gray_img ); -} - -static void pdp_opencv_floodfill_up_diff(t_pdp_opencv_floodfill *x, t_floatarg fupdiff ) -{ - if ( ( (int)fupdiff >= 0 ) && ( (int)fupdiff <= 255 ) ) - { - x->x_up = (int)fupdiff; - } -} - -static void pdp_opencv_floodfill_lo_diff(t_pdp_opencv_floodfill *x, t_floatarg flodiff ) -{ - if ( ( (int)flodiff >= 0 ) && ( (int)flodiff <= 255 ) ) - { - x->x_lo = (int)flodiff; - } -} - -static void pdp_opencv_floodfill_color(t_pdp_opencv_floodfill *x, t_floatarg fcolor ) -{ - if ( ( (int)fcolor == 0 ) || ( (int)fcolor == 1 ) ) - { - x->x_color = (int)fcolor; - } -} - -static void pdp_opencv_floodfill_fillcolor(t_pdp_opencv_floodfill *x, t_floatarg findex, t_floatarg fr, t_floatarg fg, t_floatarg fb ) -{ - if ( ( (int)findex <= 0 ) || ( (int)findex > MAX_COMPONENTS ) ) - { - post( "pdp_opencv_floodfill : wrong color index : %d", (int)findex ); - return; - } - - if ( ( (int)fr >= 0 ) || ( (int)fr <= 255 ) ) - { - x->x_r[(int)findex-1] = (int)fr; - } - - if ( ( (int)fg >= 0 ) || ( (int)fg <= 255 ) ) - { - x->x_g[(int)findex-1] = (int)fg; - } - - if ( ( (int)fb >= 0 ) || ( (int)fb <= 255 ) ) - { - x->x_b[(int)findex-1] = (int)fb; - } - -} - -static void pdp_opencv_floodfill_mark(t_pdp_opencv_floodfill *x, t_floatarg fperx, t_floatarg fpery ) -{ - int i; - int inserted; - - if ( ( fperx < 0.0 ) || ( fperx > 1.0 ) || ( fpery < 0.0 ) || ( fpery > 1.0 ) ) - { - return; - } - - inserted = 0; - for ( i=0; ix_xcomp[i] == -1 ) - { - x->x_xcomp[i] = (int)(fperx*x->x_width); - x->x_ycomp[i] = (int)(fpery*x->x_height); - // post( "pdp_opencv_floodfill : inserted point (%d,%d)", x->x_xcomp[i], x->x_ycomp[i] ); - inserted = 1; - break; - } - } - if ( !inserted ) - { - post( "pdp_opencv_floodfill : max components reached" ); - } -} - -static void pdp_opencv_floodfill_delete(t_pdp_opencv_floodfill *x, t_floatarg findex ) -{ - int i; - - if ( ( findex < 1.0 ) || ( findex > 10 ) ) - { - return; - } - - x->x_xcomp[(int)findex-1] = -1; - x->x_ycomp[(int)findex-1] = -1; -} - -static void pdp_opencv_floodfill_connectivity(t_pdp_opencv_floodfill *x, t_floatarg fconnectivity ) -{ - int i; - - if ( ( fconnectivity != 4.0 ) && ( fconnectivity != 8.0 ) ) - { - return; - } - - x->x_connectivity = (int)fconnectivity; -} - -static void pdp_opencv_floodfill_clear(t_pdp_opencv_floodfill *x ) -{ - int i; - - for ( i=0; ix_xcomp[i] = -1; - x->x_ycomp[i] = -1; - } -} - -t_class *pdp_opencv_floodfill_class; - -void *pdp_opencv_floodfill_new(t_floatarg f) -{ - int i; - - t_pdp_opencv_floodfill *x = (t_pdp_opencv_floodfill *)pd_new(pdp_opencv_floodfill_class); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("lo_diff")); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("up_diff")); - - x->x_outlet0 = outlet_new(&x->x_obj, &s_anything); - x->x_outlet1 = outlet_new(&x->x_obj, &s_anything); - - x->x_packet0 = -1; - x->x_packet1 = -1; - x->x_queue_id = -1; - - x->x_width = 320; - x->x_height = 240; - x->x_size = x->x_width * x->x_height; - - x->x_infosok = 0; - - x->x_lo = 20; - x->x_up = 20; - x->x_connectivity = 4; - x->x_color = 1; - - for ( i=0; ix_xcomp[i] = -1; - x->x_ycomp[i] = -1; - x->x_r[i] = rand() & 255; - x->x_g[i] = rand() & 255; - x->x_b[i] = rand() & 255; - } - - x->color_img = cvCreateImage( cvSize(x->x_width,x->x_height), 8, 3 ); - x->gray_img = cvCreateImage( cvSize(x->x_width, x->x_height), 8, 1 ); - - return (void *)x; -} - - -#ifdef __cplusplus -extern "C" -{ -#endif - - -void pdp_opencv_floodfill_setup(void) -{ - - post( " pdp_opencv_floodfill"); - pdp_opencv_floodfill_class = class_new(gensym("pdp_opencv_floodfill"), (t_newmethod)pdp_opencv_floodfill_new, - (t_method)pdp_opencv_floodfill_free, sizeof(t_pdp_opencv_floodfill), 0, A_DEFFLOAT, A_NULL); - - class_addmethod(pdp_opencv_floodfill_class, (t_method)pdp_opencv_floodfill_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL); - class_addmethod(pdp_opencv_floodfill_class, (t_method)pdp_opencv_floodfill_color, gensym("color"), A_DEFFLOAT, A_NULL); - class_addmethod(pdp_opencv_floodfill_class, (t_method)pdp_opencv_floodfill_fillcolor, gensym("fillcolor"), A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, A_NULL); - class_addmethod(pdp_opencv_floodfill_class, (t_method)pdp_opencv_floodfill_mark, gensym("mark"), A_DEFFLOAT, A_DEFFLOAT, A_NULL); - class_addmethod(pdp_opencv_floodfill_class, (t_method)pdp_opencv_floodfill_delete, gensym("delete"), A_DEFFLOAT, A_NULL); - class_addmethod(pdp_opencv_floodfill_class, (t_method)pdp_opencv_floodfill_connectivity, gensym("connectivity"), A_DEFFLOAT, A_NULL); - class_addmethod(pdp_opencv_floodfill_class, (t_method)pdp_opencv_floodfill_clear, gensym("clear"), A_NULL); - class_addmethod(pdp_opencv_floodfill_class, (t_method)pdp_opencv_floodfill_up_diff, gensym("up_diff"), A_FLOAT, A_NULL ); - class_addmethod(pdp_opencv_floodfill_class, (t_method)pdp_opencv_floodfill_lo_diff, gensym("lo_diff"), A_FLOAT, A_NULL ); - -} - -#ifdef __cplusplus -} -#endif diff --git a/pdp_opencv_floodfill.cc b/pdp_opencv_floodfill.cc new file mode 100755 index 0000000..2d92a3c --- /dev/null +++ b/pdp_opencv_floodfill.cc @@ -0,0 +1,402 @@ +/* + * Pure Data Packet module. + * Copyright (c) by Tom Schouten + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include + +#include "pdp.h" + +#ifndef _EiC +#include "cv.h" +#endif + +#define MAX_COMPONENTS 10 + +typedef struct pdp_opencv_floodfill_struct +{ + t_object x_obj; + t_float x_f; + + t_outlet *x_outlet0; + t_outlet *x_outlet1; + t_atom x_list[5]; + int x_packet0; + int x_packet1; + int x_dropped; + int x_queue_id; + + int x_width; + int x_height; + int x_size; + + int x_infosok; + + int x_up; + int x_lo; + int x_connectivity; + int x_color; + + // tracked components + int x_xcomp[MAX_COMPONENTS]; + int x_ycomp[MAX_COMPONENTS]; + + // fill color + int x_r[MAX_COMPONENTS]; + int x_g[MAX_COMPONENTS]; + int x_b[MAX_COMPONENTS]; + + // opencv data + IplImage* color_img; + IplImage* gray_img; + +} t_pdp_opencv_floodfill; + + + +static void pdp_opencv_floodfill_process_rgb(t_pdp_opencv_floodfill *x) +{ + t_pdp *header = pdp_packet_header(x->x_packet0); + short int *data = (short int *)pdp_packet_data(x->x_packet0); + t_pdp *newheader = pdp_packet_header(x->x_packet1); + short int *newdata = (short int *)pdp_packet_data(x->x_packet1); + int i; + CvConnectedComp comp; + int flags = x->x_connectivity + ( 255 << 8 ) + CV_FLOODFILL_FIXED_RANGE; + + if ((x->x_width != (t_int)header->info.image.width) || + (x->x_height != (t_int)header->info.image.height)) + { + + post("pdp_opencv_floodfill :: resizing plugins"); + + x->x_width = header->info.image.width; + x->x_height = header->info.image.height; + x->x_size = x->x_width*x->x_height; + + //Destroy cv_images + cvReleaseImage( &x->color_img ); + cvReleaseImage( &x->gray_img ); + + //Create cv_images + x->color_img = cvCreateImage( cvSize(x->x_width,x->x_height), 8, 3 ); + x->gray_img = cvCreateImage( cvSize(x->x_width, x->x_height), 8, 1 ); + } + + newheader->info.image.encoding = header->info.image.encoding; + newheader->info.image.width = x->x_width; + newheader->info.image.height = x->x_height; + + memcpy( newdata, data, x->x_size*3 ); + memcpy( x->color_img->imageData, data, x->x_size*3 ); + + if ( !x->x_color ) + { + cvCvtColor(x->color_img, x->gray_img, CV_BGR2GRAY); + } + + // mark recognized components + for ( i=0; ix_xcomp[i] != -1 ) + { + if ( x->x_color ) + { + CvPoint seed = cvPoint(x->x_xcomp[i],x->x_ycomp[i]); + CvScalar color = CV_RGB( x->x_r[i], x->x_g[i], x->x_b[i] ); + cvFloodFill( x->color_img, seed, color, CV_RGB( x->x_lo, x->x_lo, x->x_lo ), + CV_RGB( x->x_up, x->x_up, x->x_up ), &comp, flags, NULL ); + } + else + { + CvPoint seed = cvPoint(x->x_xcomp[i],x->x_ycomp[i]); + CvScalar brightness = cvRealScalar((x->x_r[i]*2 + x->x_g[i]*7 + x->x_b[i] + 5)/10); + cvFloodFill( x->gray_img, seed, brightness, cvRealScalar(x->x_lo), + cvRealScalar(x->x_up), &comp, flags, NULL ); + } + SETFLOAT(&x->x_list[0], i); + SETFLOAT(&x->x_list[1], comp.rect.x); + SETFLOAT(&x->x_list[2], comp.rect.y); + SETFLOAT(&x->x_list[3], comp.rect.width); + SETFLOAT(&x->x_list[4], comp.rect.height); + outlet_list( x->x_outlet1, 0, 5, x->x_list ); + } + } + + if ( !x->x_color ) + { + cvCvtColor(x->gray_img, x->color_img, CV_GRAY2RGB); + } + + memcpy( newdata, x->color_img->imageData, x->x_size*3 ); + return; +} + + +static void pdp_opencv_floodfill_sendpacket(t_pdp_opencv_floodfill *x) +{ + /* release the packet */ + pdp_packet_mark_unused(x->x_packet0); + x->x_packet0 = -1; + + /* unregister and propagate if valid dest packet */ + pdp_packet_pass_if_valid(x->x_outlet0, &x->x_packet1); +} + +static void pdp_opencv_floodfill_process(t_pdp_opencv_floodfill *x) +{ + int encoding; + t_pdp *header = 0; + + /* check if image data packets are compatible */ + if ( (header = pdp_packet_header(x->x_packet0)) + && (PDP_BITMAP == header->type)){ + + /* pdp_opencv_floodfill_process inputs and write into active inlet */ + switch(pdp_packet_header(x->x_packet0)->info.image.encoding){ + + case PDP_BITMAP_RGB: + x->x_packet1 = pdp_packet_clone_rw(x->x_packet0); + pdp_queue_add(x, (void*)pdp_opencv_floodfill_process_rgb, (void*)pdp_opencv_floodfill_sendpacket, &x->x_queue_id); + break; + + default: + /* don't know the type, so dont pdp_opencv_floodfill_process */ + break; + + } + } + +} + +static void pdp_opencv_floodfill_input_0(t_pdp_opencv_floodfill *x, t_symbol *s, t_floatarg f) +{ + /* if this is a register_ro message or register_rw message, register with packet factory */ + + if (s == gensym("register_rw")) + x->x_dropped = pdp_packet_convert_ro_or_drop(&x->x_packet0, (int)f, pdp_gensym((char*)"bitmap/rgb/*") ); + + if ((s == gensym("process")) && (-1 != x->x_packet0) && (!x->x_dropped)) + { + /* add the process method and callback to the process queue */ + pdp_opencv_floodfill_process(x); + } +} + +static void pdp_opencv_floodfill_free(t_pdp_opencv_floodfill *x) +{ + int i; + + pdp_queue_finish(x->x_queue_id); + pdp_packet_mark_unused(x->x_packet0); + + //Destroy cv_images + cvReleaseImage( &x->color_img ); + cvReleaseImage( &x->gray_img ); +} + +static void pdp_opencv_floodfill_up_diff(t_pdp_opencv_floodfill *x, t_floatarg fupdiff ) +{ + if ( ( (int)fupdiff >= 0 ) && ( (int)fupdiff <= 255 ) ) + { + x->x_up = (int)fupdiff; + } +} + +static void pdp_opencv_floodfill_lo_diff(t_pdp_opencv_floodfill *x, t_floatarg flodiff ) +{ + if ( ( (int)flodiff >= 0 ) && ( (int)flodiff <= 255 ) ) + { + x->x_lo = (int)flodiff; + } +} + +static void pdp_opencv_floodfill_color(t_pdp_opencv_floodfill *x, t_floatarg fcolor ) +{ + if ( ( (int)fcolor == 0 ) || ( (int)fcolor == 1 ) ) + { + x->x_color = (int)fcolor; + } +} + +static void pdp_opencv_floodfill_fillcolor(t_pdp_opencv_floodfill *x, t_floatarg findex, t_floatarg fr, t_floatarg fg, t_floatarg fb ) +{ + if ( ( (int)findex <= 0 ) || ( (int)findex > MAX_COMPONENTS ) ) + { + post( "pdp_opencv_floodfill : wrong color index : %d", (int)findex ); + return; + } + + if ( ( (int)fr >= 0 ) || ( (int)fr <= 255 ) ) + { + x->x_r[(int)findex-1] = (int)fr; + } + + if ( ( (int)fg >= 0 ) || ( (int)fg <= 255 ) ) + { + x->x_g[(int)findex-1] = (int)fg; + } + + if ( ( (int)fb >= 0 ) || ( (int)fb <= 255 ) ) + { + x->x_b[(int)findex-1] = (int)fb; + } + +} + +static void pdp_opencv_floodfill_mark(t_pdp_opencv_floodfill *x, t_floatarg fperx, t_floatarg fpery ) +{ + int i; + int inserted; + + if ( ( fperx < 0.0 ) || ( fperx > 1.0 ) || ( fpery < 0.0 ) || ( fpery > 1.0 ) ) + { + return; + } + + inserted = 0; + for ( i=0; ix_xcomp[i] == -1 ) + { + x->x_xcomp[i] = (int)(fperx*x->x_width); + x->x_ycomp[i] = (int)(fpery*x->x_height); + // post( "pdp_opencv_floodfill : inserted point (%d,%d)", x->x_xcomp[i], x->x_ycomp[i] ); + inserted = 1; + break; + } + } + if ( !inserted ) + { + post( "pdp_opencv_floodfill : max components reached" ); + } +} + +static void pdp_opencv_floodfill_delete(t_pdp_opencv_floodfill *x, t_floatarg findex ) +{ + int i; + + if ( ( findex < 1.0 ) || ( findex > 10 ) ) + { + return; + } + + x->x_xcomp[(int)findex-1] = -1; + x->x_ycomp[(int)findex-1] = -1; +} + +static void pdp_opencv_floodfill_connectivity(t_pdp_opencv_floodfill *x, t_floatarg fconnectivity ) +{ + int i; + + if ( ( fconnectivity != 4.0 ) && ( fconnectivity != 8.0 ) ) + { + return; + } + + x->x_connectivity = (int)fconnectivity; +} + +static void pdp_opencv_floodfill_clear(t_pdp_opencv_floodfill *x ) +{ + int i; + + for ( i=0; ix_xcomp[i] = -1; + x->x_ycomp[i] = -1; + } +} + +t_class *pdp_opencv_floodfill_class; + +void *pdp_opencv_floodfill_new(t_floatarg f) +{ + int i; + + t_pdp_opencv_floodfill *x = (t_pdp_opencv_floodfill *)pd_new(pdp_opencv_floodfill_class); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("lo_diff")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("up_diff")); + + x->x_outlet0 = outlet_new(&x->x_obj, &s_anything); + x->x_outlet1 = outlet_new(&x->x_obj, &s_anything); + + x->x_packet0 = -1; + x->x_packet1 = -1; + x->x_queue_id = -1; + + x->x_width = 320; + x->x_height = 240; + x->x_size = x->x_width * x->x_height; + + x->x_infosok = 0; + + x->x_lo = 20; + x->x_up = 20; + x->x_connectivity = 4; + x->x_color = 1; + + for ( i=0; ix_xcomp[i] = -1; + x->x_ycomp[i] = -1; + x->x_r[i] = rand() & 255; + x->x_g[i] = rand() & 255; + x->x_b[i] = rand() & 255; + } + + x->color_img = cvCreateImage( cvSize(x->x_width,x->x_height), 8, 3 ); + x->gray_img = cvCreateImage( cvSize(x->x_width, x->x_height), 8, 1 ); + + return (void *)x; +} + + +#ifdef __cplusplus +extern "C" +{ +#endif + + +void pdp_opencv_floodfill_setup(void) +{ + + post( " pdp_opencv_floodfill"); + pdp_opencv_floodfill_class = class_new(gensym("pdp_opencv_floodfill"), (t_newmethod)pdp_opencv_floodfill_new, + (t_method)pdp_opencv_floodfill_free, sizeof(t_pdp_opencv_floodfill), 0, A_DEFFLOAT, A_NULL); + + class_addmethod(pdp_opencv_floodfill_class, (t_method)pdp_opencv_floodfill_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL); + class_addmethod(pdp_opencv_floodfill_class, (t_method)pdp_opencv_floodfill_color, gensym("color"), A_DEFFLOAT, A_NULL); + class_addmethod(pdp_opencv_floodfill_class, (t_method)pdp_opencv_floodfill_fillcolor, gensym("fillcolor"), A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, A_NULL); + class_addmethod(pdp_opencv_floodfill_class, (t_method)pdp_opencv_floodfill_mark, gensym("mark"), A_DEFFLOAT, A_DEFFLOAT, A_NULL); + class_addmethod(pdp_opencv_floodfill_class, (t_method)pdp_opencv_floodfill_delete, gensym("delete"), A_DEFFLOAT, A_NULL); + class_addmethod(pdp_opencv_floodfill_class, (t_method)pdp_opencv_floodfill_connectivity, gensym("connectivity"), A_DEFFLOAT, A_NULL); + class_addmethod(pdp_opencv_floodfill_class, (t_method)pdp_opencv_floodfill_clear, gensym("clear"), A_NULL); + class_addmethod(pdp_opencv_floodfill_class, (t_method)pdp_opencv_floodfill_up_diff, gensym("up_diff"), A_FLOAT, A_NULL ); + class_addmethod(pdp_opencv_floodfill_class, (t_method)pdp_opencv_floodfill_lo_diff, gensym("lo_diff"), A_FLOAT, A_NULL ); + +} + +#ifdef __cplusplus +} +#endif diff --git a/pdp_opencv_haarcascade.c b/pdp_opencv_haarcascade.c deleted file mode 100644 index 1c1edc6..0000000 --- a/pdp_opencv_haarcascade.c +++ /dev/null @@ -1,453 +0,0 @@ -/* - * Pure Data Packet module. - * Copyright (c) by Tom Schouten - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "pdp.h" - -#ifndef _EiC -#include "cv.h" -#endif - -#define MAX_MARKERS 50 - -const char* default_cascade ="./haarcascade_frontalface_alt.xml"; - -typedef struct pdp_opencv_haarcascade_struct -{ - t_object x_obj; - t_float x_f; - - t_outlet *x_outlet0; - t_outlet *x_outlet1; - t_outlet *x_dataout; - t_atom rlist[4]; - int x_xmark[MAX_MARKERS]; - int x_ymark[MAX_MARKERS]; - int x_found[MAX_MARKERS]; - int x_ftolerance; - - int x_packet0; - int x_packet1; - int x_dropped; - int x_queue_id; - - int x_width; - int x_height; - int x_size; - - int x_infosok; - - float scale_factor; - int min_neighbors; - int mode; - int min_size; - - IplImage *frame, *img; - CvMemStorage* storage; - CvHaarClassifierCascade* cascade; - CvFont font; - -} t_pdp_opencv_haarcascade; - -static int pdp_opencv_haarcascade_mark(t_pdp_opencv_haarcascade *x, t_floatarg fx, t_floatarg fy ) -{ - int i; - - if ( ( fx < 0.0 ) || ( fx > x->x_width ) || ( fy < 0 ) || ( fy > x->x_height ) ) - { - return -1; - } - - for ( i=0; ix_xmark[i] == -1 ) - { - x->x_xmark[i] = (int)fx; - x->x_ymark[i] = (int)fy; - x->x_found[i] = x->x_ftolerance; - post( "pdp_opencv_haarcascade : inserted point %d (%d,%d)", i, x->x_xmark[i], x->x_ymark[i] ); - return i; - } - } - - post( "pdp_opencv_haarcascade : max markers reached" ); - return -1; -} - -static void pdp_opencv_haarcascade_process_rgb(t_pdp_opencv_haarcascade *x) -{ - t_pdp *header = pdp_packet_header(x->x_packet0); - short int *data = (short int *)pdp_packet_data(x->x_packet0); - t_pdp *newheader = pdp_packet_header(x->x_packet1); - short int *newdata = (short int *)pdp_packet_data(x->x_packet1); - int i, im; - - if ((x->x_width != (t_int)header->info.image.width) || - (x->x_height != (t_int)header->info.image.height)) - { - - post("pdp_opencv_haarcascade :: resizing plugins"); - - x->x_width = header->info.image.width; - x->x_height = header->info.image.height; - x->x_size = x->x_width*x->x_height; - - //Destroy cv_images - cvReleaseImage(&x->frame); - cvReleaseImage(&x->img); - - //create the orig image with new size - x->frame = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 3); - - // Create the output images with new sizes - x->img = cvCreateImage(cvSize(x->frame->width,x->frame->height), IPL_DEPTH_8U, 3); - - } - - newheader->info.image.encoding = header->info.image.encoding; - newheader->info.image.width = x->x_width; - newheader->info.image.height = x->x_height; - - memcpy( newdata, data, x->x_size*3 ); - - memcpy( x->frame->imageData, data, x->x_size*3 ); - - if( x->frame->origin == IPL_ORIGIN_TL ) - cvCopy( x->frame, x->img, 0 ); - else - cvFlip( x->frame, x->img, 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}} - }; - - double scale = 1.3; - IplImage* gray = cvCreateImage( cvSize(x->img->width,x->img->height), 8, 1 ); - IplImage* small_img = cvCreateImage( cvSize( cvRound (x->img->width/scale), - cvRound (x->img->height/scale)), 8, 1 ); - - cvCvtColor( x->img, gray, CV_BGR2GRAY ); - cvResize( gray, small_img, CV_INTER_LINEAR ); - cvEqualizeHist( small_img, small_img ); - cvClearMemStorage( x->storage ); - - if( x->cascade ) - { - double t = (double)cvGetTickCount(); - CvSeq* faces = cvHaarDetectObjects( small_img, x->cascade, x->storage, - x->scale_factor, x->min_neighbors, x->mode, cvSize(x->min_size, x->min_size) ); - //t = (double)cvGetTickCount() - t; - //printf( "detection time = %gms\n", t/((double)cvGetTickFrequency()*1000.) ); - - if ( faces && (faces->total > 0 ) ) - outlet_float(x->x_outlet1, (float)faces->total); - else - outlet_float(x->x_outlet1, 0.0); - - for ( im=0; imx_xmark[im] != -1.0 ) - { - x->x_found[im]--; - } - } - - for( i = 0; i < (faces ? faces->total : 0); i++ ) - { - int oi, found; - - CvRect* r = (CvRect*)cvGetSeqElem( faces, i ); - CvPoint center; - int radius; - center.x = cvRound((r->x + r->width*0.5)*scale); - center.y = cvRound((r->y + r->height*0.5)*scale); - radius = cvRound((r->width + r->height)*0.25*scale); - - found = 0; - oi = -1; - for ( im=0; imx_xmark[im], 2 ) + pow(center.y - x->x_ymark[im], 2 ) ) <= radius ) - { - oi=im; - found=1; - x->x_found[im] = x->x_ftolerance; - x->x_xmark[im] = center.x; - x->x_ymark[im] = center.y; - break; - } - } - // new object detected - if ( !found ) - { - oi = pdp_opencv_haarcascade_mark(x, center.x, center.y ); - } - char tindex[4]; - sprintf( tindex, "%d", oi ); - cvCircle( x->img, center, radius, colors[oi%8], 3, 8, 0 ); - cvPutText( x->img, tindex, center, &x->font, CV_RGB(255,255,255)); - - SETFLOAT(&x->rlist[0], oi); - SETFLOAT(&x->rlist[1], center.x); - SETFLOAT(&x->rlist[2], center.y); - SETFLOAT(&x->rlist[3], radius); - outlet_list( x->x_dataout, 0, 4, x->rlist ); - } - // delete lost objects - for ( im=0; imx_found[im] < 0 ) - { - x->x_xmark[im] = -1.0; - x->x_ymark[im] = -1,0; - x->x_found[im] = x->x_ftolerance; - post( "deleted point %d", im ); - } - } - } - - cvReleaseImage( &gray ); - cvReleaseImage( &small_img ); - cvClearMemStorage( x->storage ); - - memcpy( newdata, x->img->imageData, x->x_size*3 ); - - return; -} - -static void pdp_opencv_haarcascade_scale_factor(t_pdp_opencv_haarcascade *x, t_floatarg f) -{ - if (f>1) x->scale_factor = f; -} - -static void pdp_opencv_haarcascade_min_size(t_pdp_opencv_haarcascade *x, t_floatarg f) -{ - if (f>1) x->min_size = (int)f; -} - -static void pdp_opencv_haarcascade_mode(t_pdp_opencv_haarcascade *x, t_floatarg f) -{ - if ((f==0)||(f==1)) x->mode = (int)f; -} - -static void pdp_opencv_haarcascade_min_neighbors(t_pdp_opencv_haarcascade *x, t_floatarg f) -{ - if (f>=1) x->min_neighbors = (int)f; -} - -static void pdp_opencv_haarcascade_ftolerance(t_pdp_opencv_haarcascade *x, t_floatarg f) -{ - if (f>=1) x->x_ftolerance = (int)f; -} - -static void pdp_opencv_haarcascade_delete(t_pdp_opencv_haarcascade *x, t_floatarg findex ) -{ - int i; - - if ( ( findex < 1.0 ) || ( findex > 10 ) ) - { - return; - } - - x->x_xmark[(int)findex-1] = -1; - x->x_ymark[(int)findex-1] = -1; -} - -static void pdp_opencv_haarcascade_clear(t_pdp_opencv_haarcascade *x ) -{ - int i; - - for ( i=0; ix_xmark[i] = -1; - x->x_ymark[i] = -1; - x->x_found[i] = x->x_ftolerance; - } -} - -static void pdp_opencv_haarcascade_load(t_pdp_opencv_haarcascade *x, t_symbol *filename) -{ - x->cascade = (CvHaarClassifierCascade*)cvLoad( filename->s_name, 0, 0, 0 ); - if( !x->cascade ) - { - post( "pdp_opencv_haarcascade: ERROR: Could not load classifier cascade from %s\n", filename->s_name ); - } else post( "pdp_opencv_haarcascade: Loaded classifier cascade from %s\n", filename->s_name ); -} - -static void pdp_opencv_haarcascade_sendpacket(t_pdp_opencv_haarcascade *x) -{ - /* release the packet */ - pdp_packet_mark_unused(x->x_packet0); - x->x_packet0 = -1; - - /* unregister and propagate if valid dest packet */ - pdp_packet_pass_if_valid(x->x_outlet0, &x->x_packet1); -} - -static void pdp_opencv_haarcascade_process(t_pdp_opencv_haarcascade *x) -{ - int encoding; - t_pdp *header = 0; - - /* check if image data packets are compatible */ - if ( (header = pdp_packet_header(x->x_packet0)) - && (PDP_BITMAP == header->type)){ - - /* pdp_opencv_haarcascade_process inputs and write into active inlet */ - switch(pdp_packet_header(x->x_packet0)->info.image.encoding){ - - case PDP_BITMAP_RGB: - x->x_packet1 = pdp_packet_clone_rw(x->x_packet0); - pdp_queue_add(x, pdp_opencv_haarcascade_process_rgb, pdp_opencv_haarcascade_sendpacket, &x->x_queue_id); - break; - - default: - /* don't know the type, so dont pdp_opencv_haarcascade_process */ - break; - - } - } - -} - -static void pdp_opencv_haarcascade_input_0(t_pdp_opencv_haarcascade *x, t_symbol *s, t_floatarg f) -{ - /* if this is a register_ro message or register_rw message, register with packet factory */ - - if (s == gensym("register_rw")) - x->x_dropped = pdp_packet_convert_ro_or_drop(&x->x_packet0, (int)f, pdp_gensym("bitmap/rgb/*") ); - - if ((s == gensym("process")) && (-1 != x->x_packet0) && (!x->x_dropped)) - { - /* add the process method and callback to the process queue */ - pdp_opencv_haarcascade_process(x); - } -} - -static void pdp_opencv_haarcascade_free(t_pdp_opencv_haarcascade *x) -{ - int i; - - pdp_queue_finish(x->x_queue_id); - pdp_packet_mark_unused(x->x_packet0); - - cvReleaseMemStorage( &x->storage ); - //cvReleaseHaarClassifierCascade(&x->cascade); - cvReleaseImage(&x->frame); - cvReleaseImage(&x->img); -} - -t_class *pdp_opencv_haarcascade_class; - - -void *pdp_opencv_haarcascade_new(t_floatarg f) -{ - int i; - - t_pdp_opencv_haarcascade *x = (t_pdp_opencv_haarcascade *)pd_new(pdp_opencv_haarcascade_class); - - x->x_outlet0 = outlet_new(&x->x_obj, &s_anything); - x->x_outlet1 = outlet_new(&x->x_obj, &s_anything); - x->x_dataout = outlet_new(&x->x_obj, &s_anything); - - x->x_packet0 = -1; - x->x_packet1 = -1; - x->x_queue_id = -1; - - x->x_width = 320; - x->x_height = 240; - x->x_size = x->x_width * x->x_height; - - x->x_infosok = 0; - - x->scale_factor = 1.1; - x->min_neighbors = 2; - x->mode = 0; - x->min_size = 30; - x->x_ftolerance = 5; - - for ( i=0; ix_xmark[i] = -1; - x->x_ymark[i] = -1; - } - - x->cascade = (CvHaarClassifierCascade*)cvLoad( default_cascade, 0, 0, 0 ); - if( !x->cascade ) - { - post( "pdp_opencv_haarcascade : ERROR : Could not load default classifier cascade\n" ); - } else post( "pdp_opencv_haarcascade: Loaded default classifier cascade\n" ); - x->storage = cvCreateMemStorage(0); - - x->frame = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 3); - x->img = cvCreateImage(cvSize(x->frame->width,x->frame->height), IPL_DEPTH_8U, 3); - - // initialize font - cvInitFont( &x->font, CV_FONT_HERSHEY_PLAIN, 1.0, 1.0, 0, 1, 8 ); - - return (void *)x; -} - - -#ifdef __cplusplus -extern "C" -{ -#endif - - -void pdp_opencv_haarcascade_setup(void) -{ - - post( " pdp_opencv_haarcascade"); - pdp_opencv_haarcascade_class = class_new(gensym("pdp_opencv_haarcascade"), (t_newmethod)pdp_opencv_haarcascade_new, - (t_method)pdp_opencv_haarcascade_free, sizeof(t_pdp_opencv_haarcascade), 0, A_DEFFLOAT, A_NULL); - - class_addmethod(pdp_opencv_haarcascade_class, (t_method)pdp_opencv_haarcascade_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL); - class_addmethod(pdp_opencv_haarcascade_class, (t_method)pdp_opencv_haarcascade_load, gensym("load"), A_SYMBOL, A_NULL ); - class_addmethod(pdp_opencv_haarcascade_class, (t_method)pdp_opencv_haarcascade_scale_factor, gensym("scale_factor"), A_FLOAT, A_NULL ); - class_addmethod(pdp_opencv_haarcascade_class, (t_method)pdp_opencv_haarcascade_min_neighbors, gensym("min_neighbors"), A_FLOAT, A_NULL ); - class_addmethod(pdp_opencv_haarcascade_class, (t_method)pdp_opencv_haarcascade_mode, gensym("mode"), A_FLOAT, A_NULL ); - class_addmethod(pdp_opencv_haarcascade_class, (t_method)pdp_opencv_haarcascade_min_size, gensym("min_size"), A_FLOAT, A_NULL ); - class_addmethod(pdp_opencv_haarcascade_class, (t_method)pdp_opencv_haarcascade_ftolerance, gensym("ftolerance"), A_FLOAT, A_NULL ); - class_addmethod(pdp_opencv_haarcascade_class, (t_method)pdp_opencv_haarcascade_clear, gensym("clear"), A_NULL ); -} - -#ifdef __cplusplus -} -#endif - diff --git a/pdp_opencv_haarcascade.cc b/pdp_opencv_haarcascade.cc new file mode 100755 index 0000000..cafc2fb --- /dev/null +++ b/pdp_opencv_haarcascade.cc @@ -0,0 +1,453 @@ +/* + * Pure Data Packet module. + * Copyright (c) by Tom Schouten + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pdp.h" + +#ifndef _EiC +#include "cv.h" +#endif + +#define MAX_MARKERS 50 + +const char* default_cascade ="./haarcascade_frontalface_alt.xml"; + +typedef struct pdp_opencv_haarcascade_struct +{ + t_object x_obj; + t_float x_f; + + t_outlet *x_outlet0; + t_outlet *x_outlet1; + t_outlet *x_dataout; + t_atom rlist[4]; + int x_xmark[MAX_MARKERS]; + int x_ymark[MAX_MARKERS]; + int x_found[MAX_MARKERS]; + int x_ftolerance; + + int x_packet0; + int x_packet1; + int x_dropped; + int x_queue_id; + + int x_width; + int x_height; + int x_size; + + int x_infosok; + + float scale_factor; + int min_neighbors; + int mode; + int min_size; + + IplImage *frame, *img; + CvMemStorage* storage; + CvHaarClassifierCascade* cascade; + CvFont font; + +} t_pdp_opencv_haarcascade; + +static int pdp_opencv_haarcascade_mark(t_pdp_opencv_haarcascade *x, t_floatarg fx, t_floatarg fy ) +{ + int i; + + if ( ( fx < 0.0 ) || ( fx > x->x_width ) || ( fy < 0 ) || ( fy > x->x_height ) ) + { + return -1; + } + + for ( i=0; ix_xmark[i] == -1 ) + { + x->x_xmark[i] = (int)fx; + x->x_ymark[i] = (int)fy; + x->x_found[i] = x->x_ftolerance; + post( "pdp_opencv_haarcascade : inserted point %d (%d,%d)", i, x->x_xmark[i], x->x_ymark[i] ); + return i; + } + } + + post( "pdp_opencv_haarcascade : max markers reached" ); + return -1; +} + +static void pdp_opencv_haarcascade_process_rgb(t_pdp_opencv_haarcascade *x) +{ + t_pdp *header = pdp_packet_header(x->x_packet0); + short int *data = (short int *)pdp_packet_data(x->x_packet0); + t_pdp *newheader = pdp_packet_header(x->x_packet1); + short int *newdata = (short int *)pdp_packet_data(x->x_packet1); + int i, im; + + if ((x->x_width != (t_int)header->info.image.width) || + (x->x_height != (t_int)header->info.image.height)) + { + + post("pdp_opencv_haarcascade :: resizing plugins"); + + x->x_width = header->info.image.width; + x->x_height = header->info.image.height; + x->x_size = x->x_width*x->x_height; + + //Destroy cv_images + cvReleaseImage(&x->frame); + cvReleaseImage(&x->img); + + //create the orig image with new size + x->frame = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 3); + + // Create the output images with new sizes + x->img = cvCreateImage(cvSize(x->frame->width,x->frame->height), IPL_DEPTH_8U, 3); + + } + + newheader->info.image.encoding = header->info.image.encoding; + newheader->info.image.width = x->x_width; + newheader->info.image.height = x->x_height; + + memcpy( newdata, data, x->x_size*3 ); + + memcpy( x->frame->imageData, data, x->x_size*3 ); + + if( x->frame->origin == IPL_ORIGIN_TL ) + cvCopy( x->frame, x->img, 0 ); + else + cvFlip( x->frame, x->img, 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}} + }; + + double scale = 1.3; + IplImage* gray = cvCreateImage( cvSize(x->img->width,x->img->height), 8, 1 ); + IplImage* small_img = cvCreateImage( cvSize( cvRound (x->img->width/scale), + cvRound (x->img->height/scale)), 8, 1 ); + + cvCvtColor( x->img, gray, CV_BGR2GRAY ); + cvResize( gray, small_img, CV_INTER_LINEAR ); + cvEqualizeHist( small_img, small_img ); + cvClearMemStorage( x->storage ); + + if( x->cascade ) + { + double t = (double)cvGetTickCount(); + CvSeq* faces = cvHaarDetectObjects( small_img, x->cascade, x->storage, + x->scale_factor, x->min_neighbors, x->mode, cvSize(x->min_size, x->min_size) ); + //t = (double)cvGetTickCount() - t; + //printf( "detection time = %gms\n", t/((double)cvGetTickFrequency()*1000.) ); + + if ( faces && (faces->total > 0 ) ) + outlet_float(x->x_outlet1, (float)faces->total); + else + outlet_float(x->x_outlet1, 0.0); + + for ( im=0; imx_xmark[im] != -1.0 ) + { + x->x_found[im]--; + } + } + + for( i = 0; i < (faces ? faces->total : 0); i++ ) + { + int oi, found; + + CvRect* r = (CvRect*)cvGetSeqElem( faces, i ); + CvPoint center; + int radius; + center.x = cvRound((r->x + r->width*0.5)*scale); + center.y = cvRound((r->y + r->height*0.5)*scale); + radius = cvRound((r->width + r->height)*0.25*scale); + + found = 0; + oi = -1; + for ( im=0; imx_xmark[im], 2 ) + pow(center.y - x->x_ymark[im], 2 ) ) <= radius ) + { + oi=im; + found=1; + x->x_found[im] = x->x_ftolerance; + x->x_xmark[im] = center.x; + x->x_ymark[im] = center.y; + break; + } + } + // new object detected + if ( !found ) + { + oi = pdp_opencv_haarcascade_mark(x, center.x, center.y ); + } + char tindex[4]; + sprintf( tindex, "%d", oi ); + cvCircle( x->img, center, radius, colors[oi%8], 3, 8, 0 ); + cvPutText( x->img, tindex, center, &x->font, CV_RGB(255,255,255)); + + SETFLOAT(&x->rlist[0], oi); + SETFLOAT(&x->rlist[1], center.x); + SETFLOAT(&x->rlist[2], center.y); + SETFLOAT(&x->rlist[3], radius); + outlet_list( x->x_dataout, 0, 4, x->rlist ); + } + // delete lost objects + for ( im=0; imx_found[im] < 0 ) + { + x->x_xmark[im] = -1.0; + x->x_ymark[im] = -1,0; + x->x_found[im] = x->x_ftolerance; + post( "deleted point %d", im ); + } + } + } + + cvReleaseImage( &gray ); + cvReleaseImage( &small_img ); + cvClearMemStorage( x->storage ); + + memcpy( newdata, x->img->imageData, x->x_size*3 ); + + return; +} + +static void pdp_opencv_haarcascade_scale_factor(t_pdp_opencv_haarcascade *x, t_floatarg f) +{ + if (f>1) x->scale_factor = f; +} + +static void pdp_opencv_haarcascade_min_size(t_pdp_opencv_haarcascade *x, t_floatarg f) +{ + if (f>1) x->min_size = (int)f; +} + +static void pdp_opencv_haarcascade_mode(t_pdp_opencv_haarcascade *x, t_floatarg f) +{ + if ((f==0)||(f==1)) x->mode = (int)f; +} + +static void pdp_opencv_haarcascade_min_neighbors(t_pdp_opencv_haarcascade *x, t_floatarg f) +{ + if (f>=1) x->min_neighbors = (int)f; +} + +static void pdp_opencv_haarcascade_ftolerance(t_pdp_opencv_haarcascade *x, t_floatarg f) +{ + if (f>=1) x->x_ftolerance = (int)f; +} + +static void pdp_opencv_haarcascade_delete(t_pdp_opencv_haarcascade *x, t_floatarg findex ) +{ + int i; + + if ( ( findex < 1.0 ) || ( findex > 10 ) ) + { + return; + } + + x->x_xmark[(int)findex-1] = -1; + x->x_ymark[(int)findex-1] = -1; +} + +static void pdp_opencv_haarcascade_clear(t_pdp_opencv_haarcascade *x ) +{ + int i; + + for ( i=0; ix_xmark[i] = -1; + x->x_ymark[i] = -1; + x->x_found[i] = x->x_ftolerance; + } +} + +static void pdp_opencv_haarcascade_load(t_pdp_opencv_haarcascade *x, t_symbol *filename) +{ + x->cascade = (CvHaarClassifierCascade*)cvLoad( filename->s_name, 0, 0, 0 ); + if( !x->cascade ) + { + post( "pdp_opencv_haarcascade: ERROR: Could not load classifier cascade from %s\n", filename->s_name ); + } else post( "pdp_opencv_haarcascade: Loaded classifier cascade from %s\n", filename->s_name ); +} + +static void pdp_opencv_haarcascade_sendpacket(t_pdp_opencv_haarcascade *x) +{ + /* release the packet */ + pdp_packet_mark_unused(x->x_packet0); + x->x_packet0 = -1; + + /* unregister and propagate if valid dest packet */ + pdp_packet_pass_if_valid(x->x_outlet0, &x->x_packet1); +} + +static void pdp_opencv_haarcascade_process(t_pdp_opencv_haarcascade *x) +{ + int encoding; + t_pdp *header = 0; + + /* check if image data packets are compatible */ + if ( (header = pdp_packet_header(x->x_packet0)) + && (PDP_BITMAP == header->type)){ + + /* pdp_opencv_haarcascade_process inputs and write into active inlet */ + switch(pdp_packet_header(x->x_packet0)->info.image.encoding){ + + case PDP_BITMAP_RGB: + x->x_packet1 = pdp_packet_clone_rw(x->x_packet0); + pdp_queue_add(x, (void*)pdp_opencv_haarcascade_process_rgb, (void*)pdp_opencv_haarcascade_sendpacket, &x->x_queue_id); + break; + + default: + /* don't know the type, so dont pdp_opencv_haarcascade_process */ + break; + + } + } + +} + +static void pdp_opencv_haarcascade_input_0(t_pdp_opencv_haarcascade *x, t_symbol *s, t_floatarg f) +{ + /* if this is a register_ro message or register_rw message, register with packet factory */ + + if (s == gensym("register_rw")) + x->x_dropped = pdp_packet_convert_ro_or_drop(&x->x_packet0, (int)f, pdp_gensym((char*)"bitmap/rgb/*") ); + + if ((s == gensym("process")) && (-1 != x->x_packet0) && (!x->x_dropped)) + { + /* add the process method and callback to the process queue */ + pdp_opencv_haarcascade_process(x); + } +} + +static void pdp_opencv_haarcascade_free(t_pdp_opencv_haarcascade *x) +{ + int i; + + pdp_queue_finish(x->x_queue_id); + pdp_packet_mark_unused(x->x_packet0); + + cvReleaseMemStorage( &x->storage ); + //cvReleaseHaarClassifierCascade(&x->cascade); + cvReleaseImage(&x->frame); + cvReleaseImage(&x->img); +} + +t_class *pdp_opencv_haarcascade_class; + + +void *pdp_opencv_haarcascade_new(t_floatarg f) +{ + int i; + + t_pdp_opencv_haarcascade *x = (t_pdp_opencv_haarcascade *)pd_new(pdp_opencv_haarcascade_class); + + x->x_outlet0 = outlet_new(&x->x_obj, &s_anything); + x->x_outlet1 = outlet_new(&x->x_obj, &s_anything); + x->x_dataout = outlet_new(&x->x_obj, &s_anything); + + x->x_packet0 = -1; + x->x_packet1 = -1; + x->x_queue_id = -1; + + x->x_width = 320; + x->x_height = 240; + x->x_size = x->x_width * x->x_height; + + x->x_infosok = 0; + + x->scale_factor = 1.1; + x->min_neighbors = 2; + x->mode = 0; + x->min_size = 30; + x->x_ftolerance = 5; + + for ( i=0; ix_xmark[i] = -1; + x->x_ymark[i] = -1; + } + + x->cascade = (CvHaarClassifierCascade*)cvLoad( default_cascade, 0, 0, 0 ); + if( !x->cascade ) + { + post( "pdp_opencv_haarcascade : ERROR : Could not load default classifier cascade\n" ); + } else post( "pdp_opencv_haarcascade: Loaded default classifier cascade\n" ); + x->storage = cvCreateMemStorage(0); + + x->frame = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 3); + x->img = cvCreateImage(cvSize(x->frame->width,x->frame->height), IPL_DEPTH_8U, 3); + + // initialize font + cvInitFont( &x->font, CV_FONT_HERSHEY_PLAIN, 1.0, 1.0, 0, 1, 8 ); + + return (void *)x; +} + + +#ifdef __cplusplus +extern "C" +{ +#endif + + +void pdp_opencv_haarcascade_setup(void) +{ + + post( " pdp_opencv_haarcascade"); + pdp_opencv_haarcascade_class = class_new(gensym("pdp_opencv_haarcascade"), (t_newmethod)pdp_opencv_haarcascade_new, + (t_method)pdp_opencv_haarcascade_free, sizeof(t_pdp_opencv_haarcascade), 0, A_DEFFLOAT, A_NULL); + + class_addmethod(pdp_opencv_haarcascade_class, (t_method)pdp_opencv_haarcascade_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL); + class_addmethod(pdp_opencv_haarcascade_class, (t_method)pdp_opencv_haarcascade_load, gensym("load"), A_SYMBOL, A_NULL ); + class_addmethod(pdp_opencv_haarcascade_class, (t_method)pdp_opencv_haarcascade_scale_factor, gensym("scale_factor"), A_FLOAT, A_NULL ); + class_addmethod(pdp_opencv_haarcascade_class, (t_method)pdp_opencv_haarcascade_min_neighbors, gensym("min_neighbors"), A_FLOAT, A_NULL ); + class_addmethod(pdp_opencv_haarcascade_class, (t_method)pdp_opencv_haarcascade_mode, gensym("mode"), A_FLOAT, A_NULL ); + class_addmethod(pdp_opencv_haarcascade_class, (t_method)pdp_opencv_haarcascade_min_size, gensym("min_size"), A_FLOAT, A_NULL ); + class_addmethod(pdp_opencv_haarcascade_class, (t_method)pdp_opencv_haarcascade_ftolerance, gensym("ftolerance"), A_FLOAT, A_NULL ); + class_addmethod(pdp_opencv_haarcascade_class, (t_method)pdp_opencv_haarcascade_clear, gensym("clear"), A_NULL ); +} + +#ifdef __cplusplus +} +#endif + diff --git a/pdp_opencv_hist_compare.c b/pdp_opencv_hist_compare.c deleted file mode 100644 index e08c7be..0000000 --- a/pdp_opencv_hist_compare.c +++ /dev/null @@ -1,401 +0,0 @@ -/* - * Pure Data Packet module. - * Copyright (c) by Tom Schouten - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include -#include -#include -#include -#include -#include - -#include "pdp.h" - -#ifndef _EiC -#include "cv.h" -#endif - - -#define MAX_HISTOGRAMS_TO_COMPARE 80 - -typedef struct pdp_opencv_hist_compare_struct -{ - t_object x_obj; - t_float x_f; - - t_outlet *x_outlet0; - t_outlet *x_outlet1; - t_outlet *x_dataout; - int x_packet0; - int x_packet1; - int x_dropped; - int x_queue_id; - - int x_width; - int x_height; - int x_size; - - int x_infosok; - - int save_now; - int nbsaved; - - CvHistogram *hist; - CvHistogram *saved_hist[MAX_HISTOGRAMS_TO_COMPARE]; - IplImage *src, *hsv, *h_plane, *s_plane, *v_plane, *h_saved_plane, *s_saved_plane, *v_saved_plane, *planes[2],*saved_planes[2]; - - -} t_pdp_opencv_hist_compare; - - - -static void pdp_opencv_hist_compare_process_rgb(t_pdp_opencv_hist_compare *x) -{ - t_pdp *header = pdp_packet_header(x->x_packet0); - short int *data = (short int *)pdp_packet_data(x->x_packet0); - t_pdp *newheader = pdp_packet_header(x->x_packet1); - short int *newdata = (short int *)pdp_packet_data(x->x_packet1); - - int h_bins = (int)(x->x_width/10), s_bins = (int)(x->x_height/10); - - if ((x->x_width != (t_int)header->info.image.width) || - (x->x_height != (t_int)header->info.image.height)) - { - - // if image size has changed we must create again our image and histogram structures - post("pdp_opencv_hist_compare :: resizing buffers"); - - x->x_width = header->info.image.width; - x->x_height = header->info.image.height; - x->x_size = x->x_width*x->x_height; - - //Destroy cv_images - cvReleaseImage(&x->src); - cvReleaseImage(&x->hsv); - cvReleaseImage(&x->h_plane); - cvReleaseImage(&x->s_plane); - cvReleaseImage(&x->v_plane); - cvReleaseImage(&x->h_saved_plane); - cvReleaseImage(&x->s_saved_plane); - cvReleaseImage(&x->v_saved_plane); - - //create the orig image with new size - x->src = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 3); - - // Create the output images with new sizes - x->hsv = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 3 ); - - x->h_plane = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 1); - x->s_plane = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 1); - x->v_plane = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 1); - x->planes[0] = x->h_plane; - x->planes[1] = x->s_plane; - x->h_saved_plane = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 1); - x->s_saved_plane = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 1); - x->v_saved_plane = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 1); - x->saved_planes[0] = x->h_saved_plane; - x->saved_planes[1] = x->s_saved_plane; - { - int hist_size[] = { h_bins, s_bins }; - float h_ranges[] = { 0, 180 }; // hue is [0,180] - float s_ranges[] = { 0, 255 }; - float* ranges[] = { h_ranges, s_ranges }; - x->hist = cvCreateHist( - 2, - hist_size, - CV_HIST_ARRAY, - ranges, - 1 - ); - int n; - for (n=0; nsaved_hist[n] = cvCreateHist( - 2, - hist_size, - CV_HIST_ARRAY, - ranges, - 1 - ); - } - } - - } - - newheader->info.image.encoding = header->info.image.encoding; - newheader->info.image.width = x->x_width; - newheader->info.image.height = x->x_height; - - memcpy( newdata, data, x->x_size*3 ); - - - // We make here a copy of the PDP packet in image->imageData ... - // take a look on the IplImage data structure - // http://www.cs.iit.edu/~agam/cs512/lect-notes/opencv-intro/opencv-intro.html - memcpy( x->src->imageData, data, x->x_size*3 ); - - // Convert to grayscale - cvCvtColor( x->src, x->hsv, CV_BGR2HSV ); - cvCvtPixToPlane( x->hsv, x->h_plane, x->s_plane, x->v_plane, 0 ); - - // Build the histogram and compute its contents. - if (x->save_now>=0) { - fprintf(stderr,"saving histogram %d\n",x->save_now); - cvCvtPixToPlane( x->hsv, x->h_saved_plane, x->s_saved_plane, x->v_saved_plane, 0 ); - cvCalcHist( x->saved_planes, x->saved_hist[x->save_now], 0, 0 ); //Compute histogram - cvNormalizeHist( x->saved_hist[x->save_now], 1.0 ); //Normalize it - x->nbsaved++; - x->save_now=-1; - } - cvCalcHist( x->planes, x->hist, 0, 0 ); //Compute histogram - cvNormalizeHist( x->hist, 1.0 ); //Normalize it - - double tato[x->nbsaved]; - t_atom datalist[x->nbsaved]; - int nearest = -1; - double max = 0; - - int n; - if ( x->nbsaved > 0 ) - for (n=0; nnbsaved; n++) { - tato[n] = cvCompareHist(x->hist, x->saved_hist[n], CV_COMP_INTERSECT); - SETFLOAT(&datalist[n], tato[n]); - if (tato[n]>max) { - max = tato[n]; - nearest = n; - } - } - - if ( x->nbsaved > 0 ) { - outlet_float(x->x_outlet1, (float)nearest); - outlet_list( x->x_dataout, 0, x->nbsaved, datalist ); - } else - outlet_float(x->x_outlet1, -1.0); - - - // Create an image to use to visualize our histogram. - int scale = 10; - //IplImage* hist_img = cvCreateImage( - // cvSize(x->x_width,x->x_height), - // 8, - // 3 - //); - //cvZero( hist_img ); - - // populate our visualization with little gray squares. - - float max_value = 0; - cvGetMinMaxHistValue( x->hist, 0, &max_value, 0, 0 ); - - int h = 0; - int s = 0; - - for( h = 0; h < h_bins; h++ ) { - for( s = 0; s < s_bins; s++ ) { - float bin_val = cvQueryHistValue_2D( x->hist, h, s ); - int intensity = cvRound( bin_val * 255 / max_value ); - cvRectangle( - x->src, - cvPoint( h*scale, s*scale ), - cvPoint( (h+1)*scale - 1, (s+1)*scale - 1), - CV_RGB(intensity,intensity,intensity), CV_FILLED, 8 , 0 ); - } - } - - //memory copy again, now from x->cedge->imageData to the new data pdp packet - //memcpy( newdata, hist_img, x->x_size*3 ); - memcpy( newdata, x->src->imageData, x->x_size*3 ); - - return; -} - -static void pdp_opencv_hist_compare_save(t_pdp_opencv_hist_compare *x, t_floatarg f) -{ - if (((int)f>=0)&&((int)fsave_now = (int)f; -} - -static void pdp_opencv_hist_compare_sendpacket(t_pdp_opencv_hist_compare *x) -{ - /* release the packet */ - pdp_packet_mark_unused(x->x_packet0); - x->x_packet0 = -1; - - /* unregister and propagate if valid dest packet */ - pdp_packet_pass_if_valid(x->x_outlet0, &x->x_packet1); -} - -static void pdp_opencv_hist_compare_process(t_pdp_opencv_hist_compare *x) -{ - int encoding; - t_pdp *header = 0; - char *parname; - unsigned pi; - int partype; - float pardefault; - t_atom plist[2]; - t_atom tlist[2]; - t_atom vlist[2]; - - /* check if image data packets are compatible */ - if ( (header = pdp_packet_header(x->x_packet0)) - && (PDP_BITMAP == header->type)){ - - /* pdp_opencv_hist_compare_process inputs and write into active inlet */ - switch(pdp_packet_header(x->x_packet0)->info.image.encoding){ - - case PDP_BITMAP_RGB: - x->x_packet1 = pdp_packet_clone_rw(x->x_packet0); - pdp_queue_add(x, pdp_opencv_hist_compare_process_rgb, pdp_opencv_hist_compare_sendpacket, &x->x_queue_id); - break; - - default: - /* don't know the type, so dont pdp_opencv_hist_compare_process */ - break; - - } - } - -} - -static void pdp_opencv_hist_compare_input_0(t_pdp_opencv_hist_compare *x, t_symbol *s, t_floatarg f) -{ - /* if this is a register_ro message or register_rw message, register with packet factory */ - - if (s == gensym("register_rw")) - x->x_dropped = pdp_packet_convert_ro_or_drop(&x->x_packet0, (int)f, pdp_gensym("bitmap/rgb/*") ); - - if ((s == gensym("process")) && (-1 != x->x_packet0) && (!x->x_dropped)) - { - /* add the process method and callback to the process queue */ - pdp_opencv_hist_compare_process(x); - } -} - -static void pdp_opencv_hist_compare_free(t_pdp_opencv_hist_compare *x) -{ - int i; - - pdp_queue_finish(x->x_queue_id); - pdp_packet_mark_unused(x->x_packet0); - //cv_freeplugins(x); - - //Destroy cv_images - cvReleaseImage(&x->src); - cvReleaseImage(&x->hsv); - cvReleaseImage(&x->h_plane); - cvReleaseImage(&x->s_plane); - cvReleaseImage(&x->v_plane); - cvReleaseImage(&x->h_saved_plane); - cvReleaseImage(&x->s_saved_plane); - cvReleaseImage(&x->v_saved_plane); -} - -t_class *pdp_opencv_hist_compare_class; - - -void *pdp_opencv_hist_compare_new(t_floatarg f) -{ - int i; - - t_pdp_opencv_hist_compare *x = (t_pdp_opencv_hist_compare *)pd_new(pdp_opencv_hist_compare_class); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("save")); - - x->x_outlet0 = outlet_new(&x->x_obj, &s_anything); - x->x_outlet1 = outlet_new(&x->x_obj, &s_float); - x->x_dataout = outlet_new(&x->x_obj, &s_anything); - - x->x_packet0 = -1; - x->x_packet1 = -1; - x->x_queue_id = -1; - - x->x_width = 320; - x->x_height = 240; - x->x_size = x->x_width * x->x_height; - - x->x_infosok = 0; - x->save_now = 0; - x->nbsaved = 0; - - x->src = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 3); - x->hsv = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 3 ); - - x->h_plane = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 1); - x->s_plane = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 1); - x->v_plane = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 1); - x->planes[0] = x->h_plane; - x->planes[1] = x->s_plane; - cvCvtPixToPlane( x->hsv, x->h_plane, x->s_plane, x->v_plane, 0 ); - x->h_saved_plane = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 1); - x->s_saved_plane = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 1); - x->v_saved_plane = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 1); - x->saved_planes[0] = x->h_saved_plane; - x->saved_planes[1] = x->s_saved_plane; - cvCvtPixToPlane( x->hsv, x->h_saved_plane, x->s_saved_plane, x->v_saved_plane, 0 ); - - cvCvtColor( x->src, x->hsv, CV_BGR2HSV ); - - int h_bins = (int)(x->x_width/10), s_bins = (int)(x->x_height/10); - { - int hist_size[] = { h_bins, s_bins }; - float h_ranges[] = { 0, 180 }; // hue is [0,180] - float s_ranges[] = { 0, 255 }; - float* ranges[] = { h_ranges, s_ranges }; - x->hist = cvCreateHist( - 2, - hist_size, - CV_HIST_ARRAY, - ranges, - 1 - ); - int n; - for (n=0; nsaved_hist[n] = cvCreateHist( - 2, - hist_size, - CV_HIST_ARRAY, - ranges, - 1 - ); - } - } - - return (void *)x; -} - - -#ifdef __cplusplus -extern "C" -{ -#endif - - -void pdp_opencv_hist_compare_setup(void) -{ - - post( " pdp_opencv_hist_compare"); - pdp_opencv_hist_compare_class = class_new(gensym("pdp_opencv_hist_compare"), (t_newmethod)pdp_opencv_hist_compare_new, - (t_method)pdp_opencv_hist_compare_free, sizeof(t_pdp_opencv_hist_compare), 0, A_DEFFLOAT, A_NULL); - - class_addmethod(pdp_opencv_hist_compare_class, (t_method)pdp_opencv_hist_compare_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL); - class_addmethod(pdp_opencv_hist_compare_class, (t_method)pdp_opencv_hist_compare_save, gensym("save"), A_FLOAT, A_NULL ); - -} - -#ifdef __cplusplus -} -#endif diff --git a/pdp_opencv_hist_compare.cc b/pdp_opencv_hist_compare.cc new file mode 100755 index 0000000..9a68e9a --- /dev/null +++ b/pdp_opencv_hist_compare.cc @@ -0,0 +1,401 @@ +/* + * Pure Data Packet module. + * Copyright (c) by Tom Schouten + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include + +#include "pdp.h" + +#ifndef _EiC +#include "cv.h" +#endif + + +#define MAX_HISTOGRAMS_TO_COMPARE 80 + +typedef struct pdp_opencv_hist_compare_struct +{ + t_object x_obj; + t_float x_f; + + t_outlet *x_outlet0; + t_outlet *x_outlet1; + t_outlet *x_dataout; + int x_packet0; + int x_packet1; + int x_dropped; + int x_queue_id; + + int x_width; + int x_height; + int x_size; + + int x_infosok; + + int save_now; + int nbsaved; + + CvHistogram *hist; + CvHistogram *saved_hist[MAX_HISTOGRAMS_TO_COMPARE]; + IplImage *src, *hsv, *h_plane, *s_plane, *v_plane, *h_saved_plane, *s_saved_plane, *v_saved_plane, *planes[2],*saved_planes[2]; + + +} t_pdp_opencv_hist_compare; + + + +static void pdp_opencv_hist_compare_process_rgb(t_pdp_opencv_hist_compare *x) +{ + t_pdp *header = pdp_packet_header(x->x_packet0); + short int *data = (short int *)pdp_packet_data(x->x_packet0); + t_pdp *newheader = pdp_packet_header(x->x_packet1); + short int *newdata = (short int *)pdp_packet_data(x->x_packet1); + + int h_bins = (int)(x->x_width/10), s_bins = (int)(x->x_height/10); + + if ((x->x_width != (t_int)header->info.image.width) || + (x->x_height != (t_int)header->info.image.height)) + { + + // if image size has changed we must create again our image and histogram structures + post("pdp_opencv_hist_compare :: resizing buffers"); + + x->x_width = header->info.image.width; + x->x_height = header->info.image.height; + x->x_size = x->x_width*x->x_height; + + //Destroy cv_images + cvReleaseImage(&x->src); + cvReleaseImage(&x->hsv); + cvReleaseImage(&x->h_plane); + cvReleaseImage(&x->s_plane); + cvReleaseImage(&x->v_plane); + cvReleaseImage(&x->h_saved_plane); + cvReleaseImage(&x->s_saved_plane); + cvReleaseImage(&x->v_saved_plane); + + //create the orig image with new size + x->src = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 3); + + // Create the output images with new sizes + x->hsv = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 3 ); + + x->h_plane = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 1); + x->s_plane = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 1); + x->v_plane = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 1); + x->planes[0] = x->h_plane; + x->planes[1] = x->s_plane; + x->h_saved_plane = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 1); + x->s_saved_plane = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 1); + x->v_saved_plane = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 1); + x->saved_planes[0] = x->h_saved_plane; + x->saved_planes[1] = x->s_saved_plane; + { + int hist_size[] = { h_bins, s_bins }; + float h_ranges[] = { 0, 180 }; // hue is [0,180] + float s_ranges[] = { 0, 255 }; + float* ranges[] = { h_ranges, s_ranges }; + x->hist = cvCreateHist( + 2, + hist_size, + CV_HIST_ARRAY, + ranges, + 1 + ); + int n; + for (n=0; nsaved_hist[n] = cvCreateHist( + 2, + hist_size, + CV_HIST_ARRAY, + ranges, + 1 + ); + } + } + + } + + newheader->info.image.encoding = header->info.image.encoding; + newheader->info.image.width = x->x_width; + newheader->info.image.height = x->x_height; + + memcpy( newdata, data, x->x_size*3 ); + + + // We make here a copy of the PDP packet in image->imageData ... + // take a look on the IplImage data structure + // http://www.cs.iit.edu/~agam/cs512/lect-notes/opencv-intro/opencv-intro.html + memcpy( x->src->imageData, data, x->x_size*3 ); + + // Convert to grayscale + cvCvtColor( x->src, x->hsv, CV_BGR2HSV ); + cvCvtPixToPlane( x->hsv, x->h_plane, x->s_plane, x->v_plane, 0 ); + + // Build the histogram and compute its contents. + if (x->save_now>=0) { + fprintf(stderr,"saving histogram %d\n",x->save_now); + cvCvtPixToPlane( x->hsv, x->h_saved_plane, x->s_saved_plane, x->v_saved_plane, 0 ); + cvCalcHist( x->saved_planes, x->saved_hist[x->save_now], 0, 0 ); //Compute histogram + cvNormalizeHist( x->saved_hist[x->save_now], 1.0 ); //Normalize it + x->nbsaved++; + x->save_now=-1; + } + cvCalcHist( x->planes, x->hist, 0, 0 ); //Compute histogram + cvNormalizeHist( x->hist, 1.0 ); //Normalize it + + double tato[x->nbsaved]; + t_atom datalist[x->nbsaved]; + int nearest = -1; + double max = 0; + + int n; + if ( x->nbsaved > 0 ) + for (n=0; nnbsaved; n++) { + tato[n] = cvCompareHist(x->hist, x->saved_hist[n], CV_COMP_INTERSECT); + SETFLOAT(&datalist[n], tato[n]); + if (tato[n]>max) { + max = tato[n]; + nearest = n; + } + } + + if ( x->nbsaved > 0 ) { + outlet_float(x->x_outlet1, (float)nearest); + outlet_list( x->x_dataout, 0, x->nbsaved, datalist ); + } else + outlet_float(x->x_outlet1, -1.0); + + + // Create an image to use to visualize our histogram. + int scale = 10; + //IplImage* hist_img = cvCreateImage( + // cvSize(x->x_width,x->x_height), + // 8, + // 3 + //); + //cvZero( hist_img ); + + // populate our visualization with little gray squares. + + float max_value = 0; + cvGetMinMaxHistValue( x->hist, 0, &max_value, 0, 0 ); + + int h = 0; + int s = 0; + + for( h = 0; h < h_bins; h++ ) { + for( s = 0; s < s_bins; s++ ) { + float bin_val = cvQueryHistValue_2D( x->hist, h, s ); + int intensity = cvRound( bin_val * 255 / max_value ); + cvRectangle( + x->src, + cvPoint( h*scale, s*scale ), + cvPoint( (h+1)*scale - 1, (s+1)*scale - 1), + CV_RGB(intensity,intensity,intensity), CV_FILLED, 8 , 0 ); + } + } + + //memory copy again, now from x->cedge->imageData to the new data pdp packet + //memcpy( newdata, hist_img, x->x_size*3 ); + memcpy( newdata, x->src->imageData, x->x_size*3 ); + + return; +} + +static void pdp_opencv_hist_compare_save(t_pdp_opencv_hist_compare *x, t_floatarg f) +{ + if (((int)f>=0)&&((int)fsave_now = (int)f; +} + +static void pdp_opencv_hist_compare_sendpacket(t_pdp_opencv_hist_compare *x) +{ + /* release the packet */ + pdp_packet_mark_unused(x->x_packet0); + x->x_packet0 = -1; + + /* unregister and propagate if valid dest packet */ + pdp_packet_pass_if_valid(x->x_outlet0, &x->x_packet1); +} + +static void pdp_opencv_hist_compare_process(t_pdp_opencv_hist_compare *x) +{ + int encoding; + t_pdp *header = 0; + char *parname; + unsigned pi; + int partype; + float pardefault; + t_atom plist[2]; + t_atom tlist[2]; + t_atom vlist[2]; + + /* check if image data packets are compatible */ + if ( (header = pdp_packet_header(x->x_packet0)) + && (PDP_BITMAP == header->type)){ + + /* pdp_opencv_hist_compare_process inputs and write into active inlet */ + switch(pdp_packet_header(x->x_packet0)->info.image.encoding){ + + case PDP_BITMAP_RGB: + x->x_packet1 = pdp_packet_clone_rw(x->x_packet0); + pdp_queue_add(x, (void*)pdp_opencv_hist_compare_process_rgb, (void*)pdp_opencv_hist_compare_sendpacket, &x->x_queue_id); + break; + + default: + /* don't know the type, so dont pdp_opencv_hist_compare_process */ + break; + + } + } + +} + +static void pdp_opencv_hist_compare_input_0(t_pdp_opencv_hist_compare *x, t_symbol *s, t_floatarg f) +{ + /* if this is a register_ro message or register_rw message, register with packet factory */ + + if (s == gensym("register_rw")) + x->x_dropped = pdp_packet_convert_ro_or_drop(&x->x_packet0, (int)f, pdp_gensym((char*)"bitmap/rgb/*") ); + + if ((s == gensym("process")) && (-1 != x->x_packet0) && (!x->x_dropped)) + { + /* add the process method and callback to the process queue */ + pdp_opencv_hist_compare_process(x); + } +} + +static void pdp_opencv_hist_compare_free(t_pdp_opencv_hist_compare *x) +{ + int i; + + pdp_queue_finish(x->x_queue_id); + pdp_packet_mark_unused(x->x_packet0); + //cv_freeplugins(x); + + //Destroy cv_images + cvReleaseImage(&x->src); + cvReleaseImage(&x->hsv); + cvReleaseImage(&x->h_plane); + cvReleaseImage(&x->s_plane); + cvReleaseImage(&x->v_plane); + cvReleaseImage(&x->h_saved_plane); + cvReleaseImage(&x->s_saved_plane); + cvReleaseImage(&x->v_saved_plane); +} + +t_class *pdp_opencv_hist_compare_class; + + +void *pdp_opencv_hist_compare_new(t_floatarg f) +{ + int i; + + t_pdp_opencv_hist_compare *x = (t_pdp_opencv_hist_compare *)pd_new(pdp_opencv_hist_compare_class); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("save")); + + x->x_outlet0 = outlet_new(&x->x_obj, &s_anything); + x->x_outlet1 = outlet_new(&x->x_obj, &s_float); + x->x_dataout = outlet_new(&x->x_obj, &s_anything); + + x->x_packet0 = -1; + x->x_packet1 = -1; + x->x_queue_id = -1; + + x->x_width = 320; + x->x_height = 240; + x->x_size = x->x_width * x->x_height; + + x->x_infosok = 0; + x->save_now = 0; + x->nbsaved = 0; + + x->src = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 3); + x->hsv = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 3 ); + + x->h_plane = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 1); + x->s_plane = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 1); + x->v_plane = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 1); + x->planes[0] = x->h_plane; + x->planes[1] = x->s_plane; + cvCvtPixToPlane( x->hsv, x->h_plane, x->s_plane, x->v_plane, 0 ); + x->h_saved_plane = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 1); + x->s_saved_plane = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 1); + x->v_saved_plane = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 1); + x->saved_planes[0] = x->h_saved_plane; + x->saved_planes[1] = x->s_saved_plane; + cvCvtPixToPlane( x->hsv, x->h_saved_plane, x->s_saved_plane, x->v_saved_plane, 0 ); + + cvCvtColor( x->src, x->hsv, CV_BGR2HSV ); + + int h_bins = (int)(x->x_width/10), s_bins = (int)(x->x_height/10); + { + int hist_size[] = { h_bins, s_bins }; + float h_ranges[] = { 0, 180 }; // hue is [0,180] + float s_ranges[] = { 0, 255 }; + float* ranges[] = { h_ranges, s_ranges }; + x->hist = cvCreateHist( + 2, + hist_size, + CV_HIST_ARRAY, + ranges, + 1 + ); + int n; + for (n=0; nsaved_hist[n] = cvCreateHist( + 2, + hist_size, + CV_HIST_ARRAY, + ranges, + 1 + ); + } + } + + return (void *)x; +} + + +#ifdef __cplusplus +extern "C" +{ +#endif + + +void pdp_opencv_hist_compare_setup(void) +{ + + post( " pdp_opencv_hist_compare"); + pdp_opencv_hist_compare_class = class_new(gensym("pdp_opencv_hist_compare"), (t_newmethod)pdp_opencv_hist_compare_new, + (t_method)pdp_opencv_hist_compare_free, sizeof(t_pdp_opencv_hist_compare), 0, A_DEFFLOAT, A_NULL); + + class_addmethod(pdp_opencv_hist_compare_class, (t_method)pdp_opencv_hist_compare_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL); + class_addmethod(pdp_opencv_hist_compare_class, (t_method)pdp_opencv_hist_compare_save, gensym("save"), A_FLOAT, A_NULL ); + +} + +#ifdef __cplusplus +} +#endif diff --git a/pdp_opencv_hu_moments.c b/pdp_opencv_hu_moments.c deleted file mode 100755 index b64a2f5..0000000 --- a/pdp_opencv_hu_moments.c +++ /dev/null @@ -1,242 +0,0 @@ -/* - * Pure Data Packet module. - * Copyright (c) by Tom Schouten - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "pdp.h" - -#ifndef _EiC -#include "cv.h" -#endif - -#define MAX_MARKERS 100 - -typedef struct pdp_opencv_hu_moments_struct -{ - t_object x_obj; - t_float x_f; - - t_outlet *x_outlet0; - t_outlet *x_dataout; - t_atom rlist[7]; - int x_packet0; - int x_packet1; - int x_dropped; - int x_queue_id; - - int x_width; - int x_height; - int x_size; - - int x_binary; - - IplImage *image, *gray; - CvMoments x_moments; - CvHuMoments x_humoments; - -} t_pdp_opencv_hu_moments; - -static void pdp_opencv_hu_moments_process_rgb(t_pdp_opencv_hu_moments *x) -{ - t_pdp *header = pdp_packet_header(x->x_packet0); - short int *data = (short int *)pdp_packet_data(x->x_packet0); - t_pdp *newheader = pdp_packet_header(x->x_packet1); - short int *newdata = (short int *)pdp_packet_data(x->x_packet1); - char tindex[4]; - int i = 0; // Indicator of cycles. - int im = 0; // Indicator of markers. - - if ((x->x_width != (t_int)header->info.image.width) || - (x->x_height != (t_int)header->info.image.height)) - { - - post("pdp_opencv_hu_moments :: resizing"); - - x->x_width = header->info.image.width; - x->x_height = header->info.image.height; - x->x_size = x->x_width*x->x_height; - - //Destroy cv_images - cvReleaseImage(&x->image); - cvReleaseImage(&x->gray); - - //create the orig image with new size - x->image = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 3); - x->gray = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 1); - - } - - newheader->info.image.encoding = header->info.image.encoding; - newheader->info.image.width = x->x_width; - newheader->info.image.height = x->x_height; - - memcpy( x->image->imageData, data, x->x_size*3 ); - - // Convert to grayscale - cvCvtColor(x->image, x->gray, CV_BGR2GRAY); - - cvMoments( x->gray, &x->x_moments, x->x_binary ); - cvGetHuMoments( &x->x_moments, &x->x_humoments ); - - SETFLOAT(&x->rlist[0], x->x_humoments.hu1); - SETFLOAT(&x->rlist[1], x->x_humoments.hu2); - SETFLOAT(&x->rlist[2], x->x_humoments.hu3); - SETFLOAT(&x->rlist[3], x->x_humoments.hu4); - SETFLOAT(&x->rlist[4], x->x_humoments.hu5); - SETFLOAT(&x->rlist[5], x->x_humoments.hu6); - SETFLOAT(&x->rlist[6], x->x_humoments.hu7); - - outlet_list( x->x_dataout, 0, 7, x->rlist ); - - memcpy( newdata, x->image->imageData, x->x_size*3 ); - - return; -} - -static void pdp_opencv_hu_moments_sendpacket(t_pdp_opencv_hu_moments *x) -{ - /* release the packet */ - pdp_packet_mark_unused(x->x_packet0); - x->x_packet0 = -1; - - /* unregister and propagate if valid dest packet */ - pdp_packet_pass_if_valid(x->x_outlet0, &x->x_packet1); -} - -static void pdp_opencv_hu_moments_process(t_pdp_opencv_hu_moments *x) -{ - int encoding; - t_pdp *header = 0; - char *parname; - unsigned pi; - int partype; - float pardefault; - t_atom plist[2]; - t_atom tlist[2]; - t_atom vlist[2]; - - /* check if image data packets are compatible */ - if ( (header = pdp_packet_header(x->x_packet0)) - && (PDP_BITMAP == header->type)){ - - /* pdp_opencv_hu_moments_process inputs and write into active inlet */ - switch(pdp_packet_header(x->x_packet0)->info.image.encoding){ - - case PDP_BITMAP_RGB: - x->x_packet1 = pdp_packet_clone_rw(x->x_packet0); - pdp_queue_add(x, pdp_opencv_hu_moments_process_rgb, pdp_opencv_hu_moments_sendpacket, &x->x_queue_id); - break; - - default: - /* don't know the type, so dont pdp_opencv_hu_moments_process */ - break; - - } - } - -} - -static void pdp_opencv_hu_moments_input_0(t_pdp_opencv_hu_moments *x, t_symbol *s, t_floatarg f) -{ - /* if this is a register_ro message or register_rw message, register with packet factory */ - - if (s == gensym("register_rw")) - x->x_dropped = pdp_packet_convert_ro_or_drop(&x->x_packet0, (int)f, pdp_gensym("bitmap/rgb/*") ); - - if ((s == gensym("process")) && (-1 != x->x_packet0) && (!x->x_dropped)) - { - /* add the process method and callback to the process queue */ - pdp_opencv_hu_moments_process(x); - } -} - -static void pdp_opencv_hu_moments_free(t_pdp_opencv_hu_moments *x) -{ - int i; - - pdp_queue_finish(x->x_queue_id); - pdp_packet_mark_unused(x->x_packet0); - - //Destroy cv_images - cvReleaseImage(&x->image); - cvReleaseImage(&x->gray); -} - -t_class *pdp_opencv_hu_moments_class; - - -void *pdp_opencv_hu_moments_new(t_floatarg f) -{ - int i; - - t_pdp_opencv_hu_moments *x = (t_pdp_opencv_hu_moments *)pd_new(pdp_opencv_hu_moments_class); - - x->x_outlet0 = outlet_new(&x->x_obj, &s_anything); - x->x_dataout = outlet_new(&x->x_obj, &s_anything); - - x->x_packet0 = -1; - x->x_packet1 = -1; - x->x_queue_id = -1; - - x->x_width = 320; - x->x_height = 240; - x->x_size = x->x_width * x->x_height; - - x->x_binary = 0; - - x->image = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 3); - x->gray = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 1); - - //contours = 0; - return (void *)x; -} - -static void pdp_opencv_hu_moments_binary(t_pdp_opencv_hu_moments *x, t_floatarg f) -{ - if ( ((int)f==1) || ((int)f==0) ) x->x_binary = (int)f; -} - -#ifdef __cplusplus -extern "C" -{ -#endif - - -void pdp_opencv_hu_moments_setup(void) -{ - - post( " pdp_opencv_hu_moments"); - pdp_opencv_hu_moments_class = class_new(gensym("pdp_opencv_hu_moments"), (t_newmethod)pdp_opencv_hu_moments_new, - (t_method)pdp_opencv_hu_moments_free, sizeof(t_pdp_opencv_hu_moments), 0, A_DEFFLOAT, A_NULL); - - class_addmethod(pdp_opencv_hu_moments_class, (t_method)pdp_opencv_hu_moments_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL); - class_addmethod(pdp_opencv_hu_moments_class, (t_method)pdp_opencv_hu_moments_binary, gensym("binary"), A_DEFFLOAT, A_NULL); - -} - -#ifdef __cplusplus -} -#endif diff --git a/pdp_opencv_hu_moments.cc b/pdp_opencv_hu_moments.cc new file mode 100755 index 0000000..662bf32 --- /dev/null +++ b/pdp_opencv_hu_moments.cc @@ -0,0 +1,242 @@ +/* + * Pure Data Packet module. + * Copyright (c) by Tom Schouten + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "pdp.h" + +#ifndef _EiC +#include "cv.h" +#endif + +#define MAX_MARKERS 100 + +typedef struct pdp_opencv_hu_moments_struct +{ + t_object x_obj; + t_float x_f; + + t_outlet *x_outlet0; + t_outlet *x_dataout; + t_atom rlist[7]; + int x_packet0; + int x_packet1; + int x_dropped; + int x_queue_id; + + int x_width; + int x_height; + int x_size; + + int x_binary; + + IplImage *image, *gray; + CvMoments x_moments; + CvHuMoments x_humoments; + +} t_pdp_opencv_hu_moments; + +static void pdp_opencv_hu_moments_process_rgb(t_pdp_opencv_hu_moments *x) +{ + t_pdp *header = pdp_packet_header(x->x_packet0); + short int *data = (short int *)pdp_packet_data(x->x_packet0); + t_pdp *newheader = pdp_packet_header(x->x_packet1); + short int *newdata = (short int *)pdp_packet_data(x->x_packet1); + char tindex[4]; + int i = 0; // Indicator of cycles. + int im = 0; // Indicator of markers. + + if ((x->x_width != (t_int)header->info.image.width) || + (x->x_height != (t_int)header->info.image.height)) + { + + post("pdp_opencv_hu_moments :: resizing"); + + x->x_width = header->info.image.width; + x->x_height = header->info.image.height; + x->x_size = x->x_width*x->x_height; + + //Destroy cv_images + cvReleaseImage(&x->image); + cvReleaseImage(&x->gray); + + //create the orig image with new size + x->image = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 3); + x->gray = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 1); + + } + + newheader->info.image.encoding = header->info.image.encoding; + newheader->info.image.width = x->x_width; + newheader->info.image.height = x->x_height; + + memcpy( x->image->imageData, data, x->x_size*3 ); + + // Convert to grayscale + cvCvtColor(x->image, x->gray, CV_BGR2GRAY); + + cvMoments( x->gray, &x->x_moments, x->x_binary ); + cvGetHuMoments( &x->x_moments, &x->x_humoments ); + + SETFLOAT(&x->rlist[0], x->x_humoments.hu1); + SETFLOAT(&x->rlist[1], x->x_humoments.hu2); + SETFLOAT(&x->rlist[2], x->x_humoments.hu3); + SETFLOAT(&x->rlist[3], x->x_humoments.hu4); + SETFLOAT(&x->rlist[4], x->x_humoments.hu5); + SETFLOAT(&x->rlist[5], x->x_humoments.hu6); + SETFLOAT(&x->rlist[6], x->x_humoments.hu7); + + outlet_list( x->x_dataout, 0, 7, x->rlist ); + + memcpy( newdata, x->image->imageData, x->x_size*3 ); + + return; +} + +static void pdp_opencv_hu_moments_sendpacket(t_pdp_opencv_hu_moments *x) +{ + /* release the packet */ + pdp_packet_mark_unused(x->x_packet0); + x->x_packet0 = -1; + + /* unregister and propagate if valid dest packet */ + pdp_packet_pass_if_valid(x->x_outlet0, &x->x_packet1); +} + +static void pdp_opencv_hu_moments_process(t_pdp_opencv_hu_moments *x) +{ + int encoding; + t_pdp *header = 0; + char *parname; + unsigned pi; + int partype; + float pardefault; + t_atom plist[2]; + t_atom tlist[2]; + t_atom vlist[2]; + + /* check if image data packets are compatible */ + if ( (header = pdp_packet_header(x->x_packet0)) + && (PDP_BITMAP == header->type)){ + + /* pdp_opencv_hu_moments_process inputs and write into active inlet */ + switch(pdp_packet_header(x->x_packet0)->info.image.encoding){ + + case PDP_BITMAP_RGB: + x->x_packet1 = pdp_packet_clone_rw(x->x_packet0); + pdp_queue_add(x, (void*)pdp_opencv_hu_moments_process_rgb, (void*)pdp_opencv_hu_moments_sendpacket, &x->x_queue_id); + break; + + default: + /* don't know the type, so dont pdp_opencv_hu_moments_process */ + break; + + } + } + +} + +static void pdp_opencv_hu_moments_input_0(t_pdp_opencv_hu_moments *x, t_symbol *s, t_floatarg f) +{ + /* if this is a register_ro message or register_rw message, register with packet factory */ + + if (s == gensym("register_rw")) + x->x_dropped = pdp_packet_convert_ro_or_drop(&x->x_packet0, (int)f, pdp_gensym((char*)"bitmap/rgb/*") ); + + if ((s == gensym("process")) && (-1 != x->x_packet0) && (!x->x_dropped)) + { + /* add the process method and callback to the process queue */ + pdp_opencv_hu_moments_process(x); + } +} + +static void pdp_opencv_hu_moments_free(t_pdp_opencv_hu_moments *x) +{ + int i; + + pdp_queue_finish(x->x_queue_id); + pdp_packet_mark_unused(x->x_packet0); + + //Destroy cv_images + cvReleaseImage(&x->image); + cvReleaseImage(&x->gray); +} + +t_class *pdp_opencv_hu_moments_class; + + +void *pdp_opencv_hu_moments_new(t_floatarg f) +{ + int i; + + t_pdp_opencv_hu_moments *x = (t_pdp_opencv_hu_moments *)pd_new(pdp_opencv_hu_moments_class); + + x->x_outlet0 = outlet_new(&x->x_obj, &s_anything); + x->x_dataout = outlet_new(&x->x_obj, &s_anything); + + x->x_packet0 = -1; + x->x_packet1 = -1; + x->x_queue_id = -1; + + x->x_width = 320; + x->x_height = 240; + x->x_size = x->x_width * x->x_height; + + x->x_binary = 0; + + x->image = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 3); + x->gray = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 1); + + //contours = 0; + return (void *)x; +} + +static void pdp_opencv_hu_moments_binary(t_pdp_opencv_hu_moments *x, t_floatarg f) +{ + if ( ((int)f==1) || ((int)f==0) ) x->x_binary = (int)f; +} + +#ifdef __cplusplus +extern "C" +{ +#endif + + +void pdp_opencv_hu_moments_setup(void) +{ + + post( " pdp_opencv_hu_moments"); + pdp_opencv_hu_moments_class = class_new(gensym("pdp_opencv_hu_moments"), (t_newmethod)pdp_opencv_hu_moments_new, + (t_method)pdp_opencv_hu_moments_free, sizeof(t_pdp_opencv_hu_moments), 0, A_DEFFLOAT, A_NULL); + + class_addmethod(pdp_opencv_hu_moments_class, (t_method)pdp_opencv_hu_moments_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL); + class_addmethod(pdp_opencv_hu_moments_class, (t_method)pdp_opencv_hu_moments_binary, gensym("binary"), A_DEFFLOAT, A_NULL); + +} + +#ifdef __cplusplus +} +#endif diff --git a/pdp_opencv_laplace.c b/pdp_opencv_laplace.c deleted file mode 100644 index 688fe9e..0000000 --- a/pdp_opencv_laplace.c +++ /dev/null @@ -1,248 +0,0 @@ -/* - * Pure Data Packet module. - * Copyright (c) by Tom Schouten - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include -#include -#include -#include -#include -#include - -#include "pdp.h" - -#ifndef _EiC -#include "cv.h" -#endif - -typedef struct pdp_opencv_laplace_struct -{ - t_object x_obj; - t_float x_f; - - t_outlet *x_outlet0; - int x_packet0; - int x_packet1; - int x_dropped; - int x_queue_id; - - int x_width; - int x_height; - int x_size; - - int x_infosok; - - int aperture_size; - int build_voronoi; - int mask_size; - - // The output and temporary images - IplImage* frame; - IplImage* laplace; - IplImage* colorlaplace; - IplImage* planes[3]; - - -} t_pdp_opencv_laplace; - -static void pdp_opencv_laplace_process_rgb(t_pdp_opencv_laplace *x) -{ - t_pdp *header = pdp_packet_header(x->x_packet0); - short int *data = (short int *)pdp_packet_data(x->x_packet0); - t_pdp *newheader = pdp_packet_header(x->x_packet1); - short int *newdata = (short int *)pdp_packet_data(x->x_packet1); - int i; - - if ((x->x_width != (t_int)header->info.image.width) || - (x->x_height != (t_int)header->info.image.height)) - { - - post("pdp_opencv_laplace :: resizing plugins"); - - //cv_freeplugins(x); - - x->x_width = header->info.image.width; - x->x_height = header->info.image.height; - x->x_size = x->x_width*x->x_height; - - //Destroy cv_images - for( i = 0; i < 3; i++ ) - cvReleaseImage( &x->planes[i] ); - cvReleaseImage( &x->frame ); - cvReleaseImage( &x->laplace ); - cvReleaseImage( &x->colorlaplace ); - - //Create cv_images - for( i = 0; i < 3; i++ ) - x->planes[i] = cvCreateImage( cvSize(x->x_width, x->x_height), 8, 1 ); - x->laplace = cvCreateImage( cvSize(x->x_width, x->x_height), IPL_DEPTH_16S, 1 ); - x->colorlaplace = cvCreateImage( cvSize(x->x_width,x->x_height), 8, 3 ); - x->frame = cvCreateImage( cvSize(x->x_width,x->x_height), 8, 3 ); - } - - newheader->info.image.encoding = header->info.image.encoding; - newheader->info.image.width = x->x_width; - newheader->info.image.height = x->x_height; - - memcpy( newdata, data, x->x_size*3 ); - - // FEM UNA COPIA DEL PACKET A x->grey->imageData ... http://www.cs.iit.edu/~agam/cs512/lect-notes/opencv-intro/opencv-intro.html aqui veiem la estructura de IplImage - memcpy( x->frame->imageData, data, x->x_size*3 ); - - cvCvtPixToPlane( x->frame, x->planes[0], x->planes[1], x->planes[2], 0 ); - for( i = 0; i < 3; i++ ) - { - cvLaplace( x->planes[i], x->laplace, x->aperture_size ); - cvConvertScaleAbs( x->laplace, x->planes[i], 1, 0 ); - } - cvCvtPlaneToPix( x->planes[0], x->planes[1], x->planes[2], 0, x->colorlaplace ); - x->colorlaplace->origin = x->frame->origin; - - memcpy( newdata, x->colorlaplace->imageData, x->x_size*3 ); - - return; -} - - -static void pdp_opencv_laplace_thresh(t_pdp_opencv_laplace *x, t_floatarg f) -{ - if ((f==1)||(f==3)||(f==5)||(f==7)) x->aperture_size = (int)f; -} - -static void pdp_opencv_laplace_sendpacket(t_pdp_opencv_laplace *x) -{ - /* release the packet */ - pdp_packet_mark_unused(x->x_packet0); - x->x_packet0 = -1; - - /* unregister and propagate if valid dest packet */ - pdp_packet_pass_if_valid(x->x_outlet0, &x->x_packet1); -} - -static void pdp_opencv_laplace_process(t_pdp_opencv_laplace *x) -{ - int encoding; - t_pdp *header = 0; - - /* check if image data packets are compatible */ - if ( (header = pdp_packet_header(x->x_packet0)) - && (PDP_BITMAP == header->type)){ - - /* pdp_opencv_laplace_process inputs and write into active inlet */ - switch(pdp_packet_header(x->x_packet0)->info.image.encoding){ - - case PDP_BITMAP_RGB: - x->x_packet1 = pdp_packet_clone_rw(x->x_packet0); - pdp_queue_add(x, pdp_opencv_laplace_process_rgb, pdp_opencv_laplace_sendpacket, &x->x_queue_id); - break; - - default: - /* don't know the type, so dont pdp_opencv_laplace_process */ - break; - - } - } - -} - -static void pdp_opencv_laplace_input_0(t_pdp_opencv_laplace *x, t_symbol *s, t_floatarg f) -{ - /* if this is a register_ro message or register_rw message, register with packet factory */ - - if (s == gensym("register_rw")) - x->x_dropped = pdp_packet_convert_ro_or_drop(&x->x_packet0, (int)f, pdp_gensym("bitmap/rgb/*") ); - - if ((s == gensym("process")) && (-1 != x->x_packet0) && (!x->x_dropped)) - { - /* add the process method and callback to the process queue */ - pdp_opencv_laplace_process(x); - } -} - -static void pdp_opencv_laplace_free(t_pdp_opencv_laplace *x) -{ - int i; - - pdp_queue_finish(x->x_queue_id); - pdp_packet_mark_unused(x->x_packet0); - - //Destroy cv_images - for( i = 0; i < 3; i++ ) - cvReleaseImage( &x->planes[i] ); - cvReleaseImage( &x->frame ); - cvReleaseImage( &x->laplace ); - cvReleaseImage( &x->colorlaplace ); -} - -t_class *pdp_opencv_laplace_class; - - -void *pdp_opencv_laplace_new(t_floatarg f) -{ - int i; - - t_pdp_opencv_laplace *x = (t_pdp_opencv_laplace *)pd_new(pdp_opencv_laplace_class); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("aperture_size")); - - x->x_outlet0 = outlet_new(&x->x_obj, &s_anything); - - x->x_packet0 = -1; - x->x_packet1 = -1; - x->x_queue_id = -1; - - x->x_width = 320; - x->x_height = 240; - x->x_size = x->x_width * x->x_height; - - x->x_infosok = 0; - - x->aperture_size = 3; - - for( i = 0; i < 3; i++ ) - x->planes[i] = cvCreateImage( cvSize(x->x_width, x->x_height), 8, 1 ); - x->laplace = cvCreateImage( cvSize(x->x_width, x->x_height), IPL_DEPTH_16S, 1 ); - x->colorlaplace = cvCreateImage( cvSize(x->x_width,x->x_height), 8, 3 ); - x->frame = cvCreateImage( cvSize(x->x_width,x->x_height), 8, 3 ); - - - return (void *)x; -} - - -#ifdef __cplusplus -extern "C" -{ -#endif - - -void pdp_opencv_laplace_setup(void) -{ - - post( " pdp_opencv_laplace"); - pdp_opencv_laplace_class = class_new(gensym("pdp_opencv_laplace"), (t_newmethod)pdp_opencv_laplace_new, - (t_method)pdp_opencv_laplace_free, sizeof(t_pdp_opencv_laplace), 0, A_DEFFLOAT, A_NULL); - - class_addmethod(pdp_opencv_laplace_class, (t_method)pdp_opencv_laplace_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL); - class_addmethod(pdp_opencv_laplace_class, (t_method)pdp_opencv_laplace_thresh, gensym("aperture_size"), A_FLOAT, A_NULL ); - -} - -#ifdef __cplusplus -} -#endif diff --git a/pdp_opencv_laplace.cc b/pdp_opencv_laplace.cc new file mode 100755 index 0000000..91cb07f --- /dev/null +++ b/pdp_opencv_laplace.cc @@ -0,0 +1,248 @@ +/* + * Pure Data Packet module. + * Copyright (c) by Tom Schouten + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include + +#include "pdp.h" + +#ifndef _EiC +#include "cv.h" +#endif + +typedef struct pdp_opencv_laplace_struct +{ + t_object x_obj; + t_float x_f; + + t_outlet *x_outlet0; + int x_packet0; + int x_packet1; + int x_dropped; + int x_queue_id; + + int x_width; + int x_height; + int x_size; + + int x_infosok; + + int aperture_size; + int build_voronoi; + int mask_size; + + // The output and temporary images + IplImage* frame; + IplImage* laplace; + IplImage* colorlaplace; + IplImage* planes[3]; + + +} t_pdp_opencv_laplace; + +static void pdp_opencv_laplace_process_rgb(t_pdp_opencv_laplace *x) +{ + t_pdp *header = pdp_packet_header(x->x_packet0); + short int *data = (short int *)pdp_packet_data(x->x_packet0); + t_pdp *newheader = pdp_packet_header(x->x_packet1); + short int *newdata = (short int *)pdp_packet_data(x->x_packet1); + int i; + + if ((x->x_width != (t_int)header->info.image.width) || + (x->x_height != (t_int)header->info.image.height)) + { + + post("pdp_opencv_laplace :: resizing plugins"); + + //cv_freeplugins(x); + + x->x_width = header->info.image.width; + x->x_height = header->info.image.height; + x->x_size = x->x_width*x->x_height; + + //Destroy cv_images + for( i = 0; i < 3; i++ ) + cvReleaseImage( &x->planes[i] ); + cvReleaseImage( &x->frame ); + cvReleaseImage( &x->laplace ); + cvReleaseImage( &x->colorlaplace ); + + //Create cv_images + for( i = 0; i < 3; i++ ) + x->planes[i] = cvCreateImage( cvSize(x->x_width, x->x_height), 8, 1 ); + x->laplace = cvCreateImage( cvSize(x->x_width, x->x_height), IPL_DEPTH_16S, 1 ); + x->colorlaplace = cvCreateImage( cvSize(x->x_width,x->x_height), 8, 3 ); + x->frame = cvCreateImage( cvSize(x->x_width,x->x_height), 8, 3 ); + } + + newheader->info.image.encoding = header->info.image.encoding; + newheader->info.image.width = x->x_width; + newheader->info.image.height = x->x_height; + + memcpy( newdata, data, x->x_size*3 ); + + // FEM UNA COPIA DEL PACKET A x->grey->imageData ... http://www.cs.iit.edu/~agam/cs512/lect-notes/opencv-intro/opencv-intro.html aqui veiem la estructura de IplImage + memcpy( x->frame->imageData, data, x->x_size*3 ); + + cvCvtPixToPlane( x->frame, x->planes[0], x->planes[1], x->planes[2], 0 ); + for( i = 0; i < 3; i++ ) + { + cvLaplace( x->planes[i], x->laplace, x->aperture_size ); + cvConvertScaleAbs( x->laplace, x->planes[i], 1, 0 ); + } + cvCvtPlaneToPix( x->planes[0], x->planes[1], x->planes[2], 0, x->colorlaplace ); + x->colorlaplace->origin = x->frame->origin; + + memcpy( newdata, x->colorlaplace->imageData, x->x_size*3 ); + + return; +} + + +static void pdp_opencv_laplace_thresh(t_pdp_opencv_laplace *x, t_floatarg f) +{ + if ((f==1)||(f==3)||(f==5)||(f==7)) x->aperture_size = (int)f; +} + +static void pdp_opencv_laplace_sendpacket(t_pdp_opencv_laplace *x) +{ + /* release the packet */ + pdp_packet_mark_unused(x->x_packet0); + x->x_packet0 = -1; + + /* unregister and propagate if valid dest packet */ + pdp_packet_pass_if_valid(x->x_outlet0, &x->x_packet1); +} + +static void pdp_opencv_laplace_process(t_pdp_opencv_laplace *x) +{ + int encoding; + t_pdp *header = 0; + + /* check if image data packets are compatible */ + if ( (header = pdp_packet_header(x->x_packet0)) + && (PDP_BITMAP == header->type)){ + + /* pdp_opencv_laplace_process inputs and write into active inlet */ + switch(pdp_packet_header(x->x_packet0)->info.image.encoding){ + + case PDP_BITMAP_RGB: + x->x_packet1 = pdp_packet_clone_rw(x->x_packet0); + pdp_queue_add(x, (void*)pdp_opencv_laplace_process_rgb, (void*)pdp_opencv_laplace_sendpacket, &x->x_queue_id); + break; + + default: + /* don't know the type, so dont pdp_opencv_laplace_process */ + break; + + } + } + +} + +static void pdp_opencv_laplace_input_0(t_pdp_opencv_laplace *x, t_symbol *s, t_floatarg f) +{ + /* if this is a register_ro message or register_rw message, register with packet factory */ + + if (s == gensym("register_rw")) + x->x_dropped = pdp_packet_convert_ro_or_drop(&x->x_packet0, (int)f, pdp_gensym((char*)"bitmap/rgb/*") ); + + if ((s == gensym("process")) && (-1 != x->x_packet0) && (!x->x_dropped)) + { + /* add the process method and callback to the process queue */ + pdp_opencv_laplace_process(x); + } +} + +static void pdp_opencv_laplace_free(t_pdp_opencv_laplace *x) +{ + int i; + + pdp_queue_finish(x->x_queue_id); + pdp_packet_mark_unused(x->x_packet0); + + //Destroy cv_images + for( i = 0; i < 3; i++ ) + cvReleaseImage( &x->planes[i] ); + cvReleaseImage( &x->frame ); + cvReleaseImage( &x->laplace ); + cvReleaseImage( &x->colorlaplace ); +} + +t_class *pdp_opencv_laplace_class; + + +void *pdp_opencv_laplace_new(t_floatarg f) +{ + int i; + + t_pdp_opencv_laplace *x = (t_pdp_opencv_laplace *)pd_new(pdp_opencv_laplace_class); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("aperture_size")); + + x->x_outlet0 = outlet_new(&x->x_obj, &s_anything); + + x->x_packet0 = -1; + x->x_packet1 = -1; + x->x_queue_id = -1; + + x->x_width = 320; + x->x_height = 240; + x->x_size = x->x_width * x->x_height; + + x->x_infosok = 0; + + x->aperture_size = 3; + + for( i = 0; i < 3; i++ ) + x->planes[i] = cvCreateImage( cvSize(x->x_width, x->x_height), 8, 1 ); + x->laplace = cvCreateImage( cvSize(x->x_width, x->x_height), IPL_DEPTH_16S, 1 ); + x->colorlaplace = cvCreateImage( cvSize(x->x_width,x->x_height), 8, 3 ); + x->frame = cvCreateImage( cvSize(x->x_width,x->x_height), 8, 3 ); + + + return (void *)x; +} + + +#ifdef __cplusplus +extern "C" +{ +#endif + + +void pdp_opencv_laplace_setup(void) +{ + + post( " pdp_opencv_laplace"); + pdp_opencv_laplace_class = class_new(gensym("pdp_opencv_laplace"), (t_newmethod)pdp_opencv_laplace_new, + (t_method)pdp_opencv_laplace_free, sizeof(t_pdp_opencv_laplace), 0, A_DEFFLOAT, A_NULL); + + class_addmethod(pdp_opencv_laplace_class, (t_method)pdp_opencv_laplace_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL); + class_addmethod(pdp_opencv_laplace_class, (t_method)pdp_opencv_laplace_thresh, gensym("aperture_size"), A_FLOAT, A_NULL ); + +} + +#ifdef __cplusplus +} +#endif diff --git a/pdp_opencv_lk.c b/pdp_opencv_lk.c deleted file mode 100644 index 6f08444..0000000 --- a/pdp_opencv_lk.c +++ /dev/null @@ -1,700 +0,0 @@ -/* - * Pure Data Packet module. - * Copyright (c) by Tom Schouten - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "pdp.h" - -#ifndef _EiC -#include "cv.h" -#endif - -#define MAX_MARKERS 500 -const int MAX_COUNT = 500; - -typedef struct pdp_opencv_lk_struct -{ - t_object x_obj; - t_float x_f; - - t_outlet *x_outlet0; - t_outlet *x_outlet1; - t_atom x_list[3]; - - int x_packet0; - int x_packet1; - int x_dropped; - int x_queue_id; - - int x_width; - int x_height; - int x_size; - - int win_size; - double quality; - int min_distance; - int x_maxmove; - int x_ftolerance; - int x_markall; - int x_delaunay; - int x_threshold; - int x_xmark[MAX_MARKERS]; - int x_ymark[MAX_MARKERS]; - int x_found[MAX_MARKERS]; - - // The output and temporary images - IplImage *image, *oimage, *grey, *prev_grey, *pyramid, *prev_pyramid, *swap_temp; - - CvPoint2D32f* points[2], *swap_points; - char* status; - int count; - int need_to_init; - int night_mode; - int flags; - int add_remove_pt; - CvPoint pt; - CvFont font; - - // structures needed for the delaunay - CvRect x_fullrect; - CvMemStorage* x_storage; - CvSubdiv2D* x_subdiv; - -} t_pdp_opencv_lk; - -static void pdp_opencv_lk_clear(t_pdp_opencv_lk *x); - -static void pdp_opencv_lk_process_rgb(t_pdp_opencv_lk *x) -{ - t_pdp *header = pdp_packet_header(x->x_packet0); - short int *data = (short int *)pdp_packet_data(x->x_packet0); - t_pdp *newheader = pdp_packet_header(x->x_packet1); - short int *newdata = (short int *)pdp_packet_data(x->x_packet1); - int i,j,k,im; - int marked; - - if ((x->x_width != (t_int)header->info.image.width) || - (x->x_height != (t_int)header->info.image.height) || (!x->image)) - { - - post("pdp_opencv_lk :: resizing plugins"); - - x->x_width = header->info.image.width; - x->x_height = header->info.image.height; - x->x_size = x->x_width*x->x_height; - - //Destroy cv_images - cvReleaseImage( &x->image ); - cvReleaseImage( &x->oimage ); - cvReleaseImage( &x->grey ); - cvReleaseImage( &x->prev_grey ); - cvReleaseImage( &x->pyramid ); - cvReleaseImage( &x->prev_pyramid ); - - //Create cv_images - x->image = cvCreateImage( cvSize(x->x_width, x->x_height), 8, 3 ); - x->oimage = cvCreateImage( cvSize(x->x_width, x->x_height), 8, 3 ); - x->grey = cvCreateImage( cvSize(x->x_width, x->x_height), 8, 1 ); - x->prev_grey = cvCreateImage( cvSize(x->x_width, x->x_height), 8, 1 ); - x->pyramid = cvCreateImage( cvSize(x->x_width, x->x_height), 8, 1 ); - x->prev_pyramid = cvCreateImage( cvSize(x->x_width, x->x_height), 8, 1 ); - x->points[0] = (CvPoint2D32f*)cvAlloc(MAX_COUNT*sizeof(x->points[0][0])); - x->points[1] = (CvPoint2D32f*)cvAlloc(MAX_COUNT*sizeof(x->points[0][0])); - x->status = (char*)cvAlloc(MAX_COUNT); - } - - newheader->info.image.encoding = header->info.image.encoding; - newheader->info.image.width = x->x_width; - newheader->info.image.height = x->x_height; - - memcpy( newdata, data, x->x_size*3 ); - - memcpy( x->image->imageData, data, x->x_size*3 ); - memcpy( x->oimage->imageData, data, x->x_size*3 ); - - cvCvtColor( x->image, x->grey, CV_RGB2GRAY ); - - if( x->night_mode ) - cvZero( x->image ); - - for ( im=0; imx_found[im]--; - } - - if ( x->x_delaunay >= 0 ) - { - // init data structures for the delaunay - x->x_fullrect.x = -x->x_width/2; - x->x_fullrect.y = -x->x_height/2; - x->x_fullrect.width = 2*x->x_width; - x->x_fullrect.height = 2*x->x_height; - - x->x_storage = cvCreateMemStorage(0); - x->x_subdiv = cvCreateSubdiv2D( CV_SEQ_KIND_SUBDIV2D, sizeof(*x->x_subdiv), - sizeof(CvSubdiv2DPoint), - sizeof(CvQuadEdge2D), - x->x_storage ); - cvInitSubdivDelaunay2D( x->x_subdiv, x->x_fullrect ); - } - - if( x->need_to_init ) - { - /* automatic initialization */ - IplImage* eig = cvCreateImage( cvSize(x->grey->width,x->grey->height), 32, 1 ); - IplImage* temp = cvCreateImage( cvSize(x->grey->width,x->grey->height), 32, 1 ); - - x->count = MAX_COUNT; - cvGoodFeaturesToTrack( x->grey, eig, temp, x->points[1], &x->count, - x->quality, x->min_distance, 0, 3, 0, 0.04 ); - cvFindCornerSubPix( x->grey, x->points[1], x->count, - cvSize(x->win_size,x->win_size), cvSize(-1,-1), - cvTermCriteria(CV_TERMCRIT_ITER|CV_TERMCRIT_EPS,20,0.03)); - cvReleaseImage( &eig ); - cvReleaseImage( &temp ); - - x->add_remove_pt = 0; - } - else if( x->count > 0 ) - { - cvCalcOpticalFlowPyrLK( x->prev_grey, x->grey, x->prev_pyramid, x->pyramid, - x->points[0], x->points[1], x->count, cvSize(x->win_size,x->win_size), 3, x->status, 0, - cvTermCriteria(CV_TERMCRIT_ITER|CV_TERMCRIT_EPS,20,0.03), x->flags ); - x->flags |= CV_LKFLOW_PYR_A_READY; - for( i = k = 0; i < x->count; i++ ) - { - if( x->add_remove_pt ) - { - double dx = x->pt.x - x->points[1][i].x; - double dy = x->pt.y - x->points[1][i].y; - - if( dx*dx + dy*dy <= 25 ) - { - x->add_remove_pt = 0; - continue; - } - } - - if( !x->status[i] ) - continue; - - x->points[1][k++] = x->points[1][i]; - - if ( x->x_delaunay == 0 ) // add all the points - { - cvSubdivDelaunay2DInsert( x->x_subdiv, x->points[1][i] ); - cvCalcSubdivVoronoi2D( x->x_subdiv ); - } - // only add points included in (color-threshold)x_delaunay > 0 ) && ( x->x_xmark[x->x_delaunay-1] != -1 ) ) - { - int px = cvPointFrom32f(x->points[1][i]).x; - int py = cvPointFrom32f(x->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 >= x->x_width ) ) continue; - if ( ( ppy < 0 ) || ( ppy >= x->x_height ) ) continue; - - uchar red = ((uchar*)(x->oimage->imageData + x->oimage->widthStep*ppx))[ppy*3]; - uchar green = ((uchar*)(x->oimage->imageData + x->oimage->widthStep*ppx))[ppy*3+1]; - uchar blue = ((uchar*)(x->oimage->imageData + x->oimage->widthStep*ppx))[ppy*3+2]; - - uchar pred = ((uchar*)(x->oimage->imageData + x->oimage->widthStep*x->x_xmark[x->x_delaunay-1]))[x->x_ymark[x->x_delaunay-1]*3]; - uchar pgreen = ((uchar*)(x->oimage->imageData + x->oimage->widthStep*x->x_xmark[x->x_delaunay-1]))[x->x_ymark[x->x_delaunay-1]*3+1]; - uchar pblue = ((uchar*)(x->oimage->imageData + x->oimage->widthStep*x->x_xmark[x->x_delaunay-1]))[x->x_ymark[x->x_delaunay-1]*3+2]; - - int diff = abs(red-pred) + abs(green-pgreen) + abs(blue-pblue); - - // post( "pdp_opencv_lk : point (%d,%d,%d) : diff : %d", blue, green, red, diff ); - - if ( diff < x->x_threshold ) - { - cvSubdivDelaunay2DInsert( x->x_subdiv, x->points[1][i] ); - cvCalcSubdivVoronoi2D( x->x_subdiv ); - } - } - } - } - - cvCircle( x->image, cvPointFrom32f(x->points[1][i]), 3, CV_RGB(0,255,0), -1, 8,0); - - marked=0; - for ( im=0; imx_xmark[im] != -1.0 ) - { - if ( ( abs( x->points[1][i].x - x->x_xmark[im] ) <= x->x_maxmove ) && ( abs( x->points[1][i].y - x->x_ymark[im] ) <= x->x_maxmove ) ) - { - char tindex[4]; - sprintf( tindex, "%d", im+1 ); - cvPutText( x->image, tindex, cvPointFrom32f(x->points[1][i]), &x->font, CV_RGB(255,255,255)); - x->x_xmark[im]=x->points[1][i].x; - x->x_ymark[im]=x->points[1][i].y; - x->x_found[im]=x->x_ftolerance; - marked=1; - SETFLOAT(&x->x_list[0], im+1); - SETFLOAT(&x->x_list[1], x->x_xmark[im]); - SETFLOAT(&x->x_list[2], x->x_ymark[im]); - outlet_list( x->x_outlet1, 0, 3, x->x_list ); - } - } - } - - if ( x->x_markall && !marked ) - { - for ( im=0; imx_xmark[im] == -1 ) - { - x->x_xmark[im]=x->points[1][i].x; - x->x_ymark[im]=x->points[1][i].y; - x->x_found[im]=x->x_ftolerance; - break; - } - } - } - } - x->count = k; - } - - if( x->add_remove_pt && x->count < MAX_COUNT ) - { - x->points[1][x->count++] = cvPointTo32f(x->pt); - cvFindCornerSubPix( x->grey, x->points[1] + x->count - 1, 1, - cvSize(x->win_size,x->win_size), cvSize(-1,-1), - cvTermCriteria(CV_TERMCRIT_ITER|CV_TERMCRIT_EPS,20,0.03)); - x->add_remove_pt = 0; - } - - // draw the delaunay - if ( x->x_delaunay >= 0 ) - { - CvSeqReader reader; - int i, total = x->x_subdiv->edges->total; - int elem_size = x->x_subdiv->edges->elem_size; - - cvStartReadSeq( (CvSeq*)(x->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 < x->x_width ) && - ( dst.x > 0 ) && ( dst.x < x->x_width ) && - ( org.y > 0 ) && ( org.y < x->x_height ) && - ( dst.y > 0 ) && ( dst.y < x->x_height ) ) - cvLine( x->image, iorg, idst, CV_RGB(255,0,0), 1, CV_AA, 0 ); - } - } - - // draw the voronoi : useless in my opinion as points belongs to contours - /* - if( CV_IS_SET_ELEM( edge+1 )) - { - org_pt = cvSubdiv2DEdgeOrg((CvSubdiv2DEdge)edge+1); - dst_pt = cvSubdiv2DEdgeDst((CvSubdiv2DEdge)edge+1); - - 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 )); - - cvLine( x->image, iorg, idst, CV_RGB(0,0,255), 1, CV_AA, 0 ); - } - } - */ - - CV_NEXT_SEQ_ELEM( elem_size, reader ); - } - } - - for ( im=0; imx_xmark[im] != -1.0 ) && !x->x_found[im] ) - { - // lost the point - x->x_xmark[im]=-1.0; - x->x_ymark[im]=-1.0; - SETFLOAT(&x->x_list[0], im+1); - SETFLOAT(&x->x_list[1], x->x_xmark[im]); - SETFLOAT(&x->x_list[2], x->x_ymark[im]); - // send a lost point message to the patch - outlet_list( x->x_outlet1, 0, 3, x->x_list ); - // post( "pdp_opencv_lk : lost point %d", im+1 ); - } - } - - if ( x->x_delaunay >= 0 ) - { - cvReleaseMemStorage( &x->x_storage ); - } - - CV_SWAP( x->prev_grey, x->grey, x->swap_temp ); - CV_SWAP( x->prev_pyramid, x->pyramid, x->swap_temp ); - CV_SWAP( x->points[0], x->points[1], x->swap_points ); - x->need_to_init = 0; - - memcpy( newdata, x->image->imageData, x->x_size*3 ); - return; -} - - -static void pdp_opencv_lk_winsize(t_pdp_opencv_lk *x, t_floatarg f) -{ - if (f>1.0) x->win_size = (int)f; -} - -static void pdp_opencv_lk_nightmode(t_pdp_opencv_lk *x, t_floatarg f) -{ - if ((f==0.0)||(f==1.0)) x->night_mode = (int)f; -} - -static void pdp_opencv_lk_quality(t_pdp_opencv_lk *x, t_floatarg f) -{ - if (f>0.0) x->quality = f; -} - -static void pdp_opencv_lk_mindistance(t_pdp_opencv_lk *x, t_floatarg f) -{ - if (f>1.0) x->min_distance = (int)f; -} - -static void pdp_opencv_lk_maxmove(t_pdp_opencv_lk *x, t_floatarg f) -{ - // has to be more than the size of a point - if (f>=3.0) x->x_maxmove = (int)f; -} - -static void pdp_opencv_lk_ftolerance(t_pdp_opencv_lk *x, t_floatarg f) -{ - if (f>0.0) x->x_ftolerance = (int)f; -} - -static void pdp_opencv_lk_delaunay(t_pdp_opencv_lk *x, t_symbol *s) -{ - if (s == gensym("on")) - x->x_delaunay = 0; - if (s == gensym("off")) - x->x_delaunay = -1; -} - -static void pdp_opencv_lk_pdelaunay(t_pdp_opencv_lk *x, t_floatarg point, t_floatarg threshold) -{ - if (((int)point>0) && ((int)pointx_delaunay = (int)point; - x->x_threshold = (int)threshold; - } -} - -static void pdp_opencv_lk_init(t_pdp_opencv_lk *x) -{ - x->need_to_init = 1; -} - -static void pdp_opencv_lk_mark(t_pdp_opencv_lk *x, t_symbol *s, int argc, t_atom *argv) -{ - int i; - int inserted; - int px,py; - - if ( argc == 1 ) // mark all - { - if ( argv[0].a_type != A_SYMBOL ) - { - error( "pdp_opencv_lk : wrong argument (should be 'all')" ); - return; - } - if ( !strcmp( argv[0].a_w.w_symbol->s_name, "all" ) ) - { - x->x_markall = 1; - return; - } - if ( !strcmp( argv[0].a_w.w_symbol->s_name, "none" ) ) - { - x->x_markall = 0; - pdp_opencv_lk_clear(x); - return; - } - } - else - { - if ( ( argv[0].a_type != A_FLOAT ) || ( argv[1].a_type != A_FLOAT ) ) - { - error( "pdp_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; - - if ( ( fperx < 0.0 ) || ( fperx > 1.0 ) || ( fpery < 0.0 ) || ( fpery > 1.0 ) ) - { - return; - } - - px = (int)(fperx*x->x_width); - py = (int)(fpery*x->x_height); - inserted = 0; - for ( i=0; ix_xmark[i] == -1 ) - { - x->x_xmark[i] = px; - x->x_ymark[i] = py; - x->x_found[i] = x->x_ftolerance; - inserted = 1; - break; - } - } - if ( !inserted ) - { - post( "pdp_opencv_lk : max markers reached" ); - } - } - } -} - -static void pdp_opencv_lk_delete(t_pdp_opencv_lk *x, t_floatarg findex ) -{ - int i; - - if ( ( findex < 1.0 ) || ( findex > MAX_MARKERS ) ) - { - return; - } - - x->x_xmark[(int)findex-1] = -1; - x->x_ymark[(int)findex-1] = -1; -} - -static void pdp_opencv_lk_clear(t_pdp_opencv_lk *x ) -{ - int i; - - for ( i=0; ix_xmark[i] = -1; - x->x_ymark[i] = -1; - } -} - -static void pdp_opencv_lk_sendpacket(t_pdp_opencv_lk *x) -{ - /* release the packet */ - pdp_packet_mark_unused(x->x_packet0); - x->x_packet0 = -1; - - /* unregister and propagate if valid dest packet */ - pdp_packet_pass_if_valid(x->x_outlet0, &x->x_packet1); -} - -static void pdp_opencv_lk_process(t_pdp_opencv_lk *x) -{ - int encoding; - t_pdp *header = 0; - char *parname; - unsigned pi; - int partype; - float pardefault; - t_atom plist[2]; - t_atom tlist[2]; - t_atom vlist[2]; - - /* check if image data packets are compatible */ - if ( (header = pdp_packet_header(x->x_packet0)) - && (PDP_BITMAP == header->type)){ - - /* pdp_opencv_lk_process inputs and write into active inlet */ - switch(pdp_packet_header(x->x_packet0)->info.image.encoding){ - - case PDP_BITMAP_RGB: - x->x_packet1 = pdp_packet_clone_rw(x->x_packet0); - pdp_queue_add(x, pdp_opencv_lk_process_rgb, pdp_opencv_lk_sendpacket, &x->x_queue_id); - break; - - default: - /* don't know the type, so dont pdp_opencv_lk_process */ - break; - - } - } - -} - -static void pdp_opencv_lk_input_0(t_pdp_opencv_lk *x, t_symbol *s, t_floatarg f) -{ - /* if this is a register_ro message or register_rw message, register with packet factory */ - - if (s == gensym("register_rw")) - x->x_dropped = pdp_packet_convert_ro_or_drop(&x->x_packet0, (int)f, pdp_gensym("bitmap/rgb/*") ); - - if ((s == gensym("process")) && (-1 != x->x_packet0) && (!x->x_dropped)) - { - /* add the process method and callback to the process queue */ - pdp_opencv_lk_process(x); - } -} - -static void pdp_opencv_lk_free(t_pdp_opencv_lk *x) -{ - int i; - - pdp_queue_finish(x->x_queue_id); - pdp_packet_mark_unused(x->x_packet0); - //cv_freeplugins(x); - - //Destroy cv_images - cvReleaseImage( &x->image ); - cvReleaseImage( &x->oimage ); - cvReleaseImage( &x->grey ); - cvReleaseImage( &x->prev_grey ); - cvReleaseImage( &x->pyramid ); - cvReleaseImage( &x->prev_pyramid ); -} - -t_class *pdp_opencv_lk_class; - - -void *pdp_opencv_lk_new(t_floatarg f) -{ - int i; - - t_pdp_opencv_lk *x = (t_pdp_opencv_lk *)pd_new(pdp_opencv_lk_class); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("win_size")); - - x->x_outlet0 = outlet_new(&x->x_obj, &s_anything); - x->x_outlet1 = outlet_new(&x->x_obj, &s_anything); - - x->x_packet0 = -1; - x->x_packet1 = -1; - x->x_queue_id = -1; - - x->x_width = 320; - x->x_height = 240; - x->x_size = x->x_width * x->x_height; - - x->win_size = 10; - - x->points [0] = 0; - x->points [1] = 0; - x->status = 0; - x->count = 0; - x->need_to_init = 1; - x->night_mode = 0; - x->flags = 0; - x->add_remove_pt = 0; - x->quality = 0.1; - x->min_distance = 10; - x->x_maxmove = 8; - x->x_ftolerance = 8; - x->x_delaunay = -1; - x->x_threshold = -1; - - x->x_markall = 0; - for ( i=0; ix_xmark[i] = -1; - x->x_ymark[i] = -1; - } - - // initialize font - cvInitFont( &x->font, CV_FONT_HERSHEY_PLAIN, 1.0, 1.0, 0, 1, 8 ); - - x->image = cvCreateImage( cvSize(x->x_width, x->x_height), 8, 3 ); - x->oimage = cvCreateImage( cvSize(x->x_width, x->x_height), 8, 3 ); - x->grey = cvCreateImage( cvSize(x->x_width, x->x_height), 8, 1 ); - x->prev_grey = cvCreateImage( cvSize(x->x_width, x->x_height), 8, 1 ); - x->pyramid = cvCreateImage( cvSize(x->x_width, x->x_height), 8, 1 ); - x->prev_pyramid = cvCreateImage( cvSize(x->x_width, x->x_height), 8, 1 ); - x->points[0] = (CvPoint2D32f*)cvAlloc(MAX_COUNT*sizeof(x->points[0][0])); - x->points[1] = (CvPoint2D32f*)cvAlloc(MAX_COUNT*sizeof(x->points[0][0])); - x->status = (char*)cvAlloc(MAX_COUNT); - - return (void *)x; -} - - -#ifdef __cplusplus -extern "C" -{ -#endif - - -void pdp_opencv_lk_setup(void) -{ - - post( " pdp_opencv_lk"); - pdp_opencv_lk_class = class_new(gensym("pdp_opencv_lk"), (t_newmethod)pdp_opencv_lk_new, - (t_method)pdp_opencv_lk_free, sizeof(t_pdp_opencv_lk), 0, A_DEFFLOAT, A_NULL); - - class_addmethod(pdp_opencv_lk_class, (t_method)pdp_opencv_lk_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL); - class_addmethod(pdp_opencv_lk_class, (t_method)pdp_opencv_lk_winsize, gensym("win_size"), A_FLOAT, A_NULL ); - class_addmethod(pdp_opencv_lk_class, (t_method)pdp_opencv_lk_nightmode, gensym("nightmode"), A_FLOAT, A_NULL ); - class_addmethod(pdp_opencv_lk_class, (t_method)pdp_opencv_lk_quality, gensym("quality"), A_FLOAT, A_NULL ); - class_addmethod(pdp_opencv_lk_class, (t_method)pdp_opencv_lk_init, gensym("init"), A_NULL ); - class_addmethod(pdp_opencv_lk_class, (t_method)pdp_opencv_lk_mark, gensym("mark"), A_GIMME, A_NULL ); - class_addmethod(pdp_opencv_lk_class, (t_method)pdp_opencv_lk_delete, gensym("delete"), A_FLOAT, A_NULL ); - class_addmethod(pdp_opencv_lk_class, (t_method)pdp_opencv_lk_clear, gensym("clear"), A_NULL ); - class_addmethod(pdp_opencv_lk_class, (t_method)pdp_opencv_lk_mindistance, gensym("mindistance"), A_FLOAT, A_NULL ); - class_addmethod(pdp_opencv_lk_class, (t_method)pdp_opencv_lk_maxmove, gensym("maxmove"), A_FLOAT, A_NULL ); - class_addmethod(pdp_opencv_lk_class, (t_method)pdp_opencv_lk_ftolerance, gensym("ftolerance"), A_FLOAT, A_NULL ); - class_addmethod(pdp_opencv_lk_class, (t_method)pdp_opencv_lk_delaunay, gensym("delaunay"), A_SYMBOL, A_NULL ); - class_addmethod(pdp_opencv_lk_class, (t_method)pdp_opencv_lk_pdelaunay, gensym("pdelaunay"), A_FLOAT, A_FLOAT, A_NULL ); - -} - -#ifdef __cplusplus -} -#endif diff --git a/pdp_opencv_lk.cc b/pdp_opencv_lk.cc new file mode 100755 index 0000000..432c4e7 --- /dev/null +++ b/pdp_opencv_lk.cc @@ -0,0 +1,700 @@ +/* + * Pure Data Packet module. + * Copyright (c) by Tom Schouten + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "pdp.h" + +#ifndef _EiC +#include "cv.h" +#endif + +#define MAX_MARKERS 500 +const int MAX_COUNT = 500; + +typedef struct pdp_opencv_lk_struct +{ + t_object x_obj; + t_float x_f; + + t_outlet *x_outlet0; + t_outlet *x_outlet1; + t_atom x_list[3]; + + int x_packet0; + int x_packet1; + int x_dropped; + int x_queue_id; + + int x_width; + int x_height; + int x_size; + + int win_size; + double quality; + int min_distance; + int x_maxmove; + int x_ftolerance; + int x_markall; + int x_delaunay; + int x_threshold; + int x_xmark[MAX_MARKERS]; + int x_ymark[MAX_MARKERS]; + int x_found[MAX_MARKERS]; + + // The output and temporary images + IplImage *image, *oimage, *grey, *prev_grey, *pyramid, *prev_pyramid, *swap_temp; + + CvPoint2D32f* points[2], *swap_points; + char* status; + int count; + int need_to_init; + int night_mode; + int flags; + int add_remove_pt; + CvPoint pt; + CvFont font; + + // structures needed for the delaunay + CvRect x_fullrect; + CvMemStorage* x_storage; + CvSubdiv2D* x_subdiv; + +} t_pdp_opencv_lk; + +static void pdp_opencv_lk_clear(t_pdp_opencv_lk *x); + +static void pdp_opencv_lk_process_rgb(t_pdp_opencv_lk *x) +{ + t_pdp *header = pdp_packet_header(x->x_packet0); + short int *data = (short int *)pdp_packet_data(x->x_packet0); + t_pdp *newheader = pdp_packet_header(x->x_packet1); + short int *newdata = (short int *)pdp_packet_data(x->x_packet1); + int i,j,k,im; + int marked; + + if ((x->x_width != (t_int)header->info.image.width) || + (x->x_height != (t_int)header->info.image.height) || (!x->image)) + { + + post("pdp_opencv_lk :: resizing plugins"); + + x->x_width = header->info.image.width; + x->x_height = header->info.image.height; + x->x_size = x->x_width*x->x_height; + + //Destroy cv_images + cvReleaseImage( &x->image ); + cvReleaseImage( &x->oimage ); + cvReleaseImage( &x->grey ); + cvReleaseImage( &x->prev_grey ); + cvReleaseImage( &x->pyramid ); + cvReleaseImage( &x->prev_pyramid ); + + //Create cv_images + x->image = cvCreateImage( cvSize(x->x_width, x->x_height), 8, 3 ); + x->oimage = cvCreateImage( cvSize(x->x_width, x->x_height), 8, 3 ); + x->grey = cvCreateImage( cvSize(x->x_width, x->x_height), 8, 1 ); + x->prev_grey = cvCreateImage( cvSize(x->x_width, x->x_height), 8, 1 ); + x->pyramid = cvCreateImage( cvSize(x->x_width, x->x_height), 8, 1 ); + x->prev_pyramid = cvCreateImage( cvSize(x->x_width, x->x_height), 8, 1 ); + x->points[0] = (CvPoint2D32f*)cvAlloc(MAX_COUNT*sizeof(x->points[0][0])); + x->points[1] = (CvPoint2D32f*)cvAlloc(MAX_COUNT*sizeof(x->points[0][0])); + x->status = (char*)cvAlloc(MAX_COUNT); + } + + newheader->info.image.encoding = header->info.image.encoding; + newheader->info.image.width = x->x_width; + newheader->info.image.height = x->x_height; + + memcpy( newdata, data, x->x_size*3 ); + + memcpy( x->image->imageData, data, x->x_size*3 ); + memcpy( x->oimage->imageData, data, x->x_size*3 ); + + cvCvtColor( x->image, x->grey, CV_RGB2GRAY ); + + if( x->night_mode ) + cvZero( x->image ); + + for ( im=0; imx_found[im]--; + } + + if ( x->x_delaunay >= 0 ) + { + // init data structures for the delaunay + x->x_fullrect.x = -x->x_width/2; + x->x_fullrect.y = -x->x_height/2; + x->x_fullrect.width = 2*x->x_width; + x->x_fullrect.height = 2*x->x_height; + + x->x_storage = cvCreateMemStorage(0); + x->x_subdiv = cvCreateSubdiv2D( CV_SEQ_KIND_SUBDIV2D, sizeof(*x->x_subdiv), + sizeof(CvSubdiv2DPoint), + sizeof(CvQuadEdge2D), + x->x_storage ); + cvInitSubdivDelaunay2D( x->x_subdiv, x->x_fullrect ); + } + + if( x->need_to_init ) + { + /* automatic initialization */ + IplImage* eig = cvCreateImage( cvSize(x->grey->width,x->grey->height), 32, 1 ); + IplImage* temp = cvCreateImage( cvSize(x->grey->width,x->grey->height), 32, 1 ); + + x->count = MAX_COUNT; + cvGoodFeaturesToTrack( x->grey, eig, temp, x->points[1], &x->count, + x->quality, x->min_distance, 0, 3, 0, 0.04 ); + cvFindCornerSubPix( x->grey, x->points[1], x->count, + cvSize(x->win_size,x->win_size), cvSize(-1,-1), + cvTermCriteria(CV_TERMCRIT_ITER|CV_TERMCRIT_EPS,20,0.03)); + cvReleaseImage( &eig ); + cvReleaseImage( &temp ); + + x->add_remove_pt = 0; + } + else if( x->count > 0 ) + { + cvCalcOpticalFlowPyrLK( x->prev_grey, x->grey, x->prev_pyramid, x->pyramid, + x->points[0], x->points[1], x->count, cvSize(x->win_size,x->win_size), 3, x->status, 0, + cvTermCriteria(CV_TERMCRIT_ITER|CV_TERMCRIT_EPS,20,0.03), x->flags ); + x->flags |= CV_LKFLOW_PYR_A_READY; + for( i = k = 0; i < x->count; i++ ) + { + if( x->add_remove_pt ) + { + double dx = x->pt.x - x->points[1][i].x; + double dy = x->pt.y - x->points[1][i].y; + + if( dx*dx + dy*dy <= 25 ) + { + x->add_remove_pt = 0; + continue; + } + } + + if( !x->status[i] ) + continue; + + x->points[1][k++] = x->points[1][i]; + + if ( x->x_delaunay == 0 ) // add all the points + { + cvSubdivDelaunay2DInsert( x->x_subdiv, x->points[1][i] ); + cvCalcSubdivVoronoi2D( x->x_subdiv ); + } + // only add points included in (color-threshold)x_delaunay > 0 ) && ( x->x_xmark[x->x_delaunay-1] != -1 ) ) + { + int px = cvPointFrom32f(x->points[1][i]).x; + int py = cvPointFrom32f(x->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 >= x->x_width ) ) continue; + if ( ( ppy < 0 ) || ( ppy >= x->x_height ) ) continue; + + uchar red = ((uchar*)(x->oimage->imageData + x->oimage->widthStep*ppx))[ppy*3]; + uchar green = ((uchar*)(x->oimage->imageData + x->oimage->widthStep*ppx))[ppy*3+1]; + uchar blue = ((uchar*)(x->oimage->imageData + x->oimage->widthStep*ppx))[ppy*3+2]; + + uchar pred = ((uchar*)(x->oimage->imageData + x->oimage->widthStep*x->x_xmark[x->x_delaunay-1]))[x->x_ymark[x->x_delaunay-1]*3]; + uchar pgreen = ((uchar*)(x->oimage->imageData + x->oimage->widthStep*x->x_xmark[x->x_delaunay-1]))[x->x_ymark[x->x_delaunay-1]*3+1]; + uchar pblue = ((uchar*)(x->oimage->imageData + x->oimage->widthStep*x->x_xmark[x->x_delaunay-1]))[x->x_ymark[x->x_delaunay-1]*3+2]; + + int diff = abs(red-pred) + abs(green-pgreen) + abs(blue-pblue); + + // post( "pdp_opencv_lk : point (%d,%d,%d) : diff : %d", blue, green, red, diff ); + + if ( diff < x->x_threshold ) + { + cvSubdivDelaunay2DInsert( x->x_subdiv, x->points[1][i] ); + cvCalcSubdivVoronoi2D( x->x_subdiv ); + } + } + } + } + + cvCircle( x->image, cvPointFrom32f(x->points[1][i]), 3, CV_RGB(0,255,0), -1, 8,0); + + marked=0; + for ( im=0; imx_xmark[im] != -1.0 ) + { + if ( ( abs( x->points[1][i].x - x->x_xmark[im] ) <= x->x_maxmove ) && ( abs( x->points[1][i].y - x->x_ymark[im] ) <= x->x_maxmove ) ) + { + char tindex[4]; + sprintf( tindex, "%d", im+1 ); + cvPutText( x->image, tindex, cvPointFrom32f(x->points[1][i]), &x->font, CV_RGB(255,255,255)); + x->x_xmark[im]=x->points[1][i].x; + x->x_ymark[im]=x->points[1][i].y; + x->x_found[im]=x->x_ftolerance; + marked=1; + SETFLOAT(&x->x_list[0], im+1); + SETFLOAT(&x->x_list[1], x->x_xmark[im]); + SETFLOAT(&x->x_list[2], x->x_ymark[im]); + outlet_list( x->x_outlet1, 0, 3, x->x_list ); + } + } + } + + if ( x->x_markall && !marked ) + { + for ( im=0; imx_xmark[im] == -1 ) + { + x->x_xmark[im]=x->points[1][i].x; + x->x_ymark[im]=x->points[1][i].y; + x->x_found[im]=x->x_ftolerance; + break; + } + } + } + } + x->count = k; + } + + if( x->add_remove_pt && x->count < MAX_COUNT ) + { + x->points[1][x->count++] = cvPointTo32f(x->pt); + cvFindCornerSubPix( x->grey, x->points[1] + x->count - 1, 1, + cvSize(x->win_size,x->win_size), cvSize(-1,-1), + cvTermCriteria(CV_TERMCRIT_ITER|CV_TERMCRIT_EPS,20,0.03)); + x->add_remove_pt = 0; + } + + // draw the delaunay + if ( x->x_delaunay >= 0 ) + { + CvSeqReader reader; + int i, total = x->x_subdiv->edges->total; + int elem_size = x->x_subdiv->edges->elem_size; + + cvStartReadSeq( (CvSeq*)(x->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 < x->x_width ) && + ( dst.x > 0 ) && ( dst.x < x->x_width ) && + ( org.y > 0 ) && ( org.y < x->x_height ) && + ( dst.y > 0 ) && ( dst.y < x->x_height ) ) + cvLine( x->image, iorg, idst, CV_RGB(255,0,0), 1, CV_AA, 0 ); + } + } + + // draw the voronoi : useless in my opinion as points belongs to contours + /* + if( CV_IS_SET_ELEM( edge+1 )) + { + org_pt = cvSubdiv2DEdgeOrg((CvSubdiv2DEdge)edge+1); + dst_pt = cvSubdiv2DEdgeDst((CvSubdiv2DEdge)edge+1); + + 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 )); + + cvLine( x->image, iorg, idst, CV_RGB(0,0,255), 1, CV_AA, 0 ); + } + } + */ + + CV_NEXT_SEQ_ELEM( elem_size, reader ); + } + } + + for ( im=0; imx_xmark[im] != -1.0 ) && !x->x_found[im] ) + { + // lost the point + x->x_xmark[im]=-1.0; + x->x_ymark[im]=-1.0; + SETFLOAT(&x->x_list[0], im+1); + SETFLOAT(&x->x_list[1], x->x_xmark[im]); + SETFLOAT(&x->x_list[2], x->x_ymark[im]); + // send a lost point message to the patch + outlet_list( x->x_outlet1, 0, 3, x->x_list ); + // post( "pdp_opencv_lk : lost point %d", im+1 ); + } + } + + if ( x->x_delaunay >= 0 ) + { + cvReleaseMemStorage( &x->x_storage ); + } + + CV_SWAP( x->prev_grey, x->grey, x->swap_temp ); + CV_SWAP( x->prev_pyramid, x->pyramid, x->swap_temp ); + CV_SWAP( x->points[0], x->points[1], x->swap_points ); + x->need_to_init = 0; + + memcpy( newdata, x->image->imageData, x->x_size*3 ); + return; +} + + +static void pdp_opencv_lk_winsize(t_pdp_opencv_lk *x, t_floatarg f) +{ + if (f>1.0) x->win_size = (int)f; +} + +static void pdp_opencv_lk_nightmode(t_pdp_opencv_lk *x, t_floatarg f) +{ + if ((f==0.0)||(f==1.0)) x->night_mode = (int)f; +} + +static void pdp_opencv_lk_quality(t_pdp_opencv_lk *x, t_floatarg f) +{ + if (f>0.0) x->quality = f; +} + +static void pdp_opencv_lk_mindistance(t_pdp_opencv_lk *x, t_floatarg f) +{ + if (f>1.0) x->min_distance = (int)f; +} + +static void pdp_opencv_lk_maxmove(t_pdp_opencv_lk *x, t_floatarg f) +{ + // has to be more than the size of a point + if (f>=3.0) x->x_maxmove = (int)f; +} + +static void pdp_opencv_lk_ftolerance(t_pdp_opencv_lk *x, t_floatarg f) +{ + if (f>0.0) x->x_ftolerance = (int)f; +} + +static void pdp_opencv_lk_delaunay(t_pdp_opencv_lk *x, t_symbol *s) +{ + if (s == gensym("on")) + x->x_delaunay = 0; + if (s == gensym("off")) + x->x_delaunay = -1; +} + +static void pdp_opencv_lk_pdelaunay(t_pdp_opencv_lk *x, t_floatarg point, t_floatarg threshold) +{ + if (((int)point>0) && ((int)pointx_delaunay = (int)point; + x->x_threshold = (int)threshold; + } +} + +static void pdp_opencv_lk_init(t_pdp_opencv_lk *x) +{ + x->need_to_init = 1; +} + +static void pdp_opencv_lk_mark(t_pdp_opencv_lk *x, t_symbol *s, int argc, t_atom *argv) +{ + int i; + int inserted; + int px,py; + + if ( argc == 1 ) // mark all + { + if ( argv[0].a_type != A_SYMBOL ) + { + error( "pdp_opencv_lk : wrong argument (should be 'all')" ); + return; + } + if ( !strcmp( argv[0].a_w.w_symbol->s_name, "all" ) ) + { + x->x_markall = 1; + return; + } + if ( !strcmp( argv[0].a_w.w_symbol->s_name, "none" ) ) + { + x->x_markall = 0; + pdp_opencv_lk_clear(x); + return; + } + } + else + { + if ( ( argv[0].a_type != A_FLOAT ) || ( argv[1].a_type != A_FLOAT ) ) + { + error( "pdp_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; + + if ( ( fperx < 0.0 ) || ( fperx > 1.0 ) || ( fpery < 0.0 ) || ( fpery > 1.0 ) ) + { + return; + } + + px = (int)(fperx*x->x_width); + py = (int)(fpery*x->x_height); + inserted = 0; + for ( i=0; ix_xmark[i] == -1 ) + { + x->x_xmark[i] = px; + x->x_ymark[i] = py; + x->x_found[i] = x->x_ftolerance; + inserted = 1; + break; + } + } + if ( !inserted ) + { + post( "pdp_opencv_lk : max markers reached" ); + } + } + } +} + +static void pdp_opencv_lk_delete(t_pdp_opencv_lk *x, t_floatarg findex ) +{ + int i; + + if ( ( findex < 1.0 ) || ( findex > MAX_MARKERS ) ) + { + return; + } + + x->x_xmark[(int)findex-1] = -1; + x->x_ymark[(int)findex-1] = -1; +} + +static void pdp_opencv_lk_clear(t_pdp_opencv_lk *x ) +{ + int i; + + for ( i=0; ix_xmark[i] = -1; + x->x_ymark[i] = -1; + } +} + +static void pdp_opencv_lk_sendpacket(t_pdp_opencv_lk *x) +{ + /* release the packet */ + pdp_packet_mark_unused(x->x_packet0); + x->x_packet0 = -1; + + /* unregister and propagate if valid dest packet */ + pdp_packet_pass_if_valid(x->x_outlet0, &x->x_packet1); +} + +static void pdp_opencv_lk_process(t_pdp_opencv_lk *x) +{ + int encoding; + t_pdp *header = 0; + char *parname; + unsigned pi; + int partype; + float pardefault; + t_atom plist[2]; + t_atom tlist[2]; + t_atom vlist[2]; + + /* check if image data packets are compatible */ + if ( (header = pdp_packet_header(x->x_packet0)) + && (PDP_BITMAP == header->type)){ + + /* pdp_opencv_lk_process inputs and write into active inlet */ + switch(pdp_packet_header(x->x_packet0)->info.image.encoding){ + + case PDP_BITMAP_RGB: + x->x_packet1 = pdp_packet_clone_rw(x->x_packet0); + pdp_queue_add(x, (void*)pdp_opencv_lk_process_rgb, (void*)pdp_opencv_lk_sendpacket, &x->x_queue_id); + break; + + default: + /* don't know the type, so dont pdp_opencv_lk_process */ + break; + + } + } + +} + +static void pdp_opencv_lk_input_0(t_pdp_opencv_lk *x, t_symbol *s, t_floatarg f) +{ + /* if this is a register_ro message or register_rw message, register with packet factory */ + + if (s == gensym("register_rw")) + x->x_dropped = pdp_packet_convert_ro_or_drop(&x->x_packet0, (int)f, pdp_gensym((char*)"bitmap/rgb/*") ); + + if ((s == gensym("process")) && (-1 != x->x_packet0) && (!x->x_dropped)) + { + /* add the process method and callback to the process queue */ + pdp_opencv_lk_process(x); + } +} + +static void pdp_opencv_lk_free(t_pdp_opencv_lk *x) +{ + int i; + + pdp_queue_finish(x->x_queue_id); + pdp_packet_mark_unused(x->x_packet0); + //cv_freeplugins(x); + + //Destroy cv_images + cvReleaseImage( &x->image ); + cvReleaseImage( &x->oimage ); + cvReleaseImage( &x->grey ); + cvReleaseImage( &x->prev_grey ); + cvReleaseImage( &x->pyramid ); + cvReleaseImage( &x->prev_pyramid ); +} + +t_class *pdp_opencv_lk_class; + + +void *pdp_opencv_lk_new(t_floatarg f) +{ + int i; + + t_pdp_opencv_lk *x = (t_pdp_opencv_lk *)pd_new(pdp_opencv_lk_class); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("win_size")); + + x->x_outlet0 = outlet_new(&x->x_obj, &s_anything); + x->x_outlet1 = outlet_new(&x->x_obj, &s_anything); + + x->x_packet0 = -1; + x->x_packet1 = -1; + x->x_queue_id = -1; + + x->x_width = 320; + x->x_height = 240; + x->x_size = x->x_width * x->x_height; + + x->win_size = 10; + + x->points [0] = 0; + x->points [1] = 0; + x->status = 0; + x->count = 0; + x->need_to_init = 1; + x->night_mode = 0; + x->flags = 0; + x->add_remove_pt = 0; + x->quality = 0.1; + x->min_distance = 10; + x->x_maxmove = 8; + x->x_ftolerance = 8; + x->x_delaunay = -1; + x->x_threshold = -1; + + x->x_markall = 0; + for ( i=0; ix_xmark[i] = -1; + x->x_ymark[i] = -1; + } + + // initialize font + cvInitFont( &x->font, CV_FONT_HERSHEY_PLAIN, 1.0, 1.0, 0, 1, 8 ); + + x->image = cvCreateImage( cvSize(x->x_width, x->x_height), 8, 3 ); + x->oimage = cvCreateImage( cvSize(x->x_width, x->x_height), 8, 3 ); + x->grey = cvCreateImage( cvSize(x->x_width, x->x_height), 8, 1 ); + x->prev_grey = cvCreateImage( cvSize(x->x_width, x->x_height), 8, 1 ); + x->pyramid = cvCreateImage( cvSize(x->x_width, x->x_height), 8, 1 ); + x->prev_pyramid = cvCreateImage( cvSize(x->x_width, x->x_height), 8, 1 ); + x->points[0] = (CvPoint2D32f*)cvAlloc(MAX_COUNT*sizeof(x->points[0][0])); + x->points[1] = (CvPoint2D32f*)cvAlloc(MAX_COUNT*sizeof(x->points[0][0])); + x->status = (char*)cvAlloc(MAX_COUNT); + + return (void *)x; +} + + +#ifdef __cplusplus +extern "C" +{ +#endif + + +void pdp_opencv_lk_setup(void) +{ + + post( " pdp_opencv_lk"); + pdp_opencv_lk_class = class_new(gensym("pdp_opencv_lk"), (t_newmethod)pdp_opencv_lk_new, + (t_method)pdp_opencv_lk_free, sizeof(t_pdp_opencv_lk), 0, A_DEFFLOAT, A_NULL); + + class_addmethod(pdp_opencv_lk_class, (t_method)pdp_opencv_lk_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL); + class_addmethod(pdp_opencv_lk_class, (t_method)pdp_opencv_lk_winsize, gensym("win_size"), A_FLOAT, A_NULL ); + class_addmethod(pdp_opencv_lk_class, (t_method)pdp_opencv_lk_nightmode, gensym("nightmode"), A_FLOAT, A_NULL ); + class_addmethod(pdp_opencv_lk_class, (t_method)pdp_opencv_lk_quality, gensym("quality"), A_FLOAT, A_NULL ); + class_addmethod(pdp_opencv_lk_class, (t_method)pdp_opencv_lk_init, gensym("init"), A_NULL ); + class_addmethod(pdp_opencv_lk_class, (t_method)pdp_opencv_lk_mark, gensym("mark"), A_GIMME, A_NULL ); + class_addmethod(pdp_opencv_lk_class, (t_method)pdp_opencv_lk_delete, gensym("delete"), A_FLOAT, A_NULL ); + class_addmethod(pdp_opencv_lk_class, (t_method)pdp_opencv_lk_clear, gensym("clear"), A_NULL ); + class_addmethod(pdp_opencv_lk_class, (t_method)pdp_opencv_lk_mindistance, gensym("mindistance"), A_FLOAT, A_NULL ); + class_addmethod(pdp_opencv_lk_class, (t_method)pdp_opencv_lk_maxmove, gensym("maxmove"), A_FLOAT, A_NULL ); + class_addmethod(pdp_opencv_lk_class, (t_method)pdp_opencv_lk_ftolerance, gensym("ftolerance"), A_FLOAT, A_NULL ); + class_addmethod(pdp_opencv_lk_class, (t_method)pdp_opencv_lk_delaunay, gensym("delaunay"), A_SYMBOL, A_NULL ); + class_addmethod(pdp_opencv_lk_class, (t_method)pdp_opencv_lk_pdelaunay, gensym("pdelaunay"), A_FLOAT, A_FLOAT, A_NULL ); + +} + +#ifdef __cplusplus +} +#endif diff --git a/pdp_opencv_morphology.c b/pdp_opencv_morphology.c deleted file mode 100644 index 6e4b9bc..0000000 --- a/pdp_opencv_morphology.c +++ /dev/null @@ -1,299 +0,0 @@ -/* - * Pure Data Packet module. - * Copyright (c) by Tom Schouten - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include -#include -#include -#include -#include -#include - -#include "pdp.h" - -#ifndef _EiC -#include "cv.h" -#endif - -typedef struct pdp_opencv_morphology_struct -{ - t_object x_obj; - t_float x_f; - - t_outlet *x_outlet0; - int x_packet0; - int x_packet1; - int x_dropped; - int x_queue_id; - - int x_width; - int x_height; - int x_size; - - int x_infosok; - - int pos; - int element_shape; - int mode; //to switch between openclose or dilateerode modes - - // The output and temporary images - IplImage* src; - IplImage* dst; - - IplConvKernel* element; - -} t_pdp_opencv_morphology; - - -// callback function for open/close trackbar -void pdp_opencv_morphology_OpenClose(t_pdp_opencv_morphology *x, int pos) -{ - int n = x->pos; - int an = n > 0 ? n : -n; - x->element = cvCreateStructuringElementEx( an*2+1, an*2+1, an, an, x->element_shape, 0 ); - if( n < 0 ) - { - cvErode(x->src,x->dst,x->element,1); - cvDilate(x->dst,x->dst,x->element,1); - } - else - { - cvDilate(x->src,x->dst,x->element,1); - cvErode(x->dst,x->dst,x->element,1); - } - cvReleaseStructuringElement(&x->element); -} - -// callback function for erode/dilate trackbar -void pdp_opencv_morphology_ErodeDilate(t_pdp_opencv_morphology *x, int pos) -{ - int n = x->pos; - int an = n > 0 ? n : -n; - x->element = cvCreateStructuringElementEx( an*2+1, an*2+1, an, an, x->element_shape, 0 ); - if( n < 0 ) - { - cvErode(x->src,x->dst,x->element,1); - } - else - { - cvDilate(x->src,x->dst,x->element,1); - } - cvReleaseStructuringElement(&x->element); -} - - -static void pdp_opencv_morphology_process_rgb(t_pdp_opencv_morphology *x) -{ - t_pdp *header = pdp_packet_header(x->x_packet0); - short int *data = (short int *)pdp_packet_data(x->x_packet0); - t_pdp *newheader = pdp_packet_header(x->x_packet1); - short int *newdata = (short int *)pdp_packet_data(x->x_packet1); - int i; - - - if ((x->x_width != (t_int)header->info.image.width) || - (x->x_height != (t_int)header->info.image.height)) - { - - post("pdp_opencv_morphology :: resizing plugins"); - - //cv_freeplugins(x); - - x->x_width = header->info.image.width; - x->x_height = header->info.image.height; - x->x_size = x->x_width*x->x_height; - - //Destroy cv_images - cvReleaseImage( &x->src ); - cvReleaseImage( &x->dst ); - - //Create cv_images - x->src = cvCreateImage( cvSize(x->x_width,x->x_height), 8, 3 ); - x->dst = cvCloneImage(x->src); - } - - newheader->info.image.encoding = header->info.image.encoding; - newheader->info.image.width = x->x_width; - newheader->info.image.height = x->x_height; - - memcpy( newdata, data, x->x_size*3 ); - - - // FEM UNA COPIA DEL PACKET A x->grey->imageData ... http://www.cs.iit.edu/~agam/cs512/lect-notes/opencv-intro/opencv-intro.html aqui veiem la estructura de IplImage - memcpy( x->src->imageData, data, x->x_size*3 ); - - if (x->mode==1) pdp_opencv_morphology_OpenClose(x,x->pos); - else pdp_opencv_morphology_ErodeDilate(x,x->pos); - - memcpy( newdata, x->dst->imageData, x->x_size*3 ); - - return; -} - -static void pdp_opencv_morphology_shape(t_pdp_opencv_morphology *x, t_floatarg f) -{ - if( (int)f == 1 ) - x->element_shape = CV_SHAPE_RECT; - else if( (int)f == 2 ) - x->element_shape = CV_SHAPE_ELLIPSE; - else if( (int)f == 3 ) - x->element_shape = CV_SHAPE_CROSS; - -} - -static void pdp_opencv_morphology_mode(t_pdp_opencv_morphology *x, t_floatarg f) -{ - int v = (int)f; - if (v<0) v=0; - else if (v>1) v=1; - - x->mode=(int)v; -} - -static void pdp_opencv_morphology_pos(t_pdp_opencv_morphology *x, t_floatarg f) -{ - x->pos = (int)f; -} - -static void pdp_opencv_morphology_sendpacket(t_pdp_opencv_morphology *x) -{ - /* release the packet */ - pdp_packet_mark_unused(x->x_packet0); - x->x_packet0 = -1; - - /* unregister and propagate if valid dest packet */ - pdp_packet_pass_if_valid(x->x_outlet0, &x->x_packet1); -} - -static void pdp_opencv_morphology_process(t_pdp_opencv_morphology *x) -{ - int encoding; - t_pdp *header = 0; - char *parname; - unsigned pi; - int partype; - float pardefault; - t_atom plist[2]; - t_atom tlist[2]; - t_atom vlist[2]; - - /* check if image data packets are compatible */ - if ( (header = pdp_packet_header(x->x_packet0)) - && (PDP_BITMAP == header->type)){ - - /* pdp_opencv_morphology_process inputs and write into active inlet */ - switch(pdp_packet_header(x->x_packet0)->info.image.encoding){ - - case PDP_BITMAP_RGB: - x->x_packet1 = pdp_packet_clone_rw(x->x_packet0); - pdp_queue_add(x, pdp_opencv_morphology_process_rgb, pdp_opencv_morphology_sendpacket, &x->x_queue_id); - break; - - default: - /* don't know the type, so dont pdp_opencv_morphology_process */ - break; - - } - } - -} - -static void pdp_opencv_morphology_input_0(t_pdp_opencv_morphology *x, t_symbol *s, t_floatarg f) -{ - /* if this is a register_ro message or register_rw message, register with packet factory */ - - if (s == gensym("register_rw")) - x->x_dropped = pdp_packet_convert_ro_or_drop(&x->x_packet0, (int)f, pdp_gensym("bitmap/rgb/*") ); - - if ((s == gensym("process")) && (-1 != x->x_packet0) && (!x->x_dropped)) - { - /* add the process method and callback to the process queue */ - pdp_opencv_morphology_process(x); - } -} - -static void pdp_opencv_morphology_free(t_pdp_opencv_morphology *x) -{ - int i; - - pdp_queue_finish(x->x_queue_id); - pdp_packet_mark_unused(x->x_packet0); - - //Destroy cv_images - cvReleaseImage( &x->src ); - cvReleaseImage( &x->dst ); -} - -t_class *pdp_opencv_morphology_class; - -void *pdp_opencv_morphology_new(t_floatarg f) -{ - int i; - - t_pdp_opencv_morphology *x = (t_pdp_opencv_morphology *)pd_new(pdp_opencv_morphology_class); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("pos")); - - x->x_outlet0 = outlet_new(&x->x_obj, &s_anything); - - x->x_packet0 = -1; - x->x_packet1 = -1; - x->x_queue_id = -1; - - x->x_width = 320; - x->x_height = 240; - x->x_size = x->x_width * x->x_height; - - x->x_infosok = 0; - - x->element_shape = CV_SHAPE_RECT; - x->pos = 0; - x->mode = 0; - - x->element = 0; - - x->src = cvCreateImage( cvSize(x->x_width,x->x_height), 8, 3 ); - x->dst = cvCloneImage(x->src); - - return (void *)x; -} - - -#ifdef __cplusplus -extern "C" -{ -#endif - - -void pdp_opencv_morphology_setup(void) -{ - - post( " pdp_opencv_morphology"); - pdp_opencv_morphology_class = class_new(gensym("pdp_opencv_morphology"), (t_newmethod)pdp_opencv_morphology_new, - (t_method)pdp_opencv_morphology_free, sizeof(t_pdp_opencv_morphology), 0, A_DEFFLOAT, A_NULL); - - class_addmethod(pdp_opencv_morphology_class, (t_method)pdp_opencv_morphology_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL); - class_addmethod(pdp_opencv_morphology_class, (t_method)pdp_opencv_morphology_pos, gensym("pos"), A_FLOAT, A_NULL ); - class_addmethod(pdp_opencv_morphology_class, (t_method)pdp_opencv_morphology_mode, gensym("mode"), A_FLOAT, A_NULL); - class_addmethod(pdp_opencv_morphology_class, (t_method)pdp_opencv_morphology_shape, gensym("shape"), A_FLOAT, A_NULL); - -} - -#ifdef __cplusplus -} -#endif diff --git a/pdp_opencv_morphology.cc b/pdp_opencv_morphology.cc new file mode 100755 index 0000000..4fada73 --- /dev/null +++ b/pdp_opencv_morphology.cc @@ -0,0 +1,299 @@ +/* + * Pure Data Packet module. + * Copyright (c) by Tom Schouten + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include + +#include "pdp.h" + +#ifndef _EiC +#include "cv.h" +#endif + +typedef struct pdp_opencv_morphology_struct +{ + t_object x_obj; + t_float x_f; + + t_outlet *x_outlet0; + int x_packet0; + int x_packet1; + int x_dropped; + int x_queue_id; + + int x_width; + int x_height; + int x_size; + + int x_infosok; + + int pos; + int element_shape; + int mode; //to switch between openclose or dilateerode modes + + // The output and temporary images + IplImage* src; + IplImage* dst; + + IplConvKernel* element; + +} t_pdp_opencv_morphology; + + +// callback function for open/close trackbar +void pdp_opencv_morphology_OpenClose(t_pdp_opencv_morphology *x, int pos) +{ + int n = x->pos; + int an = n > 0 ? n : -n; + x->element = cvCreateStructuringElementEx( an*2+1, an*2+1, an, an, x->element_shape, 0 ); + if( n < 0 ) + { + cvErode(x->src,x->dst,x->element,1); + cvDilate(x->dst,x->dst,x->element,1); + } + else + { + cvDilate(x->src,x->dst,x->element,1); + cvErode(x->dst,x->dst,x->element,1); + } + cvReleaseStructuringElement(&x->element); +} + +// callback function for erode/dilate trackbar +void pdp_opencv_morphology_ErodeDilate(t_pdp_opencv_morphology *x, int pos) +{ + int n = x->pos; + int an = n > 0 ? n : -n; + x->element = cvCreateStructuringElementEx( an*2+1, an*2+1, an, an, x->element_shape, 0 ); + if( n < 0 ) + { + cvErode(x->src,x->dst,x->element,1); + } + else + { + cvDilate(x->src,x->dst,x->element,1); + } + cvReleaseStructuringElement(&x->element); +} + + +static void pdp_opencv_morphology_process_rgb(t_pdp_opencv_morphology *x) +{ + t_pdp *header = pdp_packet_header(x->x_packet0); + short int *data = (short int *)pdp_packet_data(x->x_packet0); + t_pdp *newheader = pdp_packet_header(x->x_packet1); + short int *newdata = (short int *)pdp_packet_data(x->x_packet1); + int i; + + + if ((x->x_width != (t_int)header->info.image.width) || + (x->x_height != (t_int)header->info.image.height)) + { + + post("pdp_opencv_morphology :: resizing plugins"); + + //cv_freeplugins(x); + + x->x_width = header->info.image.width; + x->x_height = header->info.image.height; + x->x_size = x->x_width*x->x_height; + + //Destroy cv_images + cvReleaseImage( &x->src ); + cvReleaseImage( &x->dst ); + + //Create cv_images + x->src = cvCreateImage( cvSize(x->x_width,x->x_height), 8, 3 ); + x->dst = cvCloneImage(x->src); + } + + newheader->info.image.encoding = header->info.image.encoding; + newheader->info.image.width = x->x_width; + newheader->info.image.height = x->x_height; + + memcpy( newdata, data, x->x_size*3 ); + + + // FEM UNA COPIA DEL PACKET A x->grey->imageData ... http://www.cs.iit.edu/~agam/cs512/lect-notes/opencv-intro/opencv-intro.html aqui veiem la estructura de IplImage + memcpy( x->src->imageData, data, x->x_size*3 ); + + if (x->mode==1) pdp_opencv_morphology_OpenClose(x,x->pos); + else pdp_opencv_morphology_ErodeDilate(x,x->pos); + + memcpy( newdata, x->dst->imageData, x->x_size*3 ); + + return; +} + +static void pdp_opencv_morphology_shape(t_pdp_opencv_morphology *x, t_floatarg f) +{ + if( (int)f == 1 ) + x->element_shape = CV_SHAPE_RECT; + else if( (int)f == 2 ) + x->element_shape = CV_SHAPE_ELLIPSE; + else if( (int)f == 3 ) + x->element_shape = CV_SHAPE_CROSS; + +} + +static void pdp_opencv_morphology_mode(t_pdp_opencv_morphology *x, t_floatarg f) +{ + int v = (int)f; + if (v<0) v=0; + else if (v>1) v=1; + + x->mode=(int)v; +} + +static void pdp_opencv_morphology_pos(t_pdp_opencv_morphology *x, t_floatarg f) +{ + x->pos = (int)f; +} + +static void pdp_opencv_morphology_sendpacket(t_pdp_opencv_morphology *x) +{ + /* release the packet */ + pdp_packet_mark_unused(x->x_packet0); + x->x_packet0 = -1; + + /* unregister and propagate if valid dest packet */ + pdp_packet_pass_if_valid(x->x_outlet0, &x->x_packet1); +} + +static void pdp_opencv_morphology_process(t_pdp_opencv_morphology *x) +{ + int encoding; + t_pdp *header = 0; + char *parname; + unsigned pi; + int partype; + float pardefault; + t_atom plist[2]; + t_atom tlist[2]; + t_atom vlist[2]; + + /* check if image data packets are compatible */ + if ( (header = pdp_packet_header(x->x_packet0)) + && (PDP_BITMAP == header->type)){ + + /* pdp_opencv_morphology_process inputs and write into active inlet */ + switch(pdp_packet_header(x->x_packet0)->info.image.encoding){ + + case PDP_BITMAP_RGB: + x->x_packet1 = pdp_packet_clone_rw(x->x_packet0); + pdp_queue_add(x, (void*)pdp_opencv_morphology_process_rgb, (void*)pdp_opencv_morphology_sendpacket, &x->x_queue_id); + break; + + default: + /* don't know the type, so dont pdp_opencv_morphology_process */ + break; + + } + } + +} + +static void pdp_opencv_morphology_input_0(t_pdp_opencv_morphology *x, t_symbol *s, t_floatarg f) +{ + /* if this is a register_ro message or register_rw message, register with packet factory */ + + if (s == gensym("register_rw")) + x->x_dropped = pdp_packet_convert_ro_or_drop(&x->x_packet0, (int)f, pdp_gensym((char*)"bitmap/rgb/*") ); + + if ((s == gensym("process")) && (-1 != x->x_packet0) && (!x->x_dropped)) + { + /* add the process method and callback to the process queue */ + pdp_opencv_morphology_process(x); + } +} + +static void pdp_opencv_morphology_free(t_pdp_opencv_morphology *x) +{ + int i; + + pdp_queue_finish(x->x_queue_id); + pdp_packet_mark_unused(x->x_packet0); + + //Destroy cv_images + cvReleaseImage( &x->src ); + cvReleaseImage( &x->dst ); +} + +t_class *pdp_opencv_morphology_class; + +void *pdp_opencv_morphology_new(t_floatarg f) +{ + int i; + + t_pdp_opencv_morphology *x = (t_pdp_opencv_morphology *)pd_new(pdp_opencv_morphology_class); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("pos")); + + x->x_outlet0 = outlet_new(&x->x_obj, &s_anything); + + x->x_packet0 = -1; + x->x_packet1 = -1; + x->x_queue_id = -1; + + x->x_width = 320; + x->x_height = 240; + x->x_size = x->x_width * x->x_height; + + x->x_infosok = 0; + + x->element_shape = CV_SHAPE_RECT; + x->pos = 0; + x->mode = 0; + + x->element = 0; + + x->src = cvCreateImage( cvSize(x->x_width,x->x_height), 8, 3 ); + x->dst = cvCloneImage(x->src); + + return (void *)x; +} + + +#ifdef __cplusplus +extern "C" +{ +#endif + + +void pdp_opencv_morphology_setup(void) +{ + + post( " pdp_opencv_morphology"); + pdp_opencv_morphology_class = class_new(gensym("pdp_opencv_morphology"), (t_newmethod)pdp_opencv_morphology_new, + (t_method)pdp_opencv_morphology_free, sizeof(t_pdp_opencv_morphology), 0, A_DEFFLOAT, A_NULL); + + class_addmethod(pdp_opencv_morphology_class, (t_method)pdp_opencv_morphology_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL); + class_addmethod(pdp_opencv_morphology_class, (t_method)pdp_opencv_morphology_pos, gensym("pos"), A_FLOAT, A_NULL ); + class_addmethod(pdp_opencv_morphology_class, (t_method)pdp_opencv_morphology_mode, gensym("mode"), A_FLOAT, A_NULL); + class_addmethod(pdp_opencv_morphology_class, (t_method)pdp_opencv_morphology_shape, gensym("shape"), A_FLOAT, A_NULL); + +} + +#ifdef __cplusplus +} +#endif diff --git a/pdp_opencv_motempl.c b/pdp_opencv_motempl.c deleted file mode 100644 index 53808f9..0000000 --- a/pdp_opencv_motempl.c +++ /dev/null @@ -1,468 +0,0 @@ -/* - * Pure Data Packet module. - * Copyright (c) by Tom Schouten - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include -#include -#include -#include -#include -#include - -#include "pdp.h" - -#ifndef _EiC -#include "cv.h" -#include -#include -#include -#endif - -typedef struct pdp_opencv_motempl_struct -{ - t_object x_obj; - t_float x_f; - - t_outlet *x_outlet0; - t_outlet *x_dataout; - int x_packet0; - int x_packet1; - int x_dropped; - int x_queue_id; - - int x_width; - int x_height; - int x_size; - - int x_thresh; - double x_mhi_duration; - int x_aperture; - - int x_infosok; - - // ring image buffer - IplImage **buf; - int last; - - // temporary images - IplImage *mhi; // MHI - IplImage *orient; // orientation - IplImage *mask; // valid orientation mask - IplImage *segmask; // motion segmentation map - CvMemStorage* storage; // temporary storage - CvFont font; - - IplImage* image; - IplImage* motion; - - // various tracking parameters (in seconds) - double max_time_delta; - double min_time_delta; - - // number of cyclic frame buffer used for motion detection - // (should, probably, depend on FPS) - int frame_buffer_num; - - int max_size; - int min_size; - - t_atom rlist[6]; - -} t_pdp_opencv_motempl; - -void pdp_opencv_motempl_update_mhi( t_pdp_opencv_motempl *x, IplImage* img, IplImage* dst, int diff_threshold ) -{ - double timestamp = (double)clock()/CLOCKS_PER_SEC; // get current time in seconds - CvSize size = cvSize(img->width,img->height); // get current frame size - int i, j, idx1 = x->last, idx2; - IplImage* silh; - CvSeq* seq; - CvRect comp_rect; - double count; - double angle; - CvPoint center; - double magnitude; - CvScalar color; - char tindex[10]; - - // allocate images at the beginning or - // reallocate them if the frame size is changed - if( !x->mhi || x->mhi->width != size.width || x->mhi->height != size.height || !x->buf ) { - if( x->buf == 0 ) { - x->buf = (IplImage**)malloc(x->frame_buffer_num*sizeof(x->buf[0])); - memset( x->buf, 0, x->frame_buffer_num*sizeof(x->buf[0])); - } - - for( i = 0; i < x->frame_buffer_num; i++ ) { - cvReleaseImage( &x->buf[i] ); - x->buf[i] = cvCreateImage( size, IPL_DEPTH_8U, 1 ); - cvZero( x->buf[i] ); - } - cvReleaseImage( &x->mhi ); - cvReleaseImage( &x->orient ); - cvReleaseImage( &x->segmask ); - cvReleaseImage( &x->mask ); - - x->mhi = cvCreateImage( size, IPL_DEPTH_32F, 1 ); - cvZero( x->mhi ); // clear MHI at the beginning - x->orient = cvCreateImage( size, IPL_DEPTH_32F, 1 ); - x->segmask = cvCreateImage( size, IPL_DEPTH_32F, 1 ); - x->mask = cvCreateImage( size, IPL_DEPTH_8U, 1 ); - } - - cvCvtColor( img, x->buf[x->last], CV_BGR2GRAY ); // convert frame to grayscale - - idx2 = (x->last + 1) % x->frame_buffer_num; // index of (last - (N-1))th frame - x->last = idx2; - - silh = x->buf[idx2]; - cvAbsDiff( x->buf[idx1], x->buf[idx2], silh ); // get difference between frames - - cvThreshold( silh, silh, diff_threshold, 1, CV_THRESH_BINARY ); // and threshold it - cvUpdateMotionHistory( silh, x->mhi, timestamp, x->x_mhi_duration ); // update MHI - - // convert MHI to red 8u image - cvCvtScale( x->mhi, x->mask, 255./x->x_mhi_duration, - (x->x_mhi_duration - timestamp)*255./x->x_mhi_duration ); - cvZero( dst ); - cvCvtPlaneToPix( x->mask, 0, 0, 0, dst ); - - // calculate motion gradient orientation and valid orientation mask - cvCalcMotionGradient( x->mhi, x->mask, x->orient, x->max_time_delta, x->min_time_delta, x->x_aperture ); - - if( !x->storage ) - x->storage = cvCreateMemStorage(0); - else - cvClearMemStorage(x->storage); - - // segment motion: get sequence of motion components - // segmask is marked motion components map. It is not used further - seq = cvSegmentMotion( x->mhi, x->segmask, x->storage, timestamp, x->max_time_delta ); - - // iterate through the motion components, - // One more iteration (i == -1) corresponds to the whole image (global motion) - j=0; - for( i = -1; i < seq->total; i++ ) { - - if( i < 0 ) { // case of the whole image - comp_rect = cvRect( 0, 0, size.width, size.height ); - color = CV_RGB(255,255,255); - magnitude = 100; - } - else { // i-th motion component - comp_rect = ((CvConnectedComp*)cvGetSeqElem( seq, i ))->rect; - if(( comp_rect.width + comp_rect.height < x->min_size )||( comp_rect.width + comp_rect.height > x->max_size )) // reject very small/big components - continue; - color = CV_RGB(255,0,0); - magnitude = (comp_rect.width + comp_rect.height) / 4; - } - - // select component ROI - cvSetImageROI( silh, comp_rect ); - cvSetImageROI( x->mhi, comp_rect ); - cvSetImageROI( x->orient, comp_rect ); - cvSetImageROI( x->mask, comp_rect ); - - // calculate orientation - angle = cvCalcGlobalOrientation( x->orient, x->mask, x->mhi, timestamp, x->x_mhi_duration); - angle = 360.0 - angle; // adjust for images with top-left origin - - count = cvNorm( silh, 0, CV_L1, 0 ); // calculate number of points within silhouette ROI - - cvResetImageROI( x->mhi ); - cvResetImageROI( x->orient ); - cvResetImageROI( x->mask ); - cvResetImageROI( silh ); - - // check for the case of little motion - if( count < comp_rect.width*comp_rect.height * 0.05 ) - continue; - - // draw a clock with arrow indicating the direction - center = cvPoint( (comp_rect.x + comp_rect.width/2), - (comp_rect.y + comp_rect.height/2) ); - - cvCircle( dst, center, cvRound(magnitude*1.2), color, 3, CV_AA, 0 ); - cvLine( dst, center, cvPoint( cvRound( center.x + magnitude*cos(angle*CV_PI/180)), - cvRound( center.y - magnitude*sin(angle*CV_PI/180))), color, 3, CV_AA, 0 ); - - if ( i<0 ) - { - sprintf( tindex, "%d", i ); - cvPutText( dst, tindex, center, &x->font, CV_RGB(255,255,255)); - SETFLOAT(&x->rlist[0], i); - SETFLOAT(&x->rlist[1], center.x); - SETFLOAT(&x->rlist[2], center.y); - SETFLOAT(&x->rlist[3], comp_rect.width); - SETFLOAT(&x->rlist[4], comp_rect.height); - SETFLOAT(&x->rlist[5], angle); - outlet_list( x->x_dataout, 0, 6, x->rlist ); - } - else - { - sprintf( tindex, "%d", ++j ); - cvPutText( dst, tindex, center, &x->font, CV_RGB(255,255,255)); - SETFLOAT(&x->rlist[0], j); - SETFLOAT(&x->rlist[1], center.x); - SETFLOAT(&x->rlist[2], center.y); - SETFLOAT(&x->rlist[3], comp_rect.width); - SETFLOAT(&x->rlist[4], comp_rect.height); - SETFLOAT(&x->rlist[5], angle); - outlet_list( x->x_dataout, 0, 6, x->rlist ); - } - } -} - -static void pdp_opencv_motempl_process_rgb(t_pdp_opencv_motempl *x) -{ - t_pdp *header = pdp_packet_header(x->x_packet0); - short int *data = (short int *)pdp_packet_data(x->x_packet0); - t_pdp *newheader = pdp_packet_header(x->x_packet1); - short int *newdata = (short int *)pdp_packet_data(x->x_packet1); - int i; - - - if ((x->x_width != (t_int)header->info.image.width) || - (x->x_height != (t_int)header->info.image.height)) - { - - post("pdp_opencv_motempl :: resizing plugins"); - - //cv_freeplugins(x); - - x->x_width = header->info.image.width; - x->x_height = header->info.image.height; - x->x_size = x->x_width*x->x_height; - - //Destroy cv_images - cvReleaseImage( &x->image ); - cvReleaseImage( &x->motion ); - - //create cv_images - x->image = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 3); - x->motion = cvCreateImage( cvSize(x->image->width,x->image->height), 8, 3 ); - cvZero( x->motion ); - x->motion->origin = x->image->origin; - } - - newheader->info.image.encoding = header->info.image.encoding; - newheader->info.image.width = x->x_width; - newheader->info.image.height = x->x_height; - - memcpy( newdata, data, x->x_size*3 ); - - memcpy( x->image->imageData, data, x->x_size*3 ); - - pdp_opencv_motempl_update_mhi( x, x->image, x->motion, x->x_thresh ); - - memcpy( newdata, x->motion->imageData, x->x_size*3 ); - - return; -} - -static void pdp_opencv_motempl_thresh(t_pdp_opencv_motempl *x, t_floatarg f) -{ - x->x_thresh = (int)f; -} - -static void pdp_opencv_motempl_min_size(t_pdp_opencv_motempl *x, t_floatarg f) -{ - if (f>=0) x->min_size = (int)f; -} - -static void pdp_opencv_motempl_max_size(t_pdp_opencv_motempl *x, t_floatarg f) -{ - if (f>=0) x->max_size = (int)f; -} - -static void pdp_opencv_motempl_mhi_duration(t_pdp_opencv_motempl *x, t_floatarg f) -{ - if (f>0) x->x_mhi_duration = f; -} - -static void pdp_opencv_motempl_aperture(t_pdp_opencv_motempl *x, t_floatarg f) -{ - if ( ( (int)f == 1.0 ) || ( (int)f == 3.0 ) || ( (int)f == 5.0 ) || ( (int)f == 7.0 ) ) - { - x->x_aperture = (int)f; - } -} - -static void pdp_opencv_motempl_max_time_delta(t_pdp_opencv_motempl *x, t_floatarg f) -{ - if (f>0) x->max_time_delta = f; -} - -static void pdp_opencv_motempl_min_time_delta(t_pdp_opencv_motempl *x, t_floatarg f) -{ - if (f>0) x->min_time_delta = f; -} - -static void pdp_opencv_motempl_frame_buffer_num(t_pdp_opencv_motempl *x, t_floatarg f) -{ - if (f>=3) - { - x->frame_buffer_num = (int)f; - x->buf = NULL; - } -} - -static void pdp_opencv_motempl_sendpacket(t_pdp_opencv_motempl *x) -{ - /* release the packet */ - pdp_packet_mark_unused(x->x_packet0); - x->x_packet0 = -1; - - /* unregister and propagate if valid dest packet */ - pdp_packet_pass_if_valid(x->x_outlet0, &x->x_packet1); -} - -static void pdp_opencv_motempl_process(t_pdp_opencv_motempl *x) -{ - int encoding; - t_pdp *header = 0; - - /* check if image data packets are compatible */ - if ( (header = pdp_packet_header(x->x_packet0)) - && (PDP_BITMAP == header->type)){ - - /* pdp_opencv_motempl_process inputs and write into active inlet */ - switch(pdp_packet_header(x->x_packet0)->info.image.encoding){ - - case PDP_BITMAP_RGB: - x->x_packet1 = pdp_packet_clone_rw(x->x_packet0); - pdp_queue_add(x, pdp_opencv_motempl_process_rgb, pdp_opencv_motempl_sendpacket, &x->x_queue_id); - break; - - default: - /* don't know the type, so dont pdp_opencv_motempl_process */ - break; - - } - } - -} - -static void pdp_opencv_motempl_input_0(t_pdp_opencv_motempl *x, t_symbol *s, t_floatarg f) -{ - /* if this is a register_ro message or register_rw message, register with packet factory */ - - if (s == gensym("register_rw")) - x->x_dropped = pdp_packet_convert_ro_or_drop(&x->x_packet0, (int)f, pdp_gensym("bitmap/rgb/*") ); - - if ((s == gensym("process")) && (-1 != x->x_packet0) && (!x->x_dropped)) - { - /* add the process method and callback to the process queue */ - pdp_opencv_motempl_process(x); - } -} - -static void pdp_opencv_motempl_free(t_pdp_opencv_motempl *x) -{ - int i; - - pdp_queue_finish(x->x_queue_id); - pdp_packet_mark_unused(x->x_packet0); - - //Destroy cv_images - cvReleaseImage( &x->image ); - cvReleaseImage( &x->motion ); -} - -t_class *pdp_opencv_motempl_class; - -void *pdp_opencv_motempl_new(t_floatarg f) -{ - int i; - - t_pdp_opencv_motempl *x = (t_pdp_opencv_motempl *)pd_new(pdp_opencv_motempl_class); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("threshold")); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("min_size")); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("max_size")); - - x->x_outlet0 = outlet_new(&x->x_obj, &s_anything); - x->x_dataout = outlet_new(&x->x_obj, &s_anything); - - x->x_packet0 = -1; - x->x_packet1 = -1; - x->x_queue_id = -1; - - x->x_width = 320; - x->x_height = 240; - x->x_size = x->x_width * x->x_height; - - x->x_infosok = 0; - - x->x_thresh = 30; - x->x_mhi_duration = 1; - x->x_aperture = 3; - - x->last = 0; - // various tracking parameters (in seconds) - x->max_time_delta = 0.5; - x->min_time_delta = 0.05; - // number of cyclic frame buffer used for motion detection - // (should, probably, depend on FPS) - x->frame_buffer_num = 4; - - x->min_size=50; - x->max_size=500; - - x->image = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 3); - x->motion = cvCreateImage( cvSize(x->image->width,x->image->height), 8, 3 ); - cvZero( x->motion ); - x->motion->origin = x->image->origin; - - x->storage = NULL; - - // initialize font - cvInitFont( &x->font, CV_FONT_HERSHEY_PLAIN, 1.0, 1.0, 0, 1, 8 ); - - return (void *)x; -} - - -#ifdef __cplusplus -extern "C" -{ -#endif - - -void pdp_opencv_motempl_setup(void) -{ - - post( " pdp_opencv_motempl"); - pdp_opencv_motempl_class = class_new(gensym("pdp_opencv_motempl"), (t_newmethod)pdp_opencv_motempl_new, - (t_method)pdp_opencv_motempl_free, sizeof(t_pdp_opencv_motempl), 0, A_DEFFLOAT, A_NULL); - - class_addmethod(pdp_opencv_motempl_class, (t_method)pdp_opencv_motempl_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL); - class_addmethod(pdp_opencv_motempl_class, (t_method)pdp_opencv_motempl_thresh, gensym("threshold"), A_FLOAT, A_NULL ); - class_addmethod(pdp_opencv_motempl_class, (t_method)pdp_opencv_motempl_mhi_duration, gensym("mhi_duration"), A_FLOAT, A_NULL ); - class_addmethod(pdp_opencv_motempl_class, (t_method)pdp_opencv_motempl_aperture, gensym("aperture"), A_FLOAT, A_NULL ); - class_addmethod(pdp_opencv_motempl_class, (t_method)pdp_opencv_motempl_max_time_delta, gensym("max_time_delta"), A_FLOAT, A_NULL ); - class_addmethod(pdp_opencv_motempl_class, (t_method)pdp_opencv_motempl_min_time_delta, gensym("min_time_delta"), A_FLOAT, A_NULL ); - class_addmethod(pdp_opencv_motempl_class, (t_method)pdp_opencv_motempl_frame_buffer_num, gensym("frame_buffer_num"), A_FLOAT, A_NULL ); - class_addmethod(pdp_opencv_motempl_class, (t_method)pdp_opencv_motempl_min_size, gensym("min_size"), A_FLOAT, A_NULL ); - class_addmethod(pdp_opencv_motempl_class, (t_method)pdp_opencv_motempl_max_size, gensym("max_size"), A_FLOAT, A_NULL ); - -} - -#ifdef __cplusplus -} -#endif diff --git a/pdp_opencv_motempl.cc b/pdp_opencv_motempl.cc new file mode 100755 index 0000000..5af970e --- /dev/null +++ b/pdp_opencv_motempl.cc @@ -0,0 +1,468 @@ +/* + * Pure Data Packet module. + * Copyright (c) by Tom Schouten + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include + +#include "pdp.h" + +#ifndef _EiC +#include "cv.h" +#include +#include +#include +#endif + +typedef struct pdp_opencv_motempl_struct +{ + t_object x_obj; + t_float x_f; + + t_outlet *x_outlet0; + t_outlet *x_dataout; + int x_packet0; + int x_packet1; + int x_dropped; + int x_queue_id; + + int x_width; + int x_height; + int x_size; + + int x_thresh; + double x_mhi_duration; + int x_aperture; + + int x_infosok; + + // ring image buffer + IplImage **buf; + int last; + + // temporary images + IplImage *mhi; // MHI + IplImage *orient; // orientation + IplImage *mask; // valid orientation mask + IplImage *segmask; // motion segmentation map + CvMemStorage* storage; // temporary storage + CvFont font; + + IplImage* image; + IplImage* motion; + + // various tracking parameters (in seconds) + double max_time_delta; + double min_time_delta; + + // number of cyclic frame buffer used for motion detection + // (should, probably, depend on FPS) + int frame_buffer_num; + + int max_size; + int min_size; + + t_atom rlist[6]; + +} t_pdp_opencv_motempl; + +void pdp_opencv_motempl_update_mhi( t_pdp_opencv_motempl *x, IplImage* img, IplImage* dst, int diff_threshold ) +{ + double timestamp = (double)clock()/CLOCKS_PER_SEC; // get current time in seconds + CvSize size = cvSize(img->width,img->height); // get current frame size + int i, j, idx1 = x->last, idx2; + IplImage* silh; + CvSeq* seq; + CvRect comp_rect; + double count; + double angle; + CvPoint center; + double magnitude; + CvScalar color; + char tindex[10]; + + // allocate images at the beginning or + // reallocate them if the frame size is changed + if( !x->mhi || x->mhi->width != size.width || x->mhi->height != size.height || !x->buf ) { + if( x->buf == 0 ) { + x->buf = (IplImage**)malloc(x->frame_buffer_num*sizeof(x->buf[0])); + memset( x->buf, 0, x->frame_buffer_num*sizeof(x->buf[0])); + } + + for( i = 0; i < x->frame_buffer_num; i++ ) { + cvReleaseImage( &x->buf[i] ); + x->buf[i] = cvCreateImage( size, IPL_DEPTH_8U, 1 ); + cvZero( x->buf[i] ); + } + cvReleaseImage( &x->mhi ); + cvReleaseImage( &x->orient ); + cvReleaseImage( &x->segmask ); + cvReleaseImage( &x->mask ); + + x->mhi = cvCreateImage( size, IPL_DEPTH_32F, 1 ); + cvZero( x->mhi ); // clear MHI at the beginning + x->orient = cvCreateImage( size, IPL_DEPTH_32F, 1 ); + x->segmask = cvCreateImage( size, IPL_DEPTH_32F, 1 ); + x->mask = cvCreateImage( size, IPL_DEPTH_8U, 1 ); + } + + cvCvtColor( img, x->buf[x->last], CV_BGR2GRAY ); // convert frame to grayscale + + idx2 = (x->last + 1) % x->frame_buffer_num; // index of (last - (N-1))th frame + x->last = idx2; + + silh = x->buf[idx2]; + cvAbsDiff( x->buf[idx1], x->buf[idx2], silh ); // get difference between frames + + cvThreshold( silh, silh, diff_threshold, 1, CV_THRESH_BINARY ); // and threshold it + cvUpdateMotionHistory( silh, x->mhi, timestamp, x->x_mhi_duration ); // update MHI + + // convert MHI to red 8u image + cvCvtScale( x->mhi, x->mask, 255./x->x_mhi_duration, + (x->x_mhi_duration - timestamp)*255./x->x_mhi_duration ); + cvZero( dst ); + cvCvtPlaneToPix( x->mask, 0, 0, 0, dst ); + + // calculate motion gradient orientation and valid orientation mask + cvCalcMotionGradient( x->mhi, x->mask, x->orient, x->max_time_delta, x->min_time_delta, x->x_aperture ); + + if( !x->storage ) + x->storage = cvCreateMemStorage(0); + else + cvClearMemStorage(x->storage); + + // segment motion: get sequence of motion components + // segmask is marked motion components map. It is not used further + seq = cvSegmentMotion( x->mhi, x->segmask, x->storage, timestamp, x->max_time_delta ); + + // iterate through the motion components, + // One more iteration (i == -1) corresponds to the whole image (global motion) + j=0; + for( i = -1; i < seq->total; i++ ) { + + if( i < 0 ) { // case of the whole image + comp_rect = cvRect( 0, 0, size.width, size.height ); + color = CV_RGB(255,255,255); + magnitude = 100; + } + else { // i-th motion component + comp_rect = ((CvConnectedComp*)cvGetSeqElem( seq, i ))->rect; + if(( comp_rect.width + comp_rect.height < x->min_size )||( comp_rect.width + comp_rect.height > x->max_size )) // reject very small/big components + continue; + color = CV_RGB(255,0,0); + magnitude = (comp_rect.width + comp_rect.height) / 4; + } + + // select component ROI + cvSetImageROI( silh, comp_rect ); + cvSetImageROI( x->mhi, comp_rect ); + cvSetImageROI( x->orient, comp_rect ); + cvSetImageROI( x->mask, comp_rect ); + + // calculate orientation + angle = cvCalcGlobalOrientation( x->orient, x->mask, x->mhi, timestamp, x->x_mhi_duration); + angle = 360.0 - angle; // adjust for images with top-left origin + + count = cvNorm( silh, 0, CV_L1, 0 ); // calculate number of points within silhouette ROI + + cvResetImageROI( x->mhi ); + cvResetImageROI( x->orient ); + cvResetImageROI( x->mask ); + cvResetImageROI( silh ); + + // check for the case of little motion + if( count < comp_rect.width*comp_rect.height * 0.05 ) + continue; + + // draw a clock with arrow indicating the direction + center = cvPoint( (comp_rect.x + comp_rect.width/2), + (comp_rect.y + comp_rect.height/2) ); + + cvCircle( dst, center, cvRound(magnitude*1.2), color, 3, CV_AA, 0 ); + cvLine( dst, center, cvPoint( cvRound( center.x + magnitude*cos(angle*CV_PI/180)), + cvRound( center.y - magnitude*sin(angle*CV_PI/180))), color, 3, CV_AA, 0 ); + + if ( i<0 ) + { + sprintf( tindex, "%d", i ); + cvPutText( dst, tindex, center, &x->font, CV_RGB(255,255,255)); + SETFLOAT(&x->rlist[0], i); + SETFLOAT(&x->rlist[1], center.x); + SETFLOAT(&x->rlist[2], center.y); + SETFLOAT(&x->rlist[3], comp_rect.width); + SETFLOAT(&x->rlist[4], comp_rect.height); + SETFLOAT(&x->rlist[5], angle); + outlet_list( x->x_dataout, 0, 6, x->rlist ); + } + else + { + sprintf( tindex, "%d", ++j ); + cvPutText( dst, tindex, center, &x->font, CV_RGB(255,255,255)); + SETFLOAT(&x->rlist[0], j); + SETFLOAT(&x->rlist[1], center.x); + SETFLOAT(&x->rlist[2], center.y); + SETFLOAT(&x->rlist[3], comp_rect.width); + SETFLOAT(&x->rlist[4], comp_rect.height); + SETFLOAT(&x->rlist[5], angle); + outlet_list( x->x_dataout, 0, 6, x->rlist ); + } + } +} + +static void pdp_opencv_motempl_process_rgb(t_pdp_opencv_motempl *x) +{ + t_pdp *header = pdp_packet_header(x->x_packet0); + short int *data = (short int *)pdp_packet_data(x->x_packet0); + t_pdp *newheader = pdp_packet_header(x->x_packet1); + short int *newdata = (short int *)pdp_packet_data(x->x_packet1); + int i; + + + if ((x->x_width != (t_int)header->info.image.width) || + (x->x_height != (t_int)header->info.image.height)) + { + + post("pdp_opencv_motempl :: resizing plugins"); + + //cv_freeplugins(x); + + x->x_width = header->info.image.width; + x->x_height = header->info.image.height; + x->x_size = x->x_width*x->x_height; + + //Destroy cv_images + cvReleaseImage( &x->image ); + cvReleaseImage( &x->motion ); + + //create cv_images + x->image = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 3); + x->motion = cvCreateImage( cvSize(x->image->width,x->image->height), 8, 3 ); + cvZero( x->motion ); + x->motion->origin = x->image->origin; + } + + newheader->info.image.encoding = header->info.image.encoding; + newheader->info.image.width = x->x_width; + newheader->info.image.height = x->x_height; + + memcpy( newdata, data, x->x_size*3 ); + + memcpy( x->image->imageData, data, x->x_size*3 ); + + pdp_opencv_motempl_update_mhi( x, x->image, x->motion, x->x_thresh ); + + memcpy( newdata, x->motion->imageData, x->x_size*3 ); + + return; +} + +static void pdp_opencv_motempl_thresh(t_pdp_opencv_motempl *x, t_floatarg f) +{ + x->x_thresh = (int)f; +} + +static void pdp_opencv_motempl_min_size(t_pdp_opencv_motempl *x, t_floatarg f) +{ + if (f>=0) x->min_size = (int)f; +} + +static void pdp_opencv_motempl_max_size(t_pdp_opencv_motempl *x, t_floatarg f) +{ + if (f>=0) x->max_size = (int)f; +} + +static void pdp_opencv_motempl_mhi_duration(t_pdp_opencv_motempl *x, t_floatarg f) +{ + if (f>0) x->x_mhi_duration = f; +} + +static void pdp_opencv_motempl_aperture(t_pdp_opencv_motempl *x, t_floatarg f) +{ + if ( ( (int)f == 1.0 ) || ( (int)f == 3.0 ) || ( (int)f == 5.0 ) || ( (int)f == 7.0 ) ) + { + x->x_aperture = (int)f; + } +} + +static void pdp_opencv_motempl_max_time_delta(t_pdp_opencv_motempl *x, t_floatarg f) +{ + if (f>0) x->max_time_delta = f; +} + +static void pdp_opencv_motempl_min_time_delta(t_pdp_opencv_motempl *x, t_floatarg f) +{ + if (f>0) x->min_time_delta = f; +} + +static void pdp_opencv_motempl_frame_buffer_num(t_pdp_opencv_motempl *x, t_floatarg f) +{ + if (f>=3) + { + x->frame_buffer_num = (int)f; + x->buf = NULL; + } +} + +static void pdp_opencv_motempl_sendpacket(t_pdp_opencv_motempl *x) +{ + /* release the packet */ + pdp_packet_mark_unused(x->x_packet0); + x->x_packet0 = -1; + + /* unregister and propagate if valid dest packet */ + pdp_packet_pass_if_valid(x->x_outlet0, &x->x_packet1); +} + +static void pdp_opencv_motempl_process(t_pdp_opencv_motempl *x) +{ + int encoding; + t_pdp *header = 0; + + /* check if image data packets are compatible */ + if ( (header = pdp_packet_header(x->x_packet0)) + && (PDP_BITMAP == header->type)){ + + /* pdp_opencv_motempl_process inputs and write into active inlet */ + switch(pdp_packet_header(x->x_packet0)->info.image.encoding){ + + case PDP_BITMAP_RGB: + x->x_packet1 = pdp_packet_clone_rw(x->x_packet0); + pdp_queue_add(x, (void*)pdp_opencv_motempl_process_rgb, (void*)pdp_opencv_motempl_sendpacket, &x->x_queue_id); + break; + + default: + /* don't know the type, so dont pdp_opencv_motempl_process */ + break; + + } + } + +} + +static void pdp_opencv_motempl_input_0(t_pdp_opencv_motempl *x, t_symbol *s, t_floatarg f) +{ + /* if this is a register_ro message or register_rw message, register with packet factory */ + + if (s == gensym("register_rw")) + x->x_dropped = pdp_packet_convert_ro_or_drop(&x->x_packet0, (int)f, pdp_gensym((char*)"bitmap/rgb/*") ); + + if ((s == gensym("process")) && (-1 != x->x_packet0) && (!x->x_dropped)) + { + /* add the process method and callback to the process queue */ + pdp_opencv_motempl_process(x); + } +} + +static void pdp_opencv_motempl_free(t_pdp_opencv_motempl *x) +{ + int i; + + pdp_queue_finish(x->x_queue_id); + pdp_packet_mark_unused(x->x_packet0); + + //Destroy cv_images + cvReleaseImage( &x->image ); + cvReleaseImage( &x->motion ); +} + +t_class *pdp_opencv_motempl_class; + +void *pdp_opencv_motempl_new(t_floatarg f) +{ + int i; + + t_pdp_opencv_motempl *x = (t_pdp_opencv_motempl *)pd_new(pdp_opencv_motempl_class); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("threshold")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("min_size")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("max_size")); + + x->x_outlet0 = outlet_new(&x->x_obj, &s_anything); + x->x_dataout = outlet_new(&x->x_obj, &s_anything); + + x->x_packet0 = -1; + x->x_packet1 = -1; + x->x_queue_id = -1; + + x->x_width = 320; + x->x_height = 240; + x->x_size = x->x_width * x->x_height; + + x->x_infosok = 0; + + x->x_thresh = 30; + x->x_mhi_duration = 1; + x->x_aperture = 3; + + x->last = 0; + // various tracking parameters (in seconds) + x->max_time_delta = 0.5; + x->min_time_delta = 0.05; + // number of cyclic frame buffer used for motion detection + // (should, probably, depend on FPS) + x->frame_buffer_num = 4; + + x->min_size=50; + x->max_size=500; + + x->image = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 3); + x->motion = cvCreateImage( cvSize(x->image->width,x->image->height), 8, 3 ); + cvZero( x->motion ); + x->motion->origin = x->image->origin; + + x->storage = NULL; + + // initialize font + cvInitFont( &x->font, CV_FONT_HERSHEY_PLAIN, 1.0, 1.0, 0, 1, 8 ); + + return (void *)x; +} + + +#ifdef __cplusplus +extern "C" +{ +#endif + + +void pdp_opencv_motempl_setup(void) +{ + + post( " pdp_opencv_motempl"); + pdp_opencv_motempl_class = class_new(gensym("pdp_opencv_motempl"), (t_newmethod)pdp_opencv_motempl_new, + (t_method)pdp_opencv_motempl_free, sizeof(t_pdp_opencv_motempl), 0, A_DEFFLOAT, A_NULL); + + class_addmethod(pdp_opencv_motempl_class, (t_method)pdp_opencv_motempl_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL); + class_addmethod(pdp_opencv_motempl_class, (t_method)pdp_opencv_motempl_thresh, gensym("threshold"), A_FLOAT, A_NULL ); + class_addmethod(pdp_opencv_motempl_class, (t_method)pdp_opencv_motempl_mhi_duration, gensym("mhi_duration"), A_FLOAT, A_NULL ); + class_addmethod(pdp_opencv_motempl_class, (t_method)pdp_opencv_motempl_aperture, gensym("aperture"), A_FLOAT, A_NULL ); + class_addmethod(pdp_opencv_motempl_class, (t_method)pdp_opencv_motempl_max_time_delta, gensym("max_time_delta"), A_FLOAT, A_NULL ); + class_addmethod(pdp_opencv_motempl_class, (t_method)pdp_opencv_motempl_min_time_delta, gensym("min_time_delta"), A_FLOAT, A_NULL ); + class_addmethod(pdp_opencv_motempl_class, (t_method)pdp_opencv_motempl_frame_buffer_num, gensym("frame_buffer_num"), A_FLOAT, A_NULL ); + class_addmethod(pdp_opencv_motempl_class, (t_method)pdp_opencv_motempl_min_size, gensym("min_size"), A_FLOAT, A_NULL ); + class_addmethod(pdp_opencv_motempl_class, (t_method)pdp_opencv_motempl_max_size, gensym("max_size"), A_FLOAT, A_NULL ); + +} + +#ifdef __cplusplus +} +#endif diff --git a/pdp_opencv_threshold.c b/pdp_opencv_threshold.c deleted file mode 100644 index 7773a4a..0000000 --- a/pdp_opencv_threshold.c +++ /dev/null @@ -1,267 +0,0 @@ -/* - * Pure Data Packet module. - * Copyright (c) by Tom Schouten - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include -#include -#include -#include -#include -#include - -#include "pdp.h" - -#ifndef _EiC -#include "cv.h" -#endif - - - -typedef struct pdp_opencv_threshold_struct -{ - t_object x_obj; - t_float x_f; - - t_outlet *x_outlet0; - int x_packet0; - int x_packet1; - int x_dropped; - int x_queue_id; - - int x_width; - int x_height; - int x_size; - - int x_infosok; - - int threshold_value; - int max_value; - int threshold_mode; - IplImage *image, *gray; - - -} t_pdp_opencv_threshold; - -static void pdp_opencv_threshold_process_rgb(t_pdp_opencv_threshold *x) -{ - t_pdp *header = pdp_packet_header(x->x_packet0); - short int *data = (short int *)pdp_packet_data(x->x_packet0); - t_pdp *newheader = pdp_packet_header(x->x_packet1); - short int *newdata = (short int *)pdp_packet_data(x->x_packet1); - - if ((x->x_width != (t_int)header->info.image.width) || - (x->x_height != (t_int)header->info.image.height)) - { - - post("pdp_opencv_threshold :: resizing plugins"); - - x->x_width = header->info.image.width; - x->x_height = header->info.image.height; - x->x_size = x->x_width*x->x_height; - - //Destroy cv_images - cvReleaseImage(&x->image); - cvReleaseImage(&x->gray); - - //create the orig image with new size - x->image = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 3); - - // Create the output images with new sizes - x->gray = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 1); - - } - - newheader->info.image.encoding = header->info.image.encoding; - newheader->info.image.width = x->x_width; - newheader->info.image.height = x->x_height; - - memcpy( newdata, data, x->x_size*3 ); - - memcpy( x->image->imageData, data, x->x_size*3 ); - - // Convert to grayscale - cvCvtColor(x->image, x->gray, CV_BGR2GRAY); - - // Applies fixed-level thresholding to single-channel array. - switch(x->threshold_mode) { - case 0: - cvThreshold(x->gray, x->gray, (float)x->threshold_value, (float)x->max_value, CV_THRESH_BINARY); - break; - case 1: - cvThreshold(x->gray, x->gray, (float)x->threshold_value, (float)x->max_value, CV_THRESH_BINARY_INV); - break; - case 2: - cvThreshold(x->gray, x->gray, (float)x->threshold_value, (float)x->max_value, CV_THRESH_TRUNC); - break; - case 3: - cvThreshold(x->gray, x->gray, (float)x->threshold_value, (float)x->max_value, CV_THRESH_TOZERO); - break; - case 4: - cvThreshold(x->gray, x->gray, (float)x->threshold_value, (float)x->max_value, CV_THRESH_TOZERO_INV); - break; - } - - cvCvtColor(x->gray, x->image, CV_GRAY2BGR); - memcpy( newdata, x->image->imageData, x->x_size*3 ); - - return; -} - -static void pdp_opencv_threshold_thresh(t_pdp_opencv_threshold *x, t_floatarg f) -{ - x->threshold_value = (int)f; -} - -static void pdp_opencv_threshold_max(t_pdp_opencv_threshold *x, t_floatarg f) -{ - x->max_value = (int)f; -} - -static void pdp_opencv_threshold_mode(t_pdp_opencv_threshold *x, t_floatarg f) -{ - x->threshold_mode = (int)f; -} - -static void pdp_opencv_threshold_sendpacket(t_pdp_opencv_threshold *x) -{ - /* release the packet */ - pdp_packet_mark_unused(x->x_packet0); - x->x_packet0 = -1; - - /* unregister and propagate if valid dest packet */ - pdp_packet_pass_if_valid(x->x_outlet0, &x->x_packet1); -} - -static void pdp_opencv_threshold_process(t_pdp_opencv_threshold *x) -{ - int encoding; - t_pdp *header = 0; - char *parname; - unsigned pi; - int partype; - float pardefault; - t_atom plist[2]; - t_atom tlist[2]; - t_atom vlist[2]; - - /* check if image data packets are compatible */ - if ( (header = pdp_packet_header(x->x_packet0)) - && (PDP_BITMAP == header->type)){ - - /* pdp_opencv_threshold_process inputs and write into active inlet */ - switch(pdp_packet_header(x->x_packet0)->info.image.encoding){ - - case PDP_BITMAP_RGB: - x->x_packet1 = pdp_packet_clone_rw(x->x_packet0); - pdp_queue_add(x, pdp_opencv_threshold_process_rgb, pdp_opencv_threshold_sendpacket, &x->x_queue_id); - break; - - default: - /* don't know the type, so dont pdp_opencv_threshold_process */ - break; - - } - } - -} - -static void pdp_opencv_threshold_input_0(t_pdp_opencv_threshold *x, t_symbol *s, t_floatarg f) -{ - /* if this is a register_ro message or register_rw message, register with packet factory */ - - if (s == gensym("register_rw")) - x->x_dropped = pdp_packet_convert_ro_or_drop(&x->x_packet0, (int)f, pdp_gensym("bitmap/rgb/*") ); - - if ((s == gensym("process")) && (-1 != x->x_packet0) && (!x->x_dropped)) - { - /* add the process method and callback to the process queue */ - pdp_opencv_threshold_process(x); - } -} - -static void pdp_opencv_threshold_free(t_pdp_opencv_threshold *x) -{ - int i; - - pdp_queue_finish(x->x_queue_id); - pdp_packet_mark_unused(x->x_packet0); - //cv_freeplugins(x); - - //Destroy cv_images - cvReleaseImage(&x->image); - cvReleaseImage(&x->gray); -} - -t_class *pdp_opencv_threshold_class; - -void *pdp_opencv_threshold_new(t_floatarg f) -{ - int i; - - t_pdp_opencv_threshold *x = (t_pdp_opencv_threshold *)pd_new(pdp_opencv_threshold_class); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("max_value")); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("threshold_value")); - - x->x_outlet0 = outlet_new(&x->x_obj, &s_anything); - - x->x_packet0 = -1; - x->x_packet1 = -1; - x->x_queue_id = -1; - - x->x_width = 320; - x->x_height = 240; - x->x_size = x->x_width * x->x_height; - - x->x_infosok = 0; - - x->threshold_value = 50; - x->max_value = 255; - x->threshold_mode = 0; - - x->image = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 3); - x->gray = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 1); - - return (void *)x; -} - - -#ifdef __cplusplus -extern "C" -{ -#endif - - -void pdp_opencv_threshold_setup(void) -{ - - post( " pdp_opencv_threshold"); - pdp_opencv_threshold_class = class_new(gensym("pdp_opencv_threshold"), (t_newmethod)pdp_opencv_threshold_new, - (t_method)pdp_opencv_threshold_free, sizeof(t_pdp_opencv_threshold), 0, A_DEFFLOAT, A_NULL); - - class_addmethod(pdp_opencv_threshold_class, (t_method)pdp_opencv_threshold_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL); - class_addmethod(pdp_opencv_threshold_class, (t_method)pdp_opencv_threshold_max, gensym("max_value"), A_FLOAT, A_NULL ); - class_addmethod(pdp_opencv_threshold_class, (t_method)pdp_opencv_threshold_thresh, gensym("threshold_value"), A_FLOAT, A_NULL ); - class_addmethod(pdp_opencv_threshold_class, (t_method)pdp_opencv_threshold_mode, gensym("mode"), A_FLOAT, A_NULL ); - - -} - -#ifdef __cplusplus -} -#endif diff --git a/pdp_opencv_threshold.cc b/pdp_opencv_threshold.cc new file mode 100755 index 0000000..80d418f --- /dev/null +++ b/pdp_opencv_threshold.cc @@ -0,0 +1,267 @@ +/* + * Pure Data Packet module. + * Copyright (c) by Tom Schouten + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include + +#include "pdp.h" + +#ifndef _EiC +#include "cv.h" +#endif + + + +typedef struct pdp_opencv_threshold_struct +{ + t_object x_obj; + t_float x_f; + + t_outlet *x_outlet0; + int x_packet0; + int x_packet1; + int x_dropped; + int x_queue_id; + + int x_width; + int x_height; + int x_size; + + int x_infosok; + + int threshold_value; + int max_value; + int threshold_mode; + IplImage *image, *gray; + + +} t_pdp_opencv_threshold; + +static void pdp_opencv_threshold_process_rgb(t_pdp_opencv_threshold *x) +{ + t_pdp *header = pdp_packet_header(x->x_packet0); + short int *data = (short int *)pdp_packet_data(x->x_packet0); + t_pdp *newheader = pdp_packet_header(x->x_packet1); + short int *newdata = (short int *)pdp_packet_data(x->x_packet1); + + if ((x->x_width != (t_int)header->info.image.width) || + (x->x_height != (t_int)header->info.image.height)) + { + + post("pdp_opencv_threshold :: resizing plugins"); + + x->x_width = header->info.image.width; + x->x_height = header->info.image.height; + x->x_size = x->x_width*x->x_height; + + //Destroy cv_images + cvReleaseImage(&x->image); + cvReleaseImage(&x->gray); + + //create the orig image with new size + x->image = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 3); + + // Create the output images with new sizes + x->gray = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 1); + + } + + newheader->info.image.encoding = header->info.image.encoding; + newheader->info.image.width = x->x_width; + newheader->info.image.height = x->x_height; + + memcpy( newdata, data, x->x_size*3 ); + + memcpy( x->image->imageData, data, x->x_size*3 ); + + // Convert to grayscale + cvCvtColor(x->image, x->gray, CV_BGR2GRAY); + + // Applies fixed-level thresholding to single-channel array. + switch(x->threshold_mode) { + case 0: + cvThreshold(x->gray, x->gray, (float)x->threshold_value, (float)x->max_value, CV_THRESH_BINARY); + break; + case 1: + cvThreshold(x->gray, x->gray, (float)x->threshold_value, (float)x->max_value, CV_THRESH_BINARY_INV); + break; + case 2: + cvThreshold(x->gray, x->gray, (float)x->threshold_value, (float)x->max_value, CV_THRESH_TRUNC); + break; + case 3: + cvThreshold(x->gray, x->gray, (float)x->threshold_value, (float)x->max_value, CV_THRESH_TOZERO); + break; + case 4: + cvThreshold(x->gray, x->gray, (float)x->threshold_value, (float)x->max_value, CV_THRESH_TOZERO_INV); + break; + } + + cvCvtColor(x->gray, x->image, CV_GRAY2BGR); + memcpy( newdata, x->image->imageData, x->x_size*3 ); + + return; +} + +static void pdp_opencv_threshold_thresh(t_pdp_opencv_threshold *x, t_floatarg f) +{ + x->threshold_value = (int)f; +} + +static void pdp_opencv_threshold_max(t_pdp_opencv_threshold *x, t_floatarg f) +{ + x->max_value = (int)f; +} + +static void pdp_opencv_threshold_mode(t_pdp_opencv_threshold *x, t_floatarg f) +{ + x->threshold_mode = (int)f; +} + +static void pdp_opencv_threshold_sendpacket(t_pdp_opencv_threshold *x) +{ + /* release the packet */ + pdp_packet_mark_unused(x->x_packet0); + x->x_packet0 = -1; + + /* unregister and propagate if valid dest packet */ + pdp_packet_pass_if_valid(x->x_outlet0, &x->x_packet1); +} + +static void pdp_opencv_threshold_process(t_pdp_opencv_threshold *x) +{ + int encoding; + t_pdp *header = 0; + char *parname; + unsigned pi; + int partype; + float pardefault; + t_atom plist[2]; + t_atom tlist[2]; + t_atom vlist[2]; + + /* check if image data packets are compatible */ + if ( (header = pdp_packet_header(x->x_packet0)) + && (PDP_BITMAP == header->type)){ + + /* pdp_opencv_threshold_process inputs and write into active inlet */ + switch(pdp_packet_header(x->x_packet0)->info.image.encoding){ + + case PDP_BITMAP_RGB: + x->x_packet1 = pdp_packet_clone_rw(x->x_packet0); + pdp_queue_add(x, (void*)pdp_opencv_threshold_process_rgb, (void*)pdp_opencv_threshold_sendpacket, &x->x_queue_id); + break; + + default: + /* don't know the type, so dont pdp_opencv_threshold_process */ + break; + + } + } + +} + +static void pdp_opencv_threshold_input_0(t_pdp_opencv_threshold *x, t_symbol *s, t_floatarg f) +{ + /* if this is a register_ro message or register_rw message, register with packet factory */ + + if (s == gensym("register_rw")) + x->x_dropped = pdp_packet_convert_ro_or_drop(&x->x_packet0, (int)f, pdp_gensym((char*)"bitmap/rgb/*") ); + + if ((s == gensym("process")) && (-1 != x->x_packet0) && (!x->x_dropped)) + { + /* add the process method and callback to the process queue */ + pdp_opencv_threshold_process(x); + } +} + +static void pdp_opencv_threshold_free(t_pdp_opencv_threshold *x) +{ + int i; + + pdp_queue_finish(x->x_queue_id); + pdp_packet_mark_unused(x->x_packet0); + //cv_freeplugins(x); + + //Destroy cv_images + cvReleaseImage(&x->image); + cvReleaseImage(&x->gray); +} + +t_class *pdp_opencv_threshold_class; + +void *pdp_opencv_threshold_new(t_floatarg f) +{ + int i; + + t_pdp_opencv_threshold *x = (t_pdp_opencv_threshold *)pd_new(pdp_opencv_threshold_class); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("max_value")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("threshold_value")); + + x->x_outlet0 = outlet_new(&x->x_obj, &s_anything); + + x->x_packet0 = -1; + x->x_packet1 = -1; + x->x_queue_id = -1; + + x->x_width = 320; + x->x_height = 240; + x->x_size = x->x_width * x->x_height; + + x->x_infosok = 0; + + x->threshold_value = 50; + x->max_value = 255; + x->threshold_mode = 0; + + x->image = cvCreateImage(cvSize(x->x_width,x->x_height), IPL_DEPTH_8U, 3); + x->gray = cvCreateImage(cvSize(x->image->width,x->image->height), IPL_DEPTH_8U, 1); + + return (void *)x; +} + + +#ifdef __cplusplus +extern "C" +{ +#endif + + +void pdp_opencv_threshold_setup(void) +{ + + post( " pdp_opencv_threshold"); + pdp_opencv_threshold_class = class_new(gensym("pdp_opencv_threshold"), (t_newmethod)pdp_opencv_threshold_new, + (t_method)pdp_opencv_threshold_free, sizeof(t_pdp_opencv_threshold), 0, A_DEFFLOAT, A_NULL); + + class_addmethod(pdp_opencv_threshold_class, (t_method)pdp_opencv_threshold_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL); + class_addmethod(pdp_opencv_threshold_class, (t_method)pdp_opencv_threshold_max, gensym("max_value"), A_FLOAT, A_NULL ); + class_addmethod(pdp_opencv_threshold_class, (t_method)pdp_opencv_threshold_thresh, gensym("threshold_value"), A_FLOAT, A_NULL ); + class_addmethod(pdp_opencv_threshold_class, (t_method)pdp_opencv_threshold_mode, gensym("mode"), A_FLOAT, A_NULL ); + + +} + +#ifdef __cplusplus +} +#endif -- cgit v1.2.1