From 8ef221c853850bfa0ded97192a6894f8e4d942db Mon Sep 17 00:00:00 2001 From: Antoine Villeret Date: Tue, 15 Jan 2013 14:29:08 +0000 Subject: add writing to tables methods contours could be huge and may lead to stack overflow with the list iteratiion drawing function using tables and gemvertexbuffer also improve performances svn path=/trunk/externals/pix_opencv/; revision=16868 --- pix_opencv_contours.cc | 258 +++++++++++++++++++++++++++++++++++++------------ pix_opencv_contours.h | 6 +- 2 files changed, 202 insertions(+), 62 deletions(-) diff --git a/pix_opencv_contours.cc b/pix_opencv_contours.cc index d8f162d..85d6ea4 100644 --- a/pix_opencv_contours.cc +++ b/pix_opencv_contours.cc @@ -38,7 +38,11 @@ pix_opencv_contours :: pix_opencv_contours() : m_area_threshold(30), \ m_enable_contours(1), \ m_enable_hulls(1), \ m_enable_defects(1), \ - m_hierarchy_level(-1) + m_hierarchy_level(-1), \ + m_taboutput(0), \ + m_x_arrayname(NULL), \ + m_y_arrayname(NULL), \ + m_z_arrayname(NULL) { m_dataout_middle = outlet_new(this->x_obj, 0); m_dataout_right = outlet_new(this->x_obj, 0); @@ -85,7 +89,7 @@ void pix_opencv_contours :: processGrayImage(imageStruct &image) /*****************/ /* Find Contours */ /*****************/ - + std::vector > contours; std::vector hierarchy; @@ -145,75 +149,191 @@ void pix_opencv_contours :: processGrayImage(imageStruct &image) } if ( m_enable_contours ) - { - t_atom*info; - info = new t_atom[(int) m_contours.size()*20+2]; - // info : 20x(contour_nb) matrix - // info for each contour : area, rotrect corner (8 float), rotrect center, rotrect size, rotation angle, number of segments, length of contour, other are reserved for future use - int count(0); - SETFLOAT(info+1, 20.); - int info_offset(2); - - for( size_t i = 0 ; i < m_contours.size(); i++ ) - { - if (!m_contours[i].empty() && m_contours[i].size() > 2) { - SETFLOAT(info+info_offset, (float) cv::contourArea(m_contours[i])); - - cv::RotatedRect rot_rect = cv::minAreaRect(m_contours[i]); - cv::Point2f corners[4]; - rot_rect.points(corners); - double length = cv::arcLength(m_contours[i],true); - for (int j=0;j<4;j++) { - SETFLOAT(info+info_offset+j*2+1, corners[j].x/image.xsize); - SETFLOAT(info+info_offset+j*2+2, corners[j].y/image.ysize); - } + { + t_atom*info; + info = new t_atom[(int) m_contours.size()*20+2]; + // info : 20x(contour_nb) matrix + // info for each contour : area, rotrect corner (8 float), rotrect center, rotrect size, rotation angle, number of segments, length of contour, other are reserved for future use + int count(0); + SETFLOAT(info+1, 20.); + int info_offset(2); + + for( size_t i = 0 ; i < m_contours.size(); i++ ) + { + if (!m_contours[i].empty() && m_contours[i].size() > 2) { + SETFLOAT(info+info_offset, (float) cv::contourArea(m_contours[i])); + + cv::RotatedRect rot_rect = cv::minAreaRect(m_contours[i]); + cv::Point2f corners[4]; + rot_rect.points(corners); + double length = cv::arcLength(m_contours[i],true); + for (int j=0;j<4;j++) { + SETFLOAT(info+info_offset+j*2+1, corners[j].x/image.xsize); + SETFLOAT(info+info_offset+j*2+2, corners[j].y/image.ysize); + } - SETFLOAT(info+info_offset+9, rot_rect.center.x/image.xsize); - SETFLOAT(info+info_offset+10, rot_rect.center.y/image.ysize); - SETFLOAT(info+info_offset+11, rot_rect.size.width/image.xsize); - SETFLOAT(info+info_offset+12, rot_rect.size.height/image.xsize); - SETFLOAT(info+info_offset+13, rot_rect.angle); - SETFLOAT(info+info_offset+14, m_contours[i].size()); // number of points in segment - SETFLOAT(info+info_offset+15, (float) length); - SETFLOAT(info+info_offset+16, 0); - SETFLOAT(info+info_offset+17, 0); - SETFLOAT(info+info_offset+18, 0); - SETFLOAT(info+info_offset+19, 0); - - info_offset+=20; - count++; + SETFLOAT(info+info_offset+9, rot_rect.center.x/image.xsize); + SETFLOAT(info+info_offset+10, rot_rect.center.y/image.ysize); + SETFLOAT(info+info_offset+11, rot_rect.size.width/image.xsize); + SETFLOAT(info+info_offset+12, rot_rect.size.height/image.xsize); + SETFLOAT(info+info_offset+13, rot_rect.angle); + SETFLOAT(info+info_offset+14, m_contours[i].size()); // number of points in segment + SETFLOAT(info+info_offset+15, (float) length); + SETFLOAT(info+info_offset+16, 0); + SETFLOAT(info+info_offset+17, 0); + SETFLOAT(info+info_offset+18, 0); + SETFLOAT(info+info_offset+19, 0); + + info_offset+=20; + count++; + } } - } - SETFLOAT(info, (float) count); - if (count) outlet_anything(m_dataout_right, gensym("info"), count*20+2, info); - else outlet_float(m_dataout_right, 0); + + if ( !m_taboutput ){ + + SETFLOAT(info, (float) count); + if (count) outlet_anything(m_dataout_right, gensym("info"), count*20+2, info); + else outlet_float(m_dataout_right, 0); + + for( size_t i = 0 ; i < m_contours.size() ; i++ ) + { + if (!m_contours[i].empty() && m_contours[i].size() > 2) { + int size = 2+m_contours[i].size()*2; + t_atom*ap = new t_atom[size]; + SETFLOAT(ap, static_cast(m_contours[i].size())); + SETFLOAT(ap+1, 2.0); + + int offset(2); + + for ( size_t j = 0 ; j < m_contours[i].size() ; j++){ + cv::Point pt = m_contours[i][j]; + SETFLOAT(ap+offset,(float) pt.x/image.xsize); + SETFLOAT(ap+offset+1,(float) pt.y/image.ysize); + offset+=2; + } + outlet_anything(m_dataout_middle, gensym("contour"), size, ap); + if(ap)delete[]ap;ap=NULL; + + } + } + + + if (info) delete info; + info = NULL; + + } else { - for( size_t i = 0 ; i < m_contours.size() ; i++ ) - { - if (!m_contours[i].empty() && m_contours[i].size() > 2) { - int size = 2+m_contours[i].size()*2; - t_atom*ap = new t_atom[size]; - SETFLOAT(ap, static_cast(m_contours[i].size())); - SETFLOAT(ap+1, 2.0); + //~ put contours in 3 tables. + //~ contours are separated by a -1 value + + if ( m_x_arrayname == NULL || m_y_arrayname == NULL || m_z_arrayname == NULL){ + error("please settab before trying to write into..."); + return; + } + + int size(0), vecxsize(0), vecysize(0), veczsize(0); + t_garray *ax, *ay, *az; + t_word *vecx, *vecy, *vecz; + + //~ check if array exist + if (!(ax = (t_garray *)pd_findbyclass(m_x_arrayname, garray_class))){ + error("%s: no such array", m_x_arrayname->s_name); + return; + } + if (!(ay = (t_garray *)pd_findbyclass(m_y_arrayname, garray_class))){ + error("%s: no such array", m_y_arrayname->s_name); + return; + } + if (!(az = (t_garray *)pd_findbyclass(m_z_arrayname, garray_class))){ + error("%s: no such array", m_z_arrayname->s_name); + return; + } + + //~ check array and resize if needed + for( size_t i = 0 ; i < m_contours.size(); i++ ){ + size+=m_contours[i].size()+3; + } + + if (!garray_getfloatwords(ax, &vecxsize, &vecx)){ + error("%s: bad template for tabwrite", m_x_arrayname->s_name); + return; + } else if ( vecxsize != size ){ + garray_resize_long(ax,size); + if (!garray_getfloatwords(ax, &vecxsize, &vecx)){ + error("%s: can't resize correctly", m_x_arrayname->s_name); + return; + } + } + + if (!garray_getfloatwords(ay, &vecysize, &vecy)){ + error("%s: bad template for tabwrite", m_y_arrayname->s_name); + return; + } else if ( vecysize != size ){ + garray_resize_long(ay,size); + if (!garray_getfloatwords(ay, &vecysize, &vecy)){ + error("%s: can't resize correctly", m_y_arrayname->s_name); + return; + } + } + + if (!garray_getfloatwords(az, &veczsize, &vecz)){ + error("%s: bad template for tabwrite", m_z_arrayname->s_name); + return; + } else if ( veczsize != size ){ + garray_resize_long(az,size); + if (!garray_getfloatwords(az, &veczsize, &vecz)){ + error("%s: can't resize correctly", m_z_arrayname->s_name); + return; + } + } + + int n=0; + + for( size_t i = 0 ; i < m_contours.size(); i++ ) + { + if (n >= vecxsize || n>=vecysize || n>=veczsize) + { + error("array are not wide engouth"); + return; + } - int offset(2); + unsigned int j; + cv::Point pt; + pt = m_contours[i][0]; + //~ start with blank point + vecx[n].w_float = (float) pt.x/image.xsize; + vecy[n].w_float = (float) pt.y/image.ysize; + vecz[n].w_float = 0.; + n++; + + for ( j = 0 ; j < m_contours[i].size() ; j++) { - for ( size_t j = 0 ; j < m_contours[i].size() ; j++){ - cv::Point pt = m_contours[i][j]; - SETFLOAT(ap+offset,(float) pt.x/image.xsize); - SETFLOAT(ap+offset+1,(float) pt.y/image.ysize); - offset+=2; + pt = m_contours[i][j]; + + vecx[n].w_float = (float) pt.x/image.xsize; + vecy[n].w_float = (float) pt.y/image.ysize; + vecz[n].w_float = 1.; + n++; } - outlet_anything(m_dataout_middle, gensym("contour"), size, ap); - if(ap)delete[]ap;ap=NULL; - + // close contour + pt = m_contours[i][0]; + vecx[n].w_float = (float) pt.x/image.xsize; + vecy[n].w_float = (float) pt.y/image.ysize; + vecz[n].w_float = 1.; + n++; + // add a blank point to draw invisible segment + vecz[n++].w_float = 0.; + + } + //~ comment the redraw fnt if not needed + garray_redraw(ax); + garray_redraw(ay); + garray_redraw(az); } - - if (info) delete info; - info = NULL; } + //~ cv::drawContours(imgMat2, m_contours, -1, cv::Scalar(128,255,255), 3); /**********************/ @@ -329,6 +449,8 @@ void pix_opencv_contours :: obj_setupCallback(t_class *classPtr) CPPEXTERN_MSG1(classPtr, "convexhulls", convexhullsMess, double); CPPEXTERN_MSG1(classPtr, "convexitydefects", convexitydefectsMess, double); CPPEXTERN_MSG1(classPtr, "hierarchy_level", hierarchyMess, double); + CPPEXTERN_MSG1(classPtr, "taboutput", taboutputMess, float); + CPPEXTERN_MSG3(classPtr, "settab", tableMess, t_symbol*, t_symbol*, t_symbol*); } ///////////////////////////////////////////////////////// @@ -366,3 +488,17 @@ void pix_opencv_contours :: hierarchyMess(double arg) m_hierarchy_level = arg < -1 ? -1 : arg; m_mode = m_hierarchy_level == -1 ? CV_RETR_LIST : CV_RETR_TREE; } + +void pix_opencv_contours :: taboutputMess(float arg) +{ + m_taboutput = arg > 0; +} +void pix_opencv_contours :: tableMess(t_symbol*xarray, t_symbol*yarray, t_symbol*zarray) +{ + // check if arrays exist + m_x_arrayname = xarray; + m_y_arrayname = yarray; + m_z_arrayname = zarray; + + m_taboutput = 1; +} diff --git a/pix_opencv_contours.h b/pix_opencv_contours.h index fb1ebe1..b546aca 100644 --- a/pix_opencv_contours.h +++ b/pix_opencv_contours.h @@ -65,6 +65,8 @@ class GEM_EXTERN pix_opencv_contours : public GemPixObj void convexhullsMess(double arg); void convexitydefectsMess(double arg); void hierarchyMess(double arg); + void taboutputMess(float arg); + void tableMess(t_symbol*x, t_symbol*y, t_symbol*z); private: @@ -76,7 +78,9 @@ class GEM_EXTERN pix_opencv_contours : public GemPixObj double m_area_threshold; // min area for contour double m_epsilon; - int m_enable_contours, m_enable_hulls, m_enable_defects, m_hierarchy_level, m_mode; + int m_enable_contours, m_enable_hulls, m_enable_defects, m_hierarchy_level, m_mode, m_taboutput; + + t_symbol *m_x_arrayname, *m_y_arrayname, *m_z_arrayname; }; #endif // for header file -- cgit v1.2.1