aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pix_opencv_contours.cc258
-rw-r--r--pix_opencv_contours.h6
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<std::vector<cv::Point> > contours;
std::vector<cv::Vec4i> 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<t_float>(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<t_float>(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