aboutsummaryrefslogtreecommitdiff
path: root/pix_opencv_contours.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'pix_opencv_contours.cpp')
-rw-r--r--pix_opencv_contours.cpp178
1 files changed, 178 insertions, 0 deletions
diff --git a/pix_opencv_contours.cpp b/pix_opencv_contours.cpp
new file mode 100644
index 0000000..0632c57
--- /dev/null
+++ b/pix_opencv_contours.cpp
@@ -0,0 +1,178 @@
+////////////////////////////////////////////////////////
+//
+// 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_contours.h"
+#include <stdio.h>
+#include <RTE/MessageCallbacks.h>
+
+
+CPPEXTERN_NEW(pix_opencv_contours)
+
+/////////////////////////////////////////////////////////
+//
+// pix_opencv_contours
+//
+/////////////////////////////////////////////////////////
+// Constructor
+//
+/////////////////////////////////////////////////////////
+pix_opencv_contours :: pix_opencv_contours() : m_area_threshold(30)
+{
+ m_dataout_middle = outlet_new(this->x_obj, 0);
+ m_dataout_right = outlet_new(this->x_obj, 0);
+
+ //~ post("build on %s at %s", __DATE__, __TIME__);
+}
+
+/////////////////////////////////////////////////////////
+// Destructor
+//
+/////////////////////////////////////////////////////////
+pix_opencv_contours :: ~pix_opencv_contours()
+{
+}
+
+/////////////////////////////////////////////////////////
+// processImage
+//
+/////////////////////////////////////////////////////////
+void pix_opencv_contours :: processRGBAImage(imageStruct &image)
+{
+ error( "pix_opencv_contours : rgba format not supported" );
+}
+
+void pix_opencv_contours :: processRGBImage(imageStruct &image) {
+ error( "pix_opencv_contours : rgb format not supported");
+}
+
+void pix_opencv_contours :: processYUVImage(imageStruct &image) {
+ error( "pix_opencv_contours : yuv format not supported" );
+}
+
+void pix_opencv_contours :: processGrayImage(imageStruct &image)
+{
+ if ( image.xsize < 0 || image.ysize < 0 ) return;
+
+ cv::Mat imgMat2( image.ysize, image.xsize, CV_8UC1, image.data, image.csize*image.xsize); // just transform imageStruct to IplImage without copying data
+
+ cv::Mat imgMat = imgMat2.clone();
+
+ std::vector<std::vector<cv::Point> > contours;
+ std::vector<cv::Point> one_contour;
+
+ contours.clear();
+ m_contours.clear();
+
+ cv::findContours(imgMat, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);
+
+ for( size_t i = 0; i < contours.size(); i++ ) {
+ if ( cv::contourArea(contours[i], false) > m_area_threshold ){
+ one_contour.clear();
+ cv::approxPolyDP(contours[i], one_contour, m_epsilon, true);
+ m_contours.push_back(one_contour);
+ }
+ }
+ //~ cv::drawContours(imgMat2, m_contours, -1, cv::Scalar(128,255,255), 3);
+
+ t_atom*info;
+ info = new t_atom[(int) m_contours.size()*14+2];
+ // info : 14x(contour_nb) matrix
+ // info for each contour : area, rotrect corner (8 float), rotrect center, rotrect size, rotation angle
+ int count(0);
+ SETFLOAT(info+1, 14.);
+ int info_offset(2);
+
+ for( std::vector<std::vector<cv::Point> >::iterator it = m_contours.begin(); it != m_contours.end(); ++it ) {
+ if (!it->empty() && it->size() > 2) {
+ SETFLOAT(info+info_offset, (float) cv::contourArea(*it));
+
+ cv::RotatedRect rot_rect = cv::minAreaRect(*it);
+ cv::Point2f corners[4];
+ rot_rect.points(corners);
+ 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);
+
+ info_offset+=14;
+ count++;
+ }
+ }
+ SETFLOAT(info, (float) count);
+ if (count) outlet_anything(m_dataout_right, gensym("info"), count*14+2, info);
+ else outlet_list(m_dataout_right, gensym("info"), 1, 0);
+
+ for( std::vector<std::vector<cv::Point> >::iterator it = m_contours.begin(); it != m_contours.end(); ++it ) {
+ if (!it->empty() && it->size() > 2) {
+ int size = 2+it->size()*2;
+ t_atom*ap = new t_atom[size];
+ SETFLOAT(ap, static_cast<t_float>(it->size()));
+ SETFLOAT(ap+1, 2.0);
+
+ int offset(2);
+
+ for ( std::vector<cv::Point>::iterator ite=it->begin(); ite!=it->end(); ++ite){
+ SETFLOAT(ap+offset,(float) (*ite).x/image.xsize);
+ SETFLOAT(ap+offset+1,(float) (*ite).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;
+}
+
+/////////////////////////////////////////////////////////
+// static member function
+//
+/////////////////////////////////////////////////////////
+void pix_opencv_contours :: obj_setupCallback(t_class *classPtr)
+{
+ CPPEXTERN_MSG1(classPtr, "epsilon", epsilonMess, double);
+ CPPEXTERN_MSG1(classPtr, "area", areaMess, double);
+}
+
+/////////////////////////////////////////////////////////
+// messages handling
+//
+/////////////////////////////////////////////////////////
+void pix_opencv_contours :: epsilonMess(double arg)
+{
+ m_epsilon = arg > 0 ? arg : 3.;
+ t_atom data_out;
+ SETFLOAT(&data_out, (float) m_epsilon);
+ outlet_anything( m_dataout_right, gensym("epsilon"), 1, &data_out);
+}
+void pix_opencv_contours :: areaMess(double arg)
+{
+ m_area_threshold = arg > 0 ? arg : 30.;
+ t_atom data_out;
+ SETFLOAT(&data_out, (float) m_area_threshold);
+ outlet_anything( m_dataout_right, gensym("area"), 1, &data_out);
+}