From 10d9a412a7a5d56e5061f1003d1fc244c7322197 Mon Sep 17 00:00:00 2001 From: Antoine Villeret Date: Fri, 7 Dec 2012 17:57:13 +0000 Subject: - add contours and matchshape to build process - update help file svn path=/trunk/externals/pix_opencv/; revision=16651 --- pix_opencv_contours.cc | 179 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 179 insertions(+) create mode 100644 pix_opencv_contours.cc (limited to 'pix_opencv_contours.cc') diff --git a/pix_opencv_contours.cc b/pix_opencv_contours.cc new file mode 100644 index 0000000..842cbf2 --- /dev/null +++ b/pix_opencv_contours.cc @@ -0,0 +1,179 @@ +//////////////////////////////////////////////////////// +// +// 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) +// pix_opencv_contours extract and simplify contours of incomming image +// by Antoine Villeret - 2012 + +#include "pix_opencv_contours.h" +#include +#include + + +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 > contours; + std::vector 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 >::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 >::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(it->size())); + SETFLOAT(ap+1, 2.0); + + int offset(2); + + for ( std::vector::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); +} -- cgit v1.2.1