diff options
Diffstat (limited to 'externals/gridflow/optional')
-rw-r--r-- | externals/gridflow/optional/fftw.c | 114 | ||||
-rw-r--r-- | externals/gridflow/optional/gem.c | 171 | ||||
-rw-r--r-- | externals/gridflow/optional/opencv.c | 380 |
3 files changed, 665 insertions, 0 deletions
diff --git a/externals/gridflow/optional/fftw.c b/externals/gridflow/optional/fftw.c new file mode 100644 index 00000000..e35bc9b9 --- /dev/null +++ b/externals/gridflow/optional/fftw.c @@ -0,0 +1,114 @@ +/* + GridFlow + Copyright (c) 2001-2008 by Mathieu Bouchard + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + See file ../COPYING for further informations on licensing terms. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "../gridflow.h.fcs" +#include <fftw3.h> + +#define C(x) ((fftwf_complex *)x) + +\class GridFFT : FObject { + fftwf_plan plan; + P<Dim> lastdim; /* of last input (for plan cache) */ + long lastchans; /* of last input (for plan cache) */ + \attr int sign; /* -1 or +1 */ + \attr int skip; /* 0 (y and x) or 1 (x only) */ + \attr bool real; + bool lastreal; + \constructor () {sign=-1; plan=0; lastdim=0; lastchans=0; skip=0; real=false;} + \grin 0 float32 +}; +\def 0 sign (int sign) { + if (sign!=-1 && sign!=1) RAISE("sign should be -1 or +1"); + this->sign=sign; + fftwf_destroy_plan(plan); +} +\def 0 skip (int skip) { + if (skip<0 || skip>1) RAISE("skip should be 0 or 1"); + this->skip=skip; + if (plan) {fftwf_destroy_plan(plan); plan=0;} +} +GRID_INLET(GridFFT,0) { + if (in->nt != float32_e) RAISE("expecting float32"); + if (real && sign==-1) { + if (in->dim->n != 2 && in->dim->n != 3) RAISE("expecting 2 or 3 dimensions: rows,columns,channels?"); + } else { + if (in->dim->n != 3 && in->dim->n != 4) RAISE("expecting 3 or 4 dimensions: rows,columns,channels?,complex"); + if (in->dim->get(in->dim->n-1)!=2) RAISE("expecting Dim(...,2): real,imaginary (got %d)",in->dim->get(2)); + } + in->set_chunk(0); +} GRID_FLOW { + if (skip==1 && !real) RAISE("can't do 1-D FFT in real mode, sorry"); + Dim *dim; + if (!real) dim = in->dim; + else if (sign==-1) { + int v[Dim::MAX_DIM]; + for (int i=0; i<in->dim->n; i++) v[i]=in->dim->v[i]; + v[in->dim->n] = 2; + dim = new Dim(in->dim->n+1,v); + } else dim = new Dim(in->dim->n-1,in->dim->v); + GridOutlet out(this,0,dim,in->nt); + float32 *tada = (float32 *)memalign(16,dim->prod()*sizeof(float32)); + long chans = in->dim->n>=3 ? in->dim->get(2) : 1; + CHECK_ALIGN16(data,in->nt) + CHECK_ALIGN16(tada,in->nt) + if (plan && lastdim && lastdim!=in->dim && chans!=lastchans && real==lastreal) {fftwf_destroy_plan(plan); plan=0;} + int v[] = {in->dim->v[0],in->dim->v[1],in->dim->n>2?in->dim->v[2]:1}; +// if (chans==1) { +// if (skip==0) plan = fftwf_plan_dft_2d(v[0],v[1],data,tada,sign,0); +// if (skip==1) plan = fftwf_plan_many_dft(1,&v[1],v[0],data,0,1,v[1],tada,0,1,v[1],sign,0); +// } + if (skip==0) { + //plan = fftwf_plan_dft_2d(v[0],v[1],data,tada,sign,0); + if (!plan) { + int embed[] = {dim->v[0],dim->v[1]}; + if (!real) {plan=fftwf_plan_many_dft( 2,&v[0],chans,C(data),0 ,chans,1,C(tada),0 ,chans,1,sign,0);} + else if (sign==-1) {plan=fftwf_plan_many_dft_r2c(2,&v[0],chans, data ,embed,chans,1,C(tada),embed,chans,1,0);} + else {plan=fftwf_plan_many_dft_c2r(2,&v[0],chans,C(data),embed,chans,1, tada ,embed,chans,1,0);} + } + if (!real) fftwf_execute_dft( plan,C(data),C(tada)); + else if (sign==-1) fftwf_execute_dft_r2c(plan, data ,C(tada)); + else fftwf_execute_dft_c2r(plan,C(data), tada ); + } + if (skip==1) { + if (!plan) plan=fftwf_plan_many_dft(1,&v[1],chans,C(data),0,chans,1,C(tada),0,chans,1,sign,0); + //plan = fftwf_plan_many_dft(1,&v[1],v[0],C(data),0,1,v[1],C(tada),0,1,v[1],sign,0); + long incr = v[1]*chans; + for (int i=0; i<v[0]; i++) fftwf_execute_dft(plan,C(data)+i*incr,C(tada)+i*incr); + } + if (real && sign==-1) { + for (int i=0; i<v[0]; i++) { + int h = mod(-i,v[0]); + T *tada2 = tada + (h*v[1]+v[1]/2)*v[2]*2; + T *tada3 = tada + (i*v[1]+v[1]/2)*v[2]*2; + for (int j=1+v[1]/2; j<v[1]; j++) { + tada2-=v[2]*2; tada3+=v[2]*2; + for (int k=0; k<v[2]; k++) {tada3[k+k]=tada2[k+k]; tada3[k+k+1]=-tada2[k+k+1];} + } + } + } + out.send(out.dim->prod(),tada); + free(tada); + lastdim=in->dim; lastchans=chans; lastreal=real; +} GRID_END +\end class {install("#fft",1,1);} +void startup_fftw () { + \startall +} diff --git a/externals/gridflow/optional/gem.c b/externals/gridflow/optional/gem.c new file mode 100644 index 00000000..4280855f --- /dev/null +++ b/externals/gridflow/optional/gem.c @@ -0,0 +1,171 @@ +/* + $Id: gem.c 3865 2008-06-11 21:13:58Z matju $ + + GridFlow + Copyright (c) 2001-2008 by Mathieu Bouchard + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + See file ../COPYING for further informations on licensing terms. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "../gridflow.h.fcs" +#include "Base/GemPixDualObj.h" + +struct GridToPix; +struct GridToPixHelper : GemPixObj { + GridToPix *boss; + CPPEXTERN_HEADER(GridToPixHelper,GemPixObj) +public: + GridToPixHelper () {} + virtual void startRendering(); + virtual void render(GemState *state); + virtual bool isRunnable () {return true;} // required to keep GEM 0.9.1 (the real 0.9.1) happy +}; +CPPEXTERN_NEW(GridToPixHelper) + +// in 0: gem +// in 1: grid +// out 0: gem +\class GridToPix : FObject { + GridToPixHelper *helper; + P<BitPacking> bit_packing; + pixBlock m_pixBlock; + \attr bool yflip; + GridToPix (BFObject *bself, MESSAGE) : FObject(bself,MESSAGE2) { + yflip = false; + imageStruct &im = m_pixBlock.image = imageStruct(); + im.ysize = 1; + im.xsize = 1; + im.csize = 4; + im.format = GL_RGBA; + im.type = GL_UNSIGNED_BYTE; + im.allocate(); + *(int*)im.data = 0x0000ff; + uint32 mask[4] = {0x0000ff,0x00ff00,0xff0000,0x000000}; + bit_packing = new BitPacking(is_le(),4,4,mask); + helper = new GridToPixHelper; + helper->boss = this; + bself->gemself = helper; + } + ~GridToPix () {} + \grin 1 int +}; +GRID_INLET(GridToPix,1) { + if (in->dim->n != 3) RAISE("expecting 3 dimensions: rows,columns,channels"); + if (in->dim->get(2) != 4) RAISE("expecting 4 channels (got %d)",in->dim->get(2)); + in->set_chunk(1); + imageStruct &im = m_pixBlock.image; + im.clear(); + im.ysize = in->dim->get(0); + im.xsize = in->dim->get(1); + im.csize = in->dim->get(2); + im.type = GL_UNSIGNED_BYTE; + im.allocate(); + im.format = GL_RGBA; + /* + switch (in->dim->get(2)) { + case 4: im.format = GL_RGBA; break; + default: RAISE("you shouldn't see this error message."); + } + */ +} GRID_FLOW { + uint8 *buf = (uint8 *)m_pixBlock.image.data; + /*!@#$ it would be nice to skip the bitpacking when we can */ + long sxc = in->dim->prod(1); + long sx = in->dim->v[1]; + long sy = in->dim->v[0]; + if (yflip) {for (long y= in->dex/sxc; n; data+=sxc, n-=sxc, y++) bit_packing->pack(sx,data,buf+y*sxc);} + else {for (long y=sy-1-in->dex/sxc; n; data+=sxc, n-=sxc, y--) bit_packing->pack(sx,data,buf+y*sxc);} +} GRID_END +\end class { + install("#to_pix",2,0); // outlets are 0 because GEM makes its own outlet instead + add_creator("#export_pix"); + GridToPixHelper::real_obj_setupCallback(fclass->bfclass); +} +void GridToPixHelper::obj_setupCallback(t_class *) {} +void GridToPixHelper::startRendering() {boss->m_pixBlock.newimage = 1;} +void GridToPixHelper::render(GemState *state) {state->image = &boss->m_pixBlock;} + +//------------------------------------------------------------------------ + +struct GridFromPix; +struct GridFromPixHelper : GemPixObj { + GridFromPix *boss; + CPPEXTERN_HEADER(GridFromPixHelper,GemPixObj) +public: + GridFromPixHelper () {} + virtual void render(GemState *state); + virtual bool isRunnable () {return true;} // required to keep GEM 0.9.1 (the real 0.9.1) happy +}; +CPPEXTERN_NEW(GridFromPixHelper) + +// in 0: gem (todo: auto 0 = manual mode; bang = send next frame; type = number type attr) +// out 0: grid +\class GridFromPix : FObject { + GridFromPixHelper *helper; + P<BitPacking> bit_packing; + \attr bool yflip; + GridFromPix () : FObject(0,0,0,0) {RAISE("don't call this. this exists only to make GEM happy.");} + GridFromPix (BFObject *bself, MESSAGE) : FObject(bself,MESSAGE2) { + uint32 mask[4] = {0x0000ff,0x00ff00,0xff0000,0x000000}; + bit_packing = new BitPacking(is_le(),4,4,mask); + yflip = false; + bself->gemself = (GemPixObj *)this; + helper = new GridFromPixHelper; + helper->boss = this; + bself->gemself = helper; + } + virtual ~GridFromPix () {} + void render(GemState *state) { + if (!state->image) {::post("gemstate has no pix"); return;} + imageStruct &im = state->image->image; + if (im.format != GL_RGBA ) {::post("can't produce grid from pix format %d",im.format); return;} + if (im.type != GL_UNSIGNED_BYTE) {::post("can't produce grid from pix type %d", im.type ); return;} + int32 v[] = { im.ysize, im.xsize, im.csize }; + GridOutlet out(this,0,new Dim(3,v)); + long sxc = im.xsize*im.csize; + long sy = v[0]; + uint8 buf[sxc]; + for (int y=0; y<v[0]; y++) { + uint8 *data = (uint8 *)im.data+sxc*(yflip?y:sy-1-y); + bit_packing->pack(im.xsize,data,buf); + out.send(sxc,buf); + } + } +}; + +void GridFromPixHelper::obj_setupCallback(t_class *) {} + +\end class { + install("#from_pix",2,1); + add_creator("#import_pix"); + GridFromPixHelper::real_obj_setupCallback(fclass->bfclass); +} +void GridFromPixHelper::render(GemState *state) {boss->render(state);} + +//------------------------------------------------------------------------ + +void startup_gem () { + \startall +} + +/* +virtual void processRGBAImage(imageStruct &image) {} +virtual void processRGBImage (imageStruct &image) {} +virtual void processGrayImage(imageStruct &image) {} +virtual void processYUVImage (imageStruct &image) {} +*/ + diff --git a/externals/gridflow/optional/opencv.c b/externals/gridflow/optional/opencv.c new file mode 100644 index 00000000..e9393afc --- /dev/null +++ b/externals/gridflow/optional/opencv.c @@ -0,0 +1,380 @@ +/* + $Id: opencv.c 3977 2008-07-04 20:15:08Z matju $ + + GridFlow + Copyright (c) 2001-2008 by Mathieu Bouchard + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + See file ../COPYING for further informations on licensing terms. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "../gridflow.h.fcs" +#include <opencv/cv.h> +#include <errno.h> + +int ipl_eltype(NumberTypeE e) { + switch (e) { + case uint8_e: return IPL_DEPTH_8U; + // IPL_DEPTH_8S not supported + // IPL_DEPTH_16U not supported + case int16_e: return IPL_DEPTH_16S; + case int32_e: return IPL_DEPTH_32S; + case float32_e: return IPL_DEPTH_32F; + case float64_e: return IPL_DEPTH_64F; + default: RAISE("unsupported type %s",number_type_table[e].name); + } +} + +NumberTypeE gf_ipltype(int e) { + switch (e) { + case IPL_DEPTH_8U: return uint8_e; + // IPL_DEPTH_8S not supported + // IPL_DEPTH_16U not supported + case IPL_DEPTH_16S: return int16_e; + case IPL_DEPTH_32S: return int32_e; + case IPL_DEPTH_32F: return float32_e; + case IPL_DEPTH_64F: return float64_e; + default: RAISE("unsupported IPL type %d",e); + } +} + +int cv_eltype(NumberTypeE e) { + switch (e) { + case uint8_e: return CV_8U; + // CV_8S not supported + // CV_16U not supported + case int16_e: return CV_16S; + case int32_e: return CV_32S; + case float32_e: return CV_32F; + case float64_e: return CV_64F; + default: RAISE("unsupported type %s",number_type_table[e].name); + } +} + +NumberTypeE gf_cveltype(int e) { + switch (e) { + case CV_8U: return uint8_e; + // CV_8S not supported + // CV_16U not supported + case CV_16S: return int16_e; + case CV_32S: return int32_e; + case CV_32F: return float32_e; + case CV_64F: return float64_e; + default: RAISE("unsupported CV type %d",e); + } +} + +enum CvMode { + cv_mode_auto, + cv_mode_channels, + cv_mode_nochannels, +}; + +CvMode convert (const t_atom2 &x, CvMode *foo) { + if (x==gensym("auto")) return cv_mode_auto; + if (x==gensym("channels")) return cv_mode_channels; + if (x==gensym("nochannels")) return cv_mode_nochannels; + RAISE("invalid CvMode"); +} + +CvArr *cvGrid(PtrGrid g, CvMode mode, int reqdims=-1) { + P<Dim> d = g->dim; + int channels=1; + int dims=g->dim->n; + //post("mode=%d",(int)mode); + if (mode==cv_mode_channels && g->dim->n==0) RAISE("CV: channels dimension required for 'mode channels'"); + if ((mode==cv_mode_auto && g->dim->n>=3) || mode==cv_mode_channels) channels=g->dim->v[--dims]; + if (channels>64) RAISE("CV: too many channels. max 64, got %d",channels); + //post("channels=%d dims=%d nt=%d",channels,dims,g->nt); + //post("bits=%d",number_type_table[g->nt].size); + //if (dims==2) return cvMat(g->dim->v[0],g->dim->v[1],cv_eltype(g->nt),g->data); + if (reqdims>=0 && reqdims!=dims) RAISE("CV: wrong number of dimensions. expected %d, got %d", reqdims, dims); + if (dims==2) { + CvMat *a = cvCreateMatHeader(g->dim->v[0],g->dim->v[1],CV_MAKETYPE(cv_eltype(g->nt),channels)); + cvSetData(a,g->data,g->dim->prod(1)*(number_type_table[g->nt].size/8)); + return a; + } + RAISE("unsupported number of dimensions (got %d)",g->dim->n); + //return 0; +} + +IplImage *cvImageGrid(PtrGrid g /*, CvMode mode */) { + P<Dim> d = g->dim; + if (d->n!=3) RAISE("expected 3 dimensions, got %s",d->to_s()); + int channels=g->dim->v[2]; + if (channels>64) RAISE("too many channels. max 64, got %d",channels); + CvSize size = {d->v[1],d->v[0]}; + IplImage *a = cvCreateImageHeader(size,ipl_eltype(g->nt),channels); + cvSetData(a,g->data,g->dim->prod(1)*(number_type_table[g->nt].size/8)); + return a; +} + +\class CvOp1 : FObject { + \attr CvMode mode; + \constructor () {mode = cv_mode_auto;} + /* has no default \grin 0 handler so far. */ +}; +\end class {} + +\class CvOp2 : CvOp1 { + PtrGrid r; + \constructor (Grid *r=0) {this->r = r?r:new Grid(new Dim(),int32_e,true);} + virtual void func(CvArr *l, CvArr *r, CvArr *o) {/* rien */} + \grin 0 + \grin 1 +}; +GRID_INLET(CvOp2,0) { + SAME_TYPE(in,r); + if (!in->dim->equal(r->dim)) RAISE("dimension mismatch: left:%s right:%s",in->dim->to_s(),r->dim->to_s()); + in->set_chunk(0); +} GRID_FLOW { + PtrGrid l = new Grid(in->dim,(T *)data); + PtrGrid o = new Grid(in->dim,in->nt); + CvArr *a = cvGrid(l,mode); + CvArr *b = cvGrid(r,mode); + CvArr *c = cvGrid(o,mode); + func(a,b,c); + cvReleaseMat((CvMat **)&a); + cvReleaseMat((CvMat **)&b); + cvReleaseMat((CvMat **)&c); + out = new GridOutlet(this,0,in->dim,in->nt); + out->send(o->dim->prod(),(T *)o->data); +} GRID_END +GRID_INPUT2(CvOp2,1,r) {} GRID_END +\end class {} + +#define FUNC(CLASS) CLASS(BFObject *bself, MESSAGE):CvOp2(bself,MESSAGE2) {} virtual void func(CvArr *l, CvArr *r, CvArr *o) + +\class CvAdd : CvOp2 {FUNC(CvAdd) {cvAdd(l,r,o,0);}}; +\end class {install("cv.Add",2,1);} +\class CvSub : CvOp2 {FUNC(CvSub) {cvSub(l,r,o,0);}}; +\end class {install("cv.Sub",2,1);} +\class CvMul : CvOp2 {FUNC(CvMul) {cvMul(l,r,o,1);}}; +\end class {install("cv.Mul",2,1);} +\class CvDiv : CvOp2 {FUNC(CvDiv) {cvDiv(l,r,o,1);}}; +\end class {install("cv.Div",2,1);} +\class CvAnd : CvOp2 {FUNC(CvAnd) {cvAnd(l,r,o,0);}}; +\end class {install("cv.And",2,1);} +\class CvOr : CvOp2 {FUNC(CvOr ) {cvOr( l,r,o,0);}}; +\end class {install("cv.Or" ,2,1);} +\class CvXor : CvOp2 {FUNC(CvXor) {cvXor(l,r,o,0);}}; +\end class {install("cv.Xor",2,1);} + +\class CvInvert : CvOp1 { + \constructor () {} + \grin 0 +}; +GRID_INLET(CvInvert,0) { + if (in->dim->n!=2) RAISE("should have 2 dimensions"); + if (in->dim->v[0] != in->dim->v[1]) RAISE("matrix should be square"); + in->set_chunk(0); +} GRID_FLOW { + //post("l=%p, r=%p", &*l, &*r); + PtrGrid l = new Grid(in->dim,(T *)data); + PtrGrid o = new Grid(in->dim,in->nt); + CvArr *a = cvGrid(l,mode); + CvArr *c = cvGrid(o,mode); + //post("a=%p, b=%p", a, b); + cvInvert(a,c); + cvReleaseMat((CvMat **)&a); + cvReleaseMat((CvMat **)&c); + out = new GridOutlet(this,0,in->dim,in->nt); + out->send(o->dim->prod(),(T *)o->data); +} GRID_END +\end class {install("cv.Invert",1,1);} + +\class CvSVD : CvOp1 { + \grin 0 + \constructor () {} +}; +GRID_INLET(CvSVD,0) { + if (in->dim->n!=2) RAISE("should have 2 dimensions"); + if (in->dim->v[0] != in->dim->v[1]) RAISE("matrix should be square"); + in->set_chunk(0); +} GRID_FLOW { + PtrGrid l = new Grid(in->dim,(T *)data); + PtrGrid o0 = new Grid(in->dim,in->nt); + PtrGrid o1 = new Grid(in->dim,in->nt); + PtrGrid o2 = new Grid(in->dim,in->nt); + CvArr *a = cvGrid(l,mode); + CvArr *c0 = cvGrid(o0,mode); + CvArr *c1 = cvGrid(o1,mode); + CvArr *c2 = cvGrid(o2,mode); + cvSVD(a,c0,c1,c2); + cvReleaseMat((CvMat **)&a); + cvReleaseMat((CvMat **)&c0); + cvReleaseMat((CvMat **)&c1); + cvReleaseMat((CvMat **)&c2); + out = new GridOutlet(this,2,in->dim,in->nt); out->send(o2->dim->prod(),(T *)o2->data); + out = new GridOutlet(this,1,in->dim,in->nt); out->send(o1->dim->prod(),(T *)o1->data); + out = new GridOutlet(this,0,in->dim,in->nt); out->send(o0->dim->prod(),(T *)o0->data); +} GRID_END +\end class {install("cv.SVD",1,3);} + +\class CvSplit : CvOp1 { + int channels; + \constructor (int channels) { + if (channels<0 || channels>64) RAISE("channels=%d is not in 1..64",channels); + this->channels = channels; + bself->noutlets_set(channels); + } +}; +\end class {} + +\class CvHaarDetectObjects : FObject { + \attr double scale_factor; /*=1.1*/ + \attr int min_neighbors; /*=3*/ + \attr int flags; /*=0*/ + \constructor () { + scale_factor=1.1; + min_neighbors=3; + flags=0; + //cascade = cvLoadHaarClassifierCascade("<default_face_cascade>",cvSize(24,24)); + const char *filename = OPENCV_SHARE_PATH "/haarcascades/haarcascade_frontalface_alt2.xml"; + FILE *f = fopen(filename,"r"); + if (!f) RAISE("error opening %s: %s",filename,strerror(errno)); + fclose(f); + cascade = (CvHaarClassifierCascade *)cvLoad(filename,0,0,0); + int s = cvGetErrStatus(); + post("cascade=%p, cvGetErrStatus=%d cvErrorStr=%s",cascade,s,cvErrorStr(s)); + //cascade = cvLoadHaarClassifierCascade(OPENCV_SHARE_PATH "/data/haarcascades/haarcascade_frontalface_alt2.xml",cvSize(24,24)); + storage = cvCreateMemStorage(0); + } + CvHaarClassifierCascade *cascade; + CvMemStorage *storage; + \grin 0 +}; +GRID_INLET(CvHaarDetectObjects,0) { + in->set_chunk(0); +} GRID_FLOW { + PtrGrid l = new Grid(in->dim,(T *)data); + IplImage *img = cvImageGrid(l); + CvSeq *ret = cvHaarDetectObjects(img,cascade,storage,scale_factor,min_neighbors,flags); + int n = ret ? ret->total : 0; + out = new GridOutlet(this,0,new Dim(n,2,2)); + for (int i=0; i<n; i++) { + CvRect *r = (CvRect *)cvGetSeqElem(ret,i); + int32 duh[] = {r->y,r->x,r->y+r->height,r->x+r->width}; + out->send(4,duh); + } +} GRID_END +\end class {install("cv.HaarDetectObjects",2,1);} + +\class CvKalmanWrapper : CvOp1 { + CvKalman *kal; + \constructor (int dynam_params, int measure_params, int control_params=0) { + kal = cvCreateKalman(dynam_params,measure_params,control_params); + } + ~CvKalmanWrapper () {if (kal) cvReleaseKalman(&kal);} + \decl void _0_bang (); + \grin 0 + \grin 1 +}; + +void cvMatSend(const CvMat *self, FObject *obj, int outno) { + int m = self->rows; + int n = self->cols; + int e = CV_MAT_TYPE(cvGetElemType(self)); + int c = CV_MAT_CN( cvGetElemType(self)); + GridOutlet *out = new GridOutlet(obj,0,new Dim(m,n)); + for (int i=0; i<m; i++) { + uchar *meuh = cvPtr2D(self,i,0,0); + switch (e) { + case CV_8U: out->send(c*n, (uint8 *)meuh); break; + case CV_16S: out->send(c*n, (int16 *)meuh); break; + case CV_32S: out->send(c*n, (int32 *)meuh); break; + case CV_32F: out->send(c*n,(float32 *)meuh); break; + case CV_64F: out->send(c*n,(float64 *)meuh); break; + } + } +} + +\def void _0_bang () { + const CvMat *r = cvKalmanPredict(kal,0); + cvMatSend(r,this,0); +} + +GRID_INLET(CvKalmanWrapper,0) { + in->set_chunk(0); +} GRID_FLOW { + PtrGrid l = new Grid(in->dim,(T *)data); + CvMat *a = (CvMat *)cvGrid(l,mode,2); + const CvMat *r = cvKalmanPredict(kal,a); + cvMatSend(r,this,0); +} GRID_END + +GRID_INLET(CvKalmanWrapper,1) { + in->set_chunk(0); +} GRID_FLOW { + PtrGrid l = new Grid(in->dim,(T *)data); + CvMat *a = (CvMat *)cvGrid(l,mode,2); + const CvMat* r = cvKalmanCorrect(kal,a); + cvMatSend(r,this,0); +} GRID_END +\end class {install("cv.Kalman",2,1);} + +//\class CvEllipse : FObject { +// \grin 0 +//}; +//GRID_INLET(CvEllipse,0) { +// in->set_chunk(0); +//} GRID_FLOW { +//} GRID_END +//\end class {install("cv.Ellipse",1,1);} + +/* +void cvEllipse( CvArr* img, CvPoint center, CvSize axes, double angle, + double start_angle, double end_angle, CvScalar color, + int thickness=1, int line_type=8, int shift=0 ); +CvSeq* cvApproxPoly( const void* src_seq, int header_size, CvMemStorage* storage, + int method, double parameter, int parameter2=0 ); +void cvCalcOpticalFlowHS( const CvArr* prev, const CvArr* curr, int use_previous, + CvArr* velx, CvArr* vely, double lambda, + CvTermCriteria criteria ); +void cvCalcOpticalFlowLK( const CvArr* prev, const CvArr* curr, CvSize win_size, + CvArr* velx, CvArr* vely ); +void cvCalcOpticalFlowBM( const CvArr* prev, const CvArr* curr, CvSize block_size, + CvSize shift_size, CvSize max_range, int use_previous, + CvArr* velx, CvArr* vely ); +void cvCalcOpticalFlowPyrLK( const CvArr* prev, const CvArr* curr, CvArr* prev_pyr, CvArr* curr_pyr, + const CvPoint2D32f* prev_features, CvPoint2D32f* curr_features, + int count, CvSize win_size, int level, char* status, + float* track_error, CvTermCriteria criteria, int flags ); +void cvCalcBackProject( IplImage** image, CvArr* back_project, const CvHistogram* hist ); +void cvCalcHist( IplImage** image, CvHistogram* hist, int accumulate=0, const CvArr* mask=NULL ); +CvHistogram* cvCreateHist( int dims, int* sizes, int type, float** ranges=NULL, int uniform=1 ); +void cvSnakeImage( const IplImage* image, CvPoint* points, int length, + float* alpha, float* beta, float* gamma, int coeff_usage, + CvSize win, CvTermCriteria criteria, int calc_gradient=1 ); +int cvMeanShift( const CvArr* prob_image, CvRect window, CvTermCriteria criteria, CvConnectedComp* comp ); +int cvCamShift( const CvArr* prob_image, CvRect window, CvTermCriteria criteria, CvConnectedComp* comp, CvBox2D* box=NULL ); +*/ + +/* **************************************************************** */ + +static int erreur_handleur (int status, const char* func_name, const char* err_msg, const char* file_name, int line, void *userdata) { + cvSetErrStatus(CV_StsOk); + // we might be looking for trouble because we don't know whether OpenCV is throw-proof. + RAISE("OpenCV error: status='%s' func_name=%s err_msg=\"%s\" file_name=%s line=%d",cvErrorStr(status),func_name,err_msg,file_name,line); + // if this breaks OpenCV, then we will have to use post() or a custom hybrid of post() and RAISE() that does not cause a + // longjmp when any OpenCV functions are on the stack. + return 0; +} + +void startup_opencv() { + /* CvErrorCallback z = */ cvRedirectError(erreur_handleur); + \startall +} |