aboutsummaryrefslogtreecommitdiff
path: root/src/pix_opencv_warpperspective.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/pix_opencv_warpperspective.cc')
-rw-r--r--src/pix_opencv_warpperspective.cc313
1 files changed, 313 insertions, 0 deletions
diff --git a/src/pix_opencv_warpperspective.cc b/src/pix_opencv_warpperspective.cc
new file mode 100644
index 0000000..b418ee4
--- /dev/null
+++ b/src/pix_opencv_warpperspective.cc
@@ -0,0 +1,313 @@
+////////////////////////////////////////////////////////
+//
+// 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.
+//
+/////////////////////////////////////////////////////////
+//
+// pix_opencv_warpperspective by Antoine Villeret - 2011/13
+
+
+
+
+#include "pix_opencv_warpperspective.h"
+#include <stdio.h>
+
+CPPEXTERN_NEW(pix_opencv_warpperspective)
+
+/////////////////////////////////////////////////////////
+// Constructor
+//
+/////////////////////////////////////////////////////////
+
+pix_opencv_warpperspective :: pix_opencv_warpperspective()
+{
+ //inlet_new(this->x_obj, &this->x_obj->ob_pd, gensym("float"), gensym("minarea"));
+ //inlet_new(this->x_obj, &this->x_obj->ob_pd, gensym("float"), gensym("maxarea"));
+ m_dataout = outlet_new(this->x_obj, 0);
+ //m_countout = outlet_new(this->x_obj, 0);
+ comp_xsize = 320;
+ comp_ysize = 240;
+ gray = NULL;
+ tmp = NULL;
+ rgb = NULL;
+ mapMatrix = cvCreateMat(3,3,CV_32FC1);
+ srcMatrix = cvCreateMat(4,2,CV_32FC1);
+ dstMatrix = cvCreateMat(4,2,CV_32FC1);
+
+ cvSet(mapMatrix, cvScalar(0)); // set all to 0.
+ CV_MAT_ELEM( *mapMatrix, float, 0, 0 ) = 1.; // then make identity
+ CV_MAT_ELEM( *mapMatrix, float, 1, 1 ) = 1.;
+
+ // initialize srcMatrix & dstMatrix to the same...
+ CV_MAT_ELEM( *srcMatrix, float, 0, 0 ) = 0.;
+ CV_MAT_ELEM( *srcMatrix, float, 0, 1 ) = 0.;
+ CV_MAT_ELEM( *srcMatrix, float, 1, 0 ) = 1.;
+ CV_MAT_ELEM( *srcMatrix, float, 1, 1 ) = 0.;
+ CV_MAT_ELEM( *srcMatrix, float, 2, 0 ) = 1.;
+ CV_MAT_ELEM( *srcMatrix, float, 2, 1 ) = 1.;
+ CV_MAT_ELEM( *srcMatrix, float, 3, 0 ) = 0.;
+ CV_MAT_ELEM( *srcMatrix, float, 3, 1 ) = 1.;
+
+ CV_MAT_ELEM( *dstMatrix, float, 0, 0 ) = 0.;
+ CV_MAT_ELEM( *dstMatrix, float, 0, 1 ) = 0.;
+ CV_MAT_ELEM( *dstMatrix, float, 1, 0 ) = 1.;
+ CV_MAT_ELEM( *dstMatrix, float, 1, 1 ) = 0.;
+ CV_MAT_ELEM( *dstMatrix, float, 2, 0 ) = 1.;
+ CV_MAT_ELEM( *dstMatrix, float, 2, 1 ) = 1.;
+ CV_MAT_ELEM( *dstMatrix, float, 3, 0 ) = 0.;
+ CV_MAT_ELEM( *dstMatrix, float, 3, 1 ) = 1.;
+
+ mapMatrixList=new t_atom[9];
+
+ flags = CV_WARP_FILL_OUTLIERS; // TODO add a set method
+ findmethod = 0; // TODO add a set method
+
+}
+
+/////////////////////////////////////////////////////////
+// Destructor
+//
+/////////////////////////////////////////////////////////
+pix_opencv_warpperspective :: ~pix_opencv_warpperspective()
+{
+ //Destroy cv_images to clean memory
+ //if (gray) cvReleaseImage(&gray); // TODO free image header but not data because it points to Gem image...
+ if (rgb) cvReleaseImage(&rgb);
+ //if (tmp) cvReleaseImage(&tmp); // the same
+ if (mapMatrix) cvReleaseMat(&mapMatrix);
+ if (srcMatrix) cvReleaseMat(&srcMatrix);
+ if (dstMatrix) cvReleaseMat(&dstMatrix);
+}
+
+/////////////////////////////////////////////////////////
+// processImage
+//
+/////////////////////////////////////////////////////////
+void pix_opencv_warpperspective :: processRGBAImage(imageStruct &image)
+{
+ if ((this->comp_xsize!=image.xsize)||(this->comp_ysize!=image.ysize)||(!rgb))
+ {
+ this->comp_xsize = image.xsize;
+ this->comp_ysize = image.ysize;
+
+ //Destroy cv_images to clean memory
+ if(gray) cvReleaseImage(&gray);
+ if(rgb) cvReleaseImage(&rgb);
+ if(tmp) cvReleaseImage(&tmp);
+
+ // Create images with new sizes
+ rgb = cvCreateImage(cvSize(image.xsize,image.ysize), IPL_DEPTH_8U, 4);
+ tmp = cvCreateImage(cvSize(image.xsize,image.ysize), IPL_DEPTH_8U, 4);
+ }
+
+ // no need to copy a lot of memory, just point to it...
+ rgb->imageData = (char*) image.data;
+ cvWarpPerspective(rgb, tmp, mapMatrix, flags, cvScalar(0));
+ memcpy(image.data, tmp->imageData, image.xsize*image.ysize*image.csize);
+}
+
+void pix_opencv_warpperspective :: processRGBImage(imageStruct &image)
+{
+ // TODO
+ error("cant't support RGB image for now");
+}
+
+void pix_opencv_warpperspective :: processYUVImage(imageStruct &image)
+{
+ // TODO
+ error( "pix_opencv_warpperspective : yuv format not supported" );
+}
+
+void pix_opencv_warpperspective :: processGrayImage(imageStruct &image)
+{
+ if ((this->comp_xsize!=image.xsize)||(this->comp_ysize!=image.ysize)||(!gray))
+ {
+ this->comp_xsize = image.xsize;
+ this->comp_ysize = image.ysize;
+
+ //Destroy cv_images to clean memory
+ if(gray) cvReleaseImage(&gray);
+ if(rgb) cvReleaseImage(&rgb);
+ if(tmp) cvReleaseImage(&tmp);
+
+ // Create images with new sizes
+ gray = cvCreateImage(cvSize(image.xsize,image.ysize), IPL_DEPTH_8U, 1);
+ tmp = cvCreateImage(cvSize(image.xsize,image.ysize), IPL_DEPTH_8U, 1);
+ }
+
+ // no need to copy a lot of memory, just point to it...
+ gray->imageData = (char*) image.data;
+ cvWarpPerspective(gray, tmp, mapMatrix, flags, cvScalar(0));
+ memcpy(image.data, tmp->imageData, image.xsize*image.ysize);
+
+}
+
+/////////////////////////////////////////////////////////
+// floatThreshMess
+//
+/////////////////////////////////////////////////////////
+void pix_opencv_warpperspective :: mapMatrixMess (int argc, t_atom *argv)
+{
+ post("set mapMatrix");
+ int i;
+ if (argc != 9) {
+ error("map matrix should be 3x3");
+ return;
+ }
+ for ( i = 0; i < 9 ; i++) {
+ if (argv[i].a_type != A_FLOAT) {
+ error("map matrix should be float");
+ return;
+ }
+ }
+
+ // fillin the mapMatrix
+ CV_MAT_ELEM( *mapMatrix, float, 0, 0 ) = argv[0].a_w.w_float;
+ CV_MAT_ELEM( *mapMatrix, float, 1, 0 ) = argv[1].a_w.w_float;
+ CV_MAT_ELEM( *mapMatrix, float, 2, 0 ) = argv[2].a_w.w_float;
+ CV_MAT_ELEM( *mapMatrix, float, 0, 1 ) = argv[3].a_w.w_float;
+ CV_MAT_ELEM( *mapMatrix, float, 1, 1 ) = argv[4].a_w.w_float;
+ CV_MAT_ELEM( *mapMatrix, float, 2, 1 ) = argv[5].a_w.w_float;
+ CV_MAT_ELEM( *mapMatrix, float, 0, 2 ) = argv[6].a_w.w_float;
+ CV_MAT_ELEM( *mapMatrix, float, 1, 2 ) = argv[7].a_w.w_float;
+ CV_MAT_ELEM( *mapMatrix, float, 2, 2 ) = argv[8].a_w.w_float;
+
+}
+
+void pix_opencv_warpperspective :: srcMatrixMess (int argc, t_atom *argv)
+{
+ int i;
+ if ( argc % 2 ) {
+ error("src is should be a list of couple x/y values");
+ return;
+ }
+ if ( argc != dstMatrix->rows * dstMatrix->cols )
+ {
+ error("src matrix should have the same size as dst matrix (which is %d x %d)", dstMatrix->cols, dstMatrix->rows);
+ return;
+ }
+ for ( i = 0; i < argc ; i++) {
+ if (argv[i].a_type != A_FLOAT) {
+ error("src matrix should be float");
+ return;
+ }
+ }
+
+ // fillin the srcMatrix
+ for ( i = 0 ; i < dstMatrix->rows ; i++ )
+ {
+ CV_MAT_ELEM( *srcMatrix, float, i, 0 ) = argv[i*2].a_w.w_float;
+ CV_MAT_ELEM( *srcMatrix, float, i, 1 ) = argv[i*2+1].a_w.w_float; // does it work ?
+ }
+ findhomography();
+}
+
+void pix_opencv_warpperspective :: dstMatrixMess (int argc, t_atom *argv)
+{
+ int i;
+ if ( argc % 2 ){
+ error("dstMatrix is should be a list of x/y pairs");
+ return;
+ }
+ for ( i = 0; i < argc ; i++) {
+ if (argv[i].a_type != A_FLOAT) {
+ error("dstMatrix should be float");
+ return;
+ }
+ }
+ if ( dstMatrix->rows != argc/2 ) {
+ // delete and recreate matrix if needed
+ cvReleaseMat(&dstMatrix);
+ cvReleaseMat(&srcMatrix);
+ dstMatrix = cvCreateMat(argc/2,2,CV_32FC1);
+ srcMatrix = cvCreateMat(argc/2,2,CV_32FC1);
+ cvSet(srcMatrix, cvScalar(0)); // set all to 0.
+ }
+ // fillin the dstMatrix
+ for ( i = 0 ; i < dstMatrix->rows ; i++ )
+ {
+ CV_MAT_ELEM( *dstMatrix, float, i, 0 ) = argv[i*2].a_w.w_float;
+ CV_MAT_ELEM( *dstMatrix, float, i, 1 ) = argv[i*2+1].a_w.w_float; // does it work ?
+ }
+ findhomography();
+}
+
+void pix_opencv_warpperspective :: invertMess( int argc, t_atom *argv ){
+ if ( argc == 0 ){
+ error("invert need one argument (0|1)");
+ } else if ( argv[0].a_type != A_FLOAT ){
+ error("invert need one float argument (0|1)");
+ } else {
+ int invert = argv[0].a_w.w_float;
+ if (invert > 0){
+ flags |= cv::WARP_INVERSE_MAP;
+ } else {
+ flags ^= cv::WARP_INVERSE_MAP;
+ }
+ }
+}
+
+void pix_opencv_warpperspective :: findhomography( )
+{
+ int i,j;
+ if ( srcMatrix->cols != dstMatrix->cols || srcMatrix->rows != dstMatrix->rows ) {
+ error("srcMatrix and dstMatrix should have the same size to compute homography !");
+ return;
+ }
+ cvFindHomography(srcMatrix, dstMatrix, mapMatrix, findmethod, 0, NULL);
+ for ( j = 0 ; j < 3 ; j++ ){
+ for( i=0 ; i<3 ; i++){
+ SETFLOAT(&mapMatrixList[i+j*3], CV_MAT_ELEM( *mapMatrix, float, i, j));
+ }
+ }
+ // send out mapMatrix
+ outlet_list( m_dataout, 0, 9, mapMatrixList);
+}
+/////////////////////////////////////////////////////////
+// static member function
+//
+/////////////////////////////////////////////////////////
+void pix_opencv_warpperspective :: obj_setupCallback(t_class *classPtr)
+{
+ // TODO add method for message "flags"
+ // TODO treat list messages in a PD way ?
+ class_addmethod(classPtr, (t_method)&pix_opencv_warpperspective::mapMatrixMessCallback,
+ gensym("mapMatrix"), A_GIMME, A_NULL);
+ class_addmethod(classPtr, (t_method)&pix_opencv_warpperspective::srcMatrixMessCallback,
+ gensym("srcMatrix"), A_GIMME, A_NULL);
+ class_addmethod(classPtr, (t_method)&pix_opencv_warpperspective::dstMatrixMessCallback,
+ gensym("dstMatrix"), A_GIMME, A_NULL);
+ class_addmethod(classPtr, (t_method)&pix_opencv_warpperspective::invertMessCallback,
+ gensym("invert"), A_GIMME, A_NULL);
+}
+
+void pix_opencv_warpperspective :: mapMatrixMessCallback(void *data, t_symbol *s, int argc, t_atom *argv)
+{
+ GetMyClass(data)->mapMatrixMess(argc, argv);
+}
+
+void pix_opencv_warpperspective :: srcMatrixMessCallback(void *data, t_symbol *s, int argc, t_atom *argv)
+{
+ GetMyClass(data)->srcMatrixMess(argc, argv);
+}
+
+void pix_opencv_warpperspective :: dstMatrixMessCallback(void *data, t_symbol *s, int argc, t_atom *argv)
+{
+ GetMyClass(data)->dstMatrixMess(argc, argv);
+}
+
+void pix_opencv_warpperspective :: invertMessCallback(void *data, t_symbol *s, int argc, t_atom *argv)
+{
+ GetMyClass(data)->invertMess(argc, argv);
+}