From 841e92c1821ee54a92597ede38182565f24f2a87 Mon Sep 17 00:00:00 2001 From: Antoine Villeret Date: Sat, 22 Sep 2012 15:09:44 +0000 Subject: add a shape matcher for shape recognition svn path=/trunk/externals/pix_opencv/; revision=16266 --- pix_opencv_matchshape-help.pd | 103 ++++++++++++++++++++ pix_opencv_matchshape.cpp | 221 ++++++++++++++++++++++++++++++++++++++++++ pix_opencv_matchshape.h | 73 ++++++++++++++ 3 files changed, 397 insertions(+) create mode 100644 pix_opencv_matchshape-help.pd create mode 100644 pix_opencv_matchshape.cpp create mode 100644 pix_opencv_matchshape.h diff --git a/pix_opencv_matchshape-help.pd b/pix_opencv_matchshape-help.pd new file mode 100644 index 0000000..be53c23 --- /dev/null +++ b/pix_opencv_matchshape-help.pd @@ -0,0 +1,103 @@ +#N canvas 216 165 968 473 10; +#X obj 477 6 cnv 15 480 460 empty empty empty 20 12 0 14 -228992 -66577 +0; +#X obj 20 75 cnv 15 450 200 empty empty empty 20 12 0 14 -233017 -66577 +0; +#X obj 21 326 cnv 15 450 140 empty empty empty 20 12 0 14 -233017 -66577 +0; +#X text 22 331 Inlets:; +#X obj 21 286 cnv 15 450 30 empty empty empty 20 12 0 14 -195568 -66577 +0; +#X text 30 285 Arguments:; +#X text 22 400 Outlets:; +#X obj 491 41 cnv 15 460 310 empty empty empty 20 12 0 14 -24198 -66577 +0; +#X obj 501 326 pix_opencv_matchshape; +#X obj 501 14 gemhead; +#X obj 501 377 pix_texture; +#X obj 501 398 rectangle 4 3; +#X msg 570 103 contour 4 2 0 0 0 1 1 1 1 0; +#X msg 556 239 method \$1; +#X floatatom 556 217 5 0 0 0 - - -; +#X msg 580 153 template 4 2 0 0 0 1 1 1 1 0; +#X msg 590 173 template 4 2 2 0 4 1 1 1 1 0; +#X msg 560 83 contour 6 2 0 0 0 1 1 1 1 0 -0.5 -0.5; +#X floatatom 556 267 5 0 0 0 - - -; +#X msg 556 287 threshold \$1; +#X msg 550 64 contour 4 2 2 0 4 1 1 1 1 0; +#X obj 624 357 route match_vec template_vec; +#X obj 624 407 unpack; +#X text 631 390 found corresponding contour; +#X floatatom 624 435 5 0 0 0 - - -; +#X floatatom 659 435 5 0 0 0 - - -; +#X text 623 448 id; +#X text 659 448 absolute difference from template; +#X floatatom 706 378 5 0 0 0 - - -; +#X text 740 375 number of loaded contour; +#X text 593 213 method to compare shape (1 \, 2 or 3 \, please refer +to OpenCV doc for details); +#X text 37 193 This external uses cv::matchShapes function. Documentation +is here : http://docs.opencv.org/modules/imgproc/doc/structural_analysis_and_shape_descriptors.html?highlight=matchshapes#matchshapes +; +#X text 588 266 threshold behind wich a shape is recognized; +#X text 575 135 template message add a template to library; +#X text 549 46 contour message compare the contour to each loaded contour +; +#X text 37 103 [pix_opencv_matchshape] compares input images or input +contours to a library of images (or contours). It sends out the id +of the closest found behind a threshold.; +#X text 37 143 You can use pix_opencv_contour_convexhull2 to find all +contours in the image and send them to pix_opencv_matchshape to recognize +it.; +#X text 20 79 Description: compares shapes; +#X text 45 24 Synopsis: [pix_opencv_matchshape]; +#X text 67 40 Class: pix_opencv; +#X text 76 296 none; +#X text 40 353 Inlet 1: message: template ; +#X text 40 363 Inlet 1: message: contour ; +#X text 40 373 Inlet 1: message: method ; +#X text 40 383 Inlet 1: message: threshold ; +#X text 34 413 Outlet 1: input image; +#X text 40 343 Inlet 1: image; +#X obj 364 368 cnv 15 100 60 empty empty empty 20 12 0 14 -195568 -66577 +0; +#N canvas 0 0 450 300 gemwin 0; +#X obj 132 136 gemwin; +#X obj 67 89 outlet; +#X obj 67 10 inlet; +#X obj 67 41 route create; +#X msg 67 70 set destroy; +#X msg 142 68 set create; +#X msg 198 112 destroy; +#X msg 132 112 create \, 1; +#X connect 2 0 3 0; +#X connect 3 0 4 0; +#X connect 3 0 7 0; +#X connect 3 1 5 0; +#X connect 3 1 6 0; +#X connect 4 0 1 0; +#X connect 5 0 1 0; +#X connect 6 0 0 0; +#X connect 7 0 0 0; +#X restore 369 407 pd gemwin; +#X msg 369 388 create; +#X text 365 367 Create window:; +#X connect 8 0 10 0; +#X connect 8 1 21 0; +#X connect 9 0 8 0; +#X connect 10 0 11 0; +#X connect 12 0 8 0; +#X connect 13 0 8 0; +#X connect 14 0 13 0; +#X connect 15 0 8 0; +#X connect 16 0 8 0; +#X connect 17 0 8 0; +#X connect 18 0 19 0; +#X connect 19 0 8 0; +#X connect 20 0 8 0; +#X connect 21 0 22 0; +#X connect 21 1 28 0; +#X connect 22 0 24 0; +#X connect 22 1 25 0; +#X connect 48 0 49 0; +#X connect 49 0 48 0; diff --git a/pix_opencv_matchshape.cpp b/pix_opencv_matchshape.cpp new file mode 100644 index 0000000..75dc910 --- /dev/null +++ b/pix_opencv_matchshape.cpp @@ -0,0 +1,221 @@ +//////////////////////////////////////////////////////// +// +// GEM - Graphics Environment for Multimedia +// +// zmoelnig@iem.kug.ac.at +// +// Implementation file +// +// Copyright (c) 1997-2000 Mark Danks. +// Copyright (c) Günther Geiger. +// Copyright (c) 2001-2002 IOhannes m zmoelnig. forum::für::umläute. IEM +// Copyright (c) 2002 James Tittle & Chris Clepper +// For information on usage and redistribution, and for a DISCLAIMER OF ALL +// WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution. +// +///////////////////////////////////////////////////////// +// based on code written by Lluis Gomez i Bigorda ( lluisgomez _at_ hangar _dot_ org ) (pix_opencv) +// Template for pix_opencv class + +#include "pix_opencv_matchshape.h" +#include +#include + +using namespace std; + + +CPPEXTERN_NEW(pix_opencv_matchshape) + +///////////////////////////////////////////////////////// +// +// pix_opencv_matchshape +// +///////////////////////////////////////////////////////// +// Constructor +// +///////////////////////////////////////////////////////// +pix_opencv_matchshape :: pix_opencv_matchshape() : m_threshold(2), m_method(CV_CONTOURS_MATCH_I1) +{ + m_dataout = outlet_new(this->x_obj, 0); + m_template_vec_vec.clear(); + m_template_vec_mat.clear(); +} + +///////////////////////////////////////////////////////// +// Destructor +// +///////////////////////////////////////////////////////// +pix_opencv_matchshape :: ~pix_opencv_matchshape() +{ +} + +///////////////////////////////////////////////////////// +// processImage +// +///////////////////////////////////////////////////////// +void pix_opencv_matchshape :: processRGBAImage(imageStruct &image) +{ + error( "pix_opencv_matchshape : rgba format not supported" ); +} + +void pix_opencv_matchshape :: processRGBImage(imageStruct &image) { + error( "pix_opencv_matchshape : rgb format not supported"); +} + +void pix_opencv_matchshape :: processYUVImage(imageStruct &image) +{ + error( "pix_opencv_matchshape : yuv format not supported" ); +} + +void pix_opencv_matchshape :: processGrayImage(imageStruct &image) +{ + error( "pix_opencv_matchshape : gray format not supported" ); + error( "pix_opencv_matchshape only works on pd lists" ); + + // TODO add support to compare grayscale images +} + +///////////////////////////////////////////////////////// +// static member function +// +///////////////////////////////////////////////////////// +void pix_opencv_matchshape :: obj_setupCallback(t_class *classPtr) +{ + CPPEXTERN_MSG0(classPtr, "clear", clearMess); + CPPEXTERN_MSG(classPtr, "template", templateMess); + CPPEXTERN_MSG(classPtr, "contour", contourMess); + CPPEXTERN_MSG1(classPtr, "threshold", thresholdMess, float); + CPPEXTERN_MSG1(classPtr, "method", methodMess, int); +} + +void pix_opencv_matchshape :: clearMess(void) +{ + for ( vector >::iterator it=m_template_vec_vec.end(); it!=m_template_vec_vec.begin(); it--) + { + (*it).clear(); + } + m_template_vec_vec.clear(); + m_template_vec_mat.clear(); + + t_atom data; + SETFLOAT(&data, (float)m_template_vec_vec.size()); + outlet_anything(m_dataout, gensym("template_vec"), 1, &data); + + SETFLOAT(&data, (float)m_template_vec_mat.size()); + outlet_anything(m_dataout, gensym("template_mat"), 1, &data); +} + + +void pix_opencv_matchshape :: contourMess(t_symbol*s, int argc, t_atom*argv) +{ + if ( m_template_vec_vec.empty() ){ + error("no template to match, please load a template before matching"); + return; + } + + if ( (argc%2)!=0 ) { + error("template message argument should be multiple of 2"); + return; + } + + for (int i=0;i tmp_contour; + for (int i=2;i >::iterator it=m_template_vec_vec.begin(); it!=m_template_vec_vec.end(); ++it){ + comp = cv::matchShapes(tmp_contour, *it, m_method, 0.); + if ( comp < min ){ + min=comp; + id=i; + } + i++; + } + + if ( min < m_threshold ) + { + t_atom data[2]; + SETFLOAT(data,id); + SETFLOAT(data+1, min); + outlet_anything(m_dataout, gensym("match_vec"), 2, data); + } +} + +void pix_opencv_matchshape :: templateMess(t_symbol*s, int argc, t_atom*argv) +{ + if ( (argc%2)!=0 ) { + error("template message argument should be multiple of 2"); + return; + } + for (int i=0;i tmp_contour; + tmp_contour.clear(); + for (int i=2;i0.?arg:0.); + t_atom data; + SETFLOAT(&data, m_threshold); + outlet_anything(m_dataout, gensym("threshold"), 1, &data); +} + +void pix_opencv_matchshape :: methodMess(int arg) +{ + switch (arg) { + case 1: + m_method=CV_CONTOURS_MATCH_I1; + break; + case 2: + m_method=CV_CONTOURS_MATCH_I2; + break; + case 3: + m_method=CV_CONTOURS_MATCH_I3; + break; + default: + error("method should be 1, 2 or 3"); + m_method=CV_CONTOURS_MATCH_I1; + } + t_atom data; + switch (m_method) { + case CV_CONTOURS_MATCH_I1: + SETFLOAT(&data, 1); + break; + case CV_CONTOURS_MATCH_I2: + SETFLOAT(&data, 2); + break; + case CV_CONTOURS_MATCH_I3: + SETFLOAT(&data, 3); + break; + } + outlet_anything(m_dataout, gensym("method"), 1, &data); +} diff --git a/pix_opencv_matchshape.h b/pix_opencv_matchshape.h new file mode 100644 index 0000000..9fc971b --- /dev/null +++ b/pix_opencv_matchshape.h @@ -0,0 +1,73 @@ +/*----------------------------------------------------------------- +LOG + GEM - Graphics Environment for Multimedia + + Threshold filter + + Copyright (c) 1997-1999 Mark Danks. mark@danks.org + Copyright (c) Günther Geiger. geiger@epy.co.at + Copyright (c) 2001-2002 IOhannes m zmoelnig. forum::für::umläute. IEM. zmoelnig@iem.kug.ac.at + Copyright (c) 2002 James Tittle & Chris Clepper + For information on usage and redistribution, and for a DISCLAIMER OF ALL + WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution. + +-----------------------------------------------------------------*/ + +#ifndef INCLUDE_PIX_OPENCV_MATCHSHAPE_H_ +#define INCLUDE_PIX_OPENCV_MATCHSHAPE_H_ + +#ifndef _EiC +#include "cv.h" +#endif + +#include "Base/GemPixObj.h" + +/*----------------------------------------------------------------- +------------------------------------------------------------------- +CLASS + pix_opencv_matchshape + + square pattern detector + +KEYWORDS + pix + +DESCRIPTION + +-----------------------------------------------------------------*/ +class GEM_EXTERN pix_opencv_matchshape : public GemPixObj +{ + CPPEXTERN_HEADER(pix_opencv_matchshape, GemPixObj) + + public: + + // Constructor + pix_opencv_matchshape(); + + protected: + // process messages + void clearMess(void); + void templateMess(t_symbol*s, int argc, t_atom*argv); + void contourMess(t_symbol*s, int argc, t_atom*argv); + void thresholdMess(float arg); + void methodMess(int arg); + + // Destructor + virtual ~pix_opencv_matchshape(); + + // Do the processing + virtual void processRGBAImage(imageStruct &image); + virtual void processRGBImage(imageStruct &image); + virtual void processYUVImage(imageStruct &image); + virtual void processGrayImage(imageStruct &image); + + private: + + t_outlet *m_dataout; // info outlet + double m_threshold; + int m_method; + std::vector > m_template_vec_vec; + std::vector m_template_vec_mat; + +}; +#endif // for header file -- cgit v1.2.1