00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073 #include "BeoSub/CannyModel.H"
00074 #include "BeoSub/hysteresis.H"
00075 #include "Component/ModelManager.H"
00076 #include "Devices/FrameGrabberFactory.H"
00077 #include "GUI/XWindow.H"
00078 #include "Image/ColorOps.H"
00079 #include "Image/DrawOps.H"
00080 #include "Image/FilterOps.H"
00081 #include "Image/Image.H"
00082 #include "Image/MathOps.H"
00083 #include "Image/MorphOps.H"
00084 #include "Image/Transforms.H"
00085 #include "Raster/Raster.H"
00086 #include "Util/MathFunctions.H"
00087 #include "Util/Timer.H"
00088 #include "Util/Types.H"
00089 #include "Util/log.H"
00090 #include "VFAT/segmentImageTrackMC.H"
00091 #include "rutz/shared_ptr.h"
00092
00093 #include <algorithm>
00094 #include <cmath>
00095 #include <cstdio>
00096 #include <cstdlib>
00097 #include <cstring>
00098
00099
00100 #define BOOSTBLURFACTOR 90.0
00101
00102 #define TOL 2.0e-4
00103 #define ITMAX 200
00104
00105 #define ITMAXB 100
00106 #define CGOLD 0.3819660
00107 #define ZEPS 1.0e-10
00108 #define SHFT(a,b,c,d) (a)=(b);(b)=(c);(c)=(d);
00109 #define SIGN(a,b) ((b)>=0.0?fabs(a):-fabs(a))
00110
00111 #define GOLD 1.618034
00112 #define GLIMIT 100.0
00113 #define TINY 1.0e-20
00114
00115
00116
00117
00118 #define FREE_ARG char*
00119
00120
00121
00122 int canny(unsigned char *image, int rows, int cols, float sigma,
00123 float tlow, float thigh, unsigned char **edge, const char* fname);
00124 void gaussian_smooth(unsigned char *image, int rows, int cols, float sigma,
00125 short int **smoothedim);
00126 void make_gaussian_kernel(float sigma, float **kernel, int *windowsize);
00127 void derrivative_x_y(short int *smoothedim, int rows, int cols,
00128 short int **delta_x, short int **delta_y);
00129 void magnitude_x_y(short int *delta_x, short int *delta_y, int rows, int cols,
00130 short int **magnitude);
00131 void radian_direction(short int *delta_x, short int *delta_y, int rows,
00132 int cols, float **dir_radians, int xdirtag, int ydirtag);
00133 void radian_direction(short int *delta_x, short int *delta_y, int rows,
00134 int cols, float **dir_radians, int xdirtag, int ydirtag);
00135 double angle_radians(double x, double y);
00136 void grabImage(Image<PixRGB<byte> >* image);
00137
00138 Image<float> distMap;
00139 rutz::shared_ptr<XWindow> xwin, win;
00140 const bool debugmode = true;
00141
00142
00143
00144 bool fromFile = true;
00145
00146 const char *infilename = NULL;
00147 const char *dirfilename = NULL;
00148 const char *shapeArg = NULL;
00149 const char *colorArg = NULL;
00150 char outfilename[128];
00151 char composedfname[128];
00152 unsigned char *edge;
00153 float sigma,
00154 tlow,
00155 thigh;
00156
00157
00158
00159
00160
00161 int imgW, imgH, ww, hh;
00162 Image< PixRGB<byte> > colorImg;
00163 Image<byte> grayImg;
00164
00165 Image< PixRGB<byte> > display;
00166 Image<byte> temp;
00167 Image<PixRGB<byte> > Aux;
00168 Image<PixH2SV2<float> > H2SVimage;
00169
00170
00171 ModelManager manager("Canny Tester");
00172
00173 nub::soft_ref<FrameIstream>
00174 gb(makeIEEE1394grabber(manager, "cannycam", "cc"));
00175
00176
00177 segmentImageTrackMC<float,unsigned int,4> *segmenter;
00178
00179
00180 std::vector<float> color(4,0.0F);
00181
00182 bool runCanny(bool fromFile, bool useColor, const char* shapeArg);
00183
00184
00185
00186
00187
00188
00189
00190
00191 bool powell(double p[], double **xi, int n, double ftol,
00192 int *iter, double *fret, rutz::shared_ptr<ShapeModel>& optimizee);
00193 int ncom;
00194 double *pcom,*xicom;
00195
00196 double brent(double ax, double bx, double cx,
00197 double (*f)(double, rutz::shared_ptr<ShapeModel>&), double tol,
00198 double *xmin, rutz::shared_ptr<ShapeModel>& shape);
00199 void mnbrak(double *ax, double *bx, double *cx, double *fa, double *fb,
00200 double *fc, double (*func)(double, rutz::shared_ptr<ShapeModel>&),
00201 rutz::shared_ptr<ShapeModel>& shape);
00202 double f1dim(double x, rutz::shared_ptr<ShapeModel>& shape);
00203 void linmin(double p[], double xi[], int n, double *fret,
00204 rutz::shared_ptr<ShapeModel>& optimizee);
00205
00206
00207
00208
00209
00210 double *nrVector(long nl, long nh)
00211
00212 {
00213 double *v;
00214
00215 v=(double *)malloc((size_t) ((nh-nl+2)*sizeof(double)));
00216 if (!v) printf("allocation failure in nrVector()");
00217 return v-nl+1;
00218 }
00219
00220 void free_nrVector(double *v, long nl, long nh)
00221
00222 {
00223 free((FREE_ARG) (v+nl-1));
00224 }
00225
00226
00227
00228 int main(int argc, char *argv[])
00229 {
00230
00231
00232
00233 sigma = .5;
00234 tlow = .5;
00235 thigh = .5;
00236
00237 bool useColor = true;
00238
00239 manager.addSubComponent(gb);
00240
00241
00242
00243
00244 gb->setModelParamVal("FrameGrabberSubChan", 0);
00245
00246
00247
00248
00249
00250
00251 if(argc < 3){
00252 fprintf(stderr,"\n<USAGE> %s image shape color \n",argv[0]);
00253 fprintf(stderr,"\n image: An image to process. Must be in PGM format.\n");
00254 fprintf(stderr," Type 'none' for camera input.\n");
00255 fprintf(stderr," shape: Shape on which to run recognition\n");
00256 fprintf(stderr," Candidates: Rectangle, Square, Circle, Octagon.\n");
00257 fprintf(stderr," color: Color to track\n");
00258 fprintf(stderr," Candidates: Blue, Yellow, none (for no color tracking).\n");
00259 exit(1);
00260 }
00261 infilename = argv[1];
00262 shapeArg = argv[2];
00263 colorArg = argv[3];
00264
00265 printf("READ: 1: %s 2: %s 3: %s\n", infilename, shapeArg, colorArg);
00266
00267 if(!strcmp(infilename, "none")){
00268 fromFile = false;
00269 infilename = "../../bin/Camera.pgm";
00270 }
00271
00272
00273 if(argc == 6) dirfilename = infilename;
00274 else dirfilename = NULL;
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287 if(!strcmp(colorArg, "Red")){
00288
00289 color[0] = 0.70000F; color[1] = 0.94400F; color[2] = 0.67200F; color[3] = 0.96900F;
00290 }
00291
00292 else if(!strcmp(colorArg, "Green")){
00293
00294 color[0] = 0.53000F; color[1] = 0.36000F; color[2] = 0.44600F; color[3] = 0.92000F;
00295 }
00296
00297 else if(!strcmp(colorArg, "Orange")){
00298
00299 color[0] = 0.80000F; color[1] = 0.80000F; color[2] = 0.57600F; color[3] = 0.96800F;
00300 }
00301 else if(!strcmp(colorArg, "Blue")){
00302
00303 color[0] = 0.27500F; color[1] = 0.52500F; color[2] = 0.44500F; color[3] = 0.97200F;
00304 }
00305 else if(!strcmp(colorArg, "Yellow")){
00306
00307 color[0] = 0.90000F; color[1] = 0.62000F; color[2] = 0.54000F; color[3] = 0.97000F;
00308 }
00309 else{
00310 useColor = false;
00311 }
00312
00313
00314 std::vector<float> std(4,0.0F);
00315
00316 std[0] = 0.30000; std[1] = 0.30000; std[2] = 0.44500; std[3] = 0.45000;
00317
00318
00319 std::vector<float> norm(4,0.0F);
00320 norm[0] = 1.0F; norm[1] = 1.0F; norm[2] = 1.0F; norm[3] = 1.0F;
00321
00322
00323
00324
00325 std::vector<float> adapt(4,0.0F);
00326
00327 adapt[0] = 5.0F; adapt[1] = 5.0F; adapt[2] = 5.0F; adapt[3] = 5.0F;
00328
00329
00330 std::vector<float> upperBound(4,0.0F);
00331 upperBound[0] = color[0] + 0.45F; upperBound[1] = color[1] + 0.45F; upperBound[2] = color[2] + 0.55F; upperBound[3] = color[3] + 0.55F;
00332
00333
00334 std::vector<float> lowerBound(4,0.0F);
00335 lowerBound[0] = color[0] - 0.45F; lowerBound[1] = color[1] - 0.45F; lowerBound[2] = color[2] - 0.55F; lowerBound[3] = color[3] - 0.55F;
00336
00337
00338
00339 if(fromFile){
00340 colorImg = Raster::ReadRGB(infilename);
00341 imgW = colorImg.getWidth();
00342 imgH = colorImg.getHeight();
00343 }
00344 else{
00345
00346
00347
00348
00349
00350 imgH = gb->getHeight();
00351 imgW = gb->getWidth();
00352
00353 }
00354
00355 segmenter = new segmentImageTrackMC<float,unsigned int,4> (imgW*imgH);
00356
00357 segmenter->SITsetTrackColor(&color,&std,&norm,&adapt,&upperBound,&lowerBound);
00358
00359 ww = imgW/4;
00360 hh = imgH/4;
00361
00362 segmenter->SITsetFrame(&ww,&hh);
00363
00364
00365
00366 segmenter->SITsetCircleColor(0,255,0);
00367 segmenter->SITsetBoxColor(255,255,0,0,255,255);
00368 segmenter->SITsetUseSmoothing(true,10);
00369
00370
00371 segmenter->SITtoggleColorAdaptation(false);
00372
00373 segmenter->SITtoggleCandidateBandPass(false);
00374
00375 Image<PixRGB<byte> > Aux;
00376 Aux.resize(100,450,true);
00377 Image<byte> temp;
00378 Image< PixRGB<byte> > display = colorImg;
00379
00380 if(fromFile){
00381
00382 if(useColor){
00383 segmenter->SITtrackImage(colorImg,&display,&Aux,true);
00384 temp = segmenter->SITreturnCandidateImage();
00385
00386 grayImg = luminance(temp);
00387 }
00388 else{
00389 grayImg = luminance(colorImg);
00390 }
00391 }
00392 else{
00393
00394 win.reset( new XWindow(gb->peekDims(), -1, -1, "test-canny window") );
00395
00396 segmenter->SITsetTrackColor(&color,&std,&norm,&adapt,&upperBound,&lowerBound);
00397 ww = imgW/4;
00398 hh = imgH/4;
00399 segmenter->SITsetFrame(&ww,&hh);
00400
00401
00402 segmenter->SITsetCircleColor(0,255,0);
00403 segmenter->SITsetBoxColor(255,255,0,0,255,255);
00404 segmenter->SITsetUseSmoothing(true,10);
00405
00406 Aux.resize(100,450,true);
00407
00408 }
00409
00410 if(fromFile){
00411 runCanny(fromFile, useColor, shapeArg);
00412 }
00413 else{
00414
00415
00416 manager.start();
00417
00418
00419 gb->startStream();
00420
00421 colorImg = gb->readRGB();
00422
00423 xwin.reset(new XWindow(colorImg.getDims()));
00424 xwin->setPosition(colorImg.getWidth(), 0);
00425 while(1){
00426 runCanny(fromFile, useColor, shapeArg);
00427 }
00428
00429 manager.stop();
00430 }
00431 }
00432
00433 bool runCanny(bool fromFile, bool useColor, const char* shapeArg){
00434
00435 if(!fromFile){
00436 int i;
00437 for(i = 0; i < 30; i++) {
00438
00439 colorImg = gb->readRGB();
00440 win->drawImage(colorImg);
00441 }
00442
00443
00444 H2SVimage = colorImg;
00445 display = colorImg;
00446 segmenter->SITtrackImageAny(H2SVimage,&display,&Aux,true);
00447 temp = segmenter->SITreturnCandidateImage();
00448
00449
00450 Image<byte> se1(5, 5, ZEROS);
00451 Point2D<int> t1(2,2);
00452 drawDisk(se1, t1, 2, static_cast<byte>(255));
00453
00454 Image<byte> se2(9, 9, ZEROS);
00455 Point2D<int> t2(4,4);
00456 drawDisk(se2, t2, 3, static_cast<byte>(255));
00457
00458
00459
00460
00461
00462 temp = closeImg(temp, se2);
00463
00464 if(useColor){
00465 grayImg = (Image<byte>)(quickInterpolate(temp,4));
00466 }
00467 else{
00468 grayImg = luminance(colorImg);
00469 }
00470
00471 }
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488 canny(grayImg.getArrayPtr(), grayImg.getHeight(), grayImg.getWidth(), sigma, tlow, thigh, &edge, dirfilename);
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502 Image<unsigned char> cannyCharImg(edge, grayImg.getWidth(), grayImg.getHeight());
00503
00504 Image<float> cannyImg = cannyCharImg;
00505
00506 Raster::WriteGray(cannyImg, outfilename, RASFMT_PNM);
00507
00508 xwin->drawImage((Image< PixRGB<byte> >)grayImg);
00509
00510 Point2D<int> cent = centroid(cannyCharImg);
00511 distMap = chamfer34(cannyImg, 5000.0f);
00512
00513
00514
00515 rutz::shared_ptr<ShapeModel> shape;
00516 double* p = NULL;
00517
00518 int iter = 0;
00519 double fret = 0.0;
00520 bool shapeFound = false;
00521
00522
00523 {
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537 if(!strcmp(shapeArg, "Rectangle")){
00538
00539
00540
00541 p = (double*)calloc(6, sizeof(double));
00542 p[1] = (double)(cent.i);
00543 p[2] = (double)(cent.j);
00544 p[4] = 170.0f;
00545 p[5] = 140.0f;
00546 p[3] = 0.0;
00547
00548 shape.reset(new RectangleShape(120.0, p, true));
00549 }
00550 else if(!strcmp(shapeArg, "Square")){
00551
00552
00553 p = (double*)calloc(5, sizeof(double));
00554 p[1] = (double)(cent.i);
00555 p[2] = (double)(cent.j);
00556 p[3] = 100.0f;
00557 p[4] = 0.0;
00558
00559 shape.reset(new SquareShape(100.0, p, true));
00560 }
00561 else if(!strcmp(shapeArg, "Octagon")){
00562
00563
00564 p = (double*)calloc(5, sizeof(double));
00565 p[1] = (double)(cent.i);
00566 p[2] = (double)(cent.j);
00567 p[3] = 80.0f;
00568 p[4] = 0.0;
00569
00570 shape.reset(new OctagonShape(80.0, p, true));
00571 }
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582 else if(!strcmp(shapeArg, "Circle")){
00583
00584 p = (double*)calloc(4, sizeof(double));
00585 p[1] = (double)(cent.i);
00586 p[2] = (double)(cent.j);
00587 p[3] = 50.0f;
00588
00589
00590 shape.reset(new CircleShape(40.0, p, true));
00591 }
00592 else{
00593 printf("Cannot run shape recognition without a shape to recognize! Returning...\n");
00594 shape.reset(new CircleShape(9999.0, p, false));
00595 return(false);
00596 }
00597
00598 double** xi = (double**)calloc(shape->getNumDims(), sizeof(double));
00599
00600
00601 for(int i=0; i < shape->getNumDims(); i++) {
00602 xi[i] = (double*)calloc(shape->getNumDims(), sizeof(double));
00603 xi[i][i] = 1.0;
00604 }
00605
00606 xi[0][0] = 0.5;
00607 xi[0][1] = 0.5;
00608
00609
00610 shapeFound = powell(shape->getDimensions(), xi, shape->getNumDims(), 0.5, &iter, &fret, shape);
00611 if(shapeFound){
00612 p = shape->getDimensions();
00613 printf("Shape found!\n");
00614 printf("Final dimensions are -- ");
00615 for(int w = 1; w <=shape->getNumDims(); w++){
00616 printf("%d: %f ", w, p[w]);
00617 }
00618 printf("Certainty (lower is better): %f\n", fret);
00619 }else{
00620 printf("Shape not found -- certainty was %f\n", fret);
00621 }
00622 }
00623
00624
00625
00626
00627
00628
00629 return(shapeFound);
00630 }
00631
00632 void mnbrak(double *ax, double *bx, double *cx, double *fa, double *fb,
00633 double *fc, double (*func)(double, rutz::shared_ptr<ShapeModel>& ),
00634 rutz::shared_ptr<ShapeModel>& shape)
00635 {
00636 double ulim,u,r,q,fu,dum;
00637
00638 *fa=(*func)(*ax, shape);
00639 *fb=(*func)(*bx, shape);
00640 if (*fb > *fa) {
00641 SHFT(dum,*ax,*bx,dum)
00642 SHFT(dum,*fb,*fa,dum)
00643 }
00644 *cx=(*bx)+GOLD*(*bx-*ax);
00645 *fc=(*func)(*cx, shape);
00646 while (*fb > *fc) {
00647 r=(*bx-*ax)*(*fb-*fc);
00648 q=(*bx-*cx)*(*fb-*fa);
00649 u=(*bx)-((*bx-*cx)*q-(*bx-*ax)*r)/
00650 (2.0*SIGN(std::max(fabs(q-r),TINY),q-r));
00651 ulim=(*bx)+GLIMIT*(*cx-*bx);
00652 if ((*bx-u)*(u-*cx) > 0.0) {
00653 fu=(*func)(u, shape);
00654 if (fu < *fc) {
00655 *ax=(*bx);
00656 *bx=u;
00657 *fa=(*fb);
00658 *fb=fu;
00659 return;
00660 } else if (fu > *fb) {
00661 *cx=u;
00662 *fc=fu;
00663 return;
00664 }
00665 u=(*cx)+GOLD*(*cx-*bx);
00666 fu=(*func)(u, shape);
00667 } else if ((*cx-u)*(u-ulim) > 0.0) {
00668 fu=(*func)(u, shape);
00669 if (fu < *fc) {
00670 SHFT(*bx,*cx,u,*cx+GOLD*(*cx-*bx))
00671 SHFT(*fb,*fc,fu,(*func)(u, shape))
00672 }
00673 } else if ((u-ulim)*(ulim-*cx) >= 0.0) {
00674 u=ulim;
00675 fu=(*func)(u, shape);
00676 } else {
00677 u=(*cx)+GOLD*(*cx-*bx);
00678 fu=(*func)(u, shape);
00679 }
00680 SHFT(*ax,*bx,*cx,u)
00681 SHFT(*fa,*fb,*fc,fu)
00682 }
00683 }
00684
00685 double brent(double ax, double bx, double cx, double (*f)(double, rutz::shared_ptr<ShapeModel>&), double tol,
00686 double *xmin, rutz::shared_ptr<ShapeModel>& shape)
00687 {
00688 int iter;
00689 double a,b,d=0.0,etemp,fu,fv,fw,fx,p,q,r,tol1,tol2,u,v,w,x,xm;
00690 double e=0.0;
00691
00692 a=(ax < cx ? ax : cx);
00693 b=(ax > cx ? ax : cx);
00694 x=w=v=bx;
00695 fw=fv=fx=(*f)(x, shape);
00696 for (iter=1;iter<=ITMAXB;iter++) {
00697 xm=0.5*(a+b);
00698 tol2=2.0*(tol1=tol*fabs(x)+ZEPS);
00699 if (fabs(x-xm) <= (tol2-0.5*(b-a))) {
00700 *xmin=x;
00701 return fx;
00702 }
00703 if (fabs(e) > tol1) {
00704 r=(x-w)*(fx-fv);
00705 q=(x-v)*(fx-fw);
00706 p=(x-v)*q-(x-w)*r;
00707 q=2.0*(q-r);
00708 if (q > 0.0) p = -p;
00709 q=fabs(q);
00710 etemp=e;
00711 e=d;
00712 if (fabs(p) >= fabs(0.5*q*etemp) || p <= q*(a-x) || p >= q*(b-x))
00713 d=CGOLD*(e=(x >= xm ? a-x : b-x));
00714 else {
00715 d=p/q;
00716 u=x+d;
00717 if (u-a < tol2 || b-u < tol2)
00718 d=SIGN(tol1,xm-x);
00719 }
00720 } else {
00721 d=CGOLD*(e=(x >= xm ? a-x : b-x));
00722 }
00723 u=(fabs(d) >= tol1 ? x+d : x+SIGN(tol1,d));
00724 fu=(*f)(u, shape);
00725 if (fu <= fx) {
00726 if (u >= x) a=x; else b=x;
00727 SHFT(v,w,x,u)
00728 SHFT(fv,fw,fx,fu)
00729 } else {
00730 if (u < x) a=u; else b=u;
00731 if (fu <= fw || w == x) {
00732 v=w;
00733 w=u;
00734 fv=fw;
00735 fw=fu;
00736 } else if (fu <= fv || v == x || v == w) {
00737 v=u;
00738 fv=fu;
00739 }
00740 }
00741 }
00742 printf("Too many iterations in brent");
00743 *xmin=x;
00744 return fx;
00745 }
00746
00747
00748 double f1dim(double x, rutz::shared_ptr<ShapeModel>& shape)
00749 {
00750 int j;
00751 double f, *xt;
00752 xt=nrVector(1,ncom);
00753
00754 for (j=1;j<=ncom;j++) xt[j]=pcom[j]+x*xicom[j];
00755 f=shape->calcDist(xt, distMap);
00756 free_nrVector(xt,1,ncom);
00757 return f;
00758 }
00759
00760
00761 void linmin(double p[], double xi[], int n, double *fret,
00762 rutz::shared_ptr<ShapeModel>& optimizee)
00763 {
00764 int j;
00765 double xx,xmin,fx,fb,fa,bx,ax;
00766
00767 ncom=n;
00768 pcom=nrVector(1,n);
00769 xicom=nrVector(1,n);
00770 for (j=1;j<=n;j++) {
00771 pcom[j]=p[j];
00772 xicom[j]=xi[j];
00773 }
00774
00775 ax=0.0;
00776 xx=1.0;
00777
00778 mnbrak(&ax,&xx,&bx,&fa,&fx,&fb,f1dim,optimizee);
00779 *fret=brent(ax,xx,bx,f1dim,TOL,&xmin, optimizee);
00780 for (j=1;j<=n;j++) {
00781 xi[j] *= xmin;
00782 p[j] += xi[j];
00783 }
00784 free_nrVector(xicom,1,n);
00785 free_nrVector(pcom,1,n);
00786 }
00787
00788
00789 bool powell(double p[], double **xi, int n, double ftol,
00790 int *iter, double *fret, rutz::shared_ptr<ShapeModel>& optimizee)
00791 {
00792 int i,ibig,j;
00793 double del,fp,fptt,t, *pt, *ptt, *xit;
00794
00795 pt=nrVector(1,n);
00796 ptt=nrVector(1,n);
00797 xit=nrVector(1,n);
00798
00799 fptt = optimizee->getThreshold();
00800
00801 *fret=optimizee->calcDist(p, distMap);
00802 for (j=1;j<=n;j++) pt[j]=p[j];
00803 for (*iter=1;;++(*iter)) {
00804 fp=(*fret);
00805 ibig=0;
00806 del=0.0;
00807 for (i=1;i<=n;i++) {
00808 for (j = 1; j <= n; j++){
00809
00810 xit[j] = xi[j-1][i-1];
00811 }
00812 fptt=(*fret);
00813 linmin(p,xit,n,fret,optimizee);
00814 if (fabs(fptt-(*fret)) > del) {
00815 del=fabs(fptt-(*fret));
00816 ibig=i;
00817 }
00818 }
00819 if (2.0*fabs(fp-(*fret)) <= ftol*(fabs(fp)+fabs(*fret))) {
00820
00821
00822
00823 if(fptt < optimizee->getThreshold()){
00824
00825 return(true);
00826 }
00827
00828 else{return(false);}
00829 }
00830 if (*iter == ITMAX){
00831 return(false);
00832 printf("powell exceeding maximum iterations.");
00833 }
00834 for (j=1;j<=n;j++) {
00835 ptt[j]=2.0*p[j]-pt[j];
00836 xit[j]=p[j]-pt[j];
00837 pt[j]=p[j];
00838 }
00839 fptt=optimizee->calcDist(ptt, distMap);
00840 if (fptt < fp) {
00841 t=2.0*(fp-2.0*(*fret)+fptt)*squareOf(fp-(*fret)-del)-del*squareOf(fp-fptt);
00842 if (t < 0.0) {
00843 linmin(p,xit,n,fret,optimizee);
00844 for (j=0;j<n;j++) {
00845 xi[j][ibig]=xi[j][n];
00846 xi[j][n]=xit[j];
00847 }
00848 }
00849 }
00850
00851 }
00852 }
00853
00854
00855
00856
00857
00858
00859
00860
00861 int canny(unsigned char *image, int rows, int cols, float sigma,
00862 float tlow, float thigh, unsigned char **edge, const char* fname)
00863 {
00864 FILE *fpdir=NULL;
00865 unsigned char *nms;
00866 short int *smoothedim,
00867 *delta_x,
00868 *delta_y,
00869 *magnitude;
00870 float *dir_radians=NULL;
00871
00872
00873
00874
00875
00876 gaussian_smooth(image, rows, cols, sigma, &smoothedim);
00877
00878
00879
00880
00881 derrivative_x_y(smoothedim, rows, cols, &delta_x, &delta_y);
00882
00883
00884
00885
00886
00887
00888 if(fname != NULL){
00889
00890
00891
00892
00893 radian_direction(delta_x, delta_y, rows, cols, &dir_radians, -1, -1);
00894
00895
00896
00897
00898 if((fpdir = fopen(fname, "wb")) == NULL){
00899 fprintf(stderr, "Error opening the file %s for writing.\n", fname);
00900 exit(1);
00901 }
00902 fwrite(dir_radians, sizeof(float), rows*cols, fpdir);
00903 fclose(fpdir);
00904 free(dir_radians);
00905 }
00906
00907
00908
00909
00910 magnitude_x_y(delta_x, delta_y, rows, cols, &magnitude);
00911
00912
00913
00914
00915 if((nms = (unsigned char *) calloc(rows*cols,sizeof(unsigned char)))==NULL){
00916 fprintf(stderr, "Error allocating the nms image.\n");
00917 exit(1);
00918 }
00919
00920 non_max_supp(magnitude, delta_x, delta_y, rows, cols, nms);
00921
00922
00923
00924
00925 if((*edge=(unsigned char *)calloc(rows*cols,sizeof(unsigned char))) ==NULL){
00926 fprintf(stderr, "Error allocating the edge image.\n");
00927 exit(1);
00928 }
00929
00930 int centroid = apply_hysteresis(magnitude, nms, rows, cols, tlow, thigh, *edge);
00931
00932
00933
00934
00935 free(smoothedim);
00936 free(delta_x);
00937 free(delta_y);
00938 free(magnitude);
00939 free(nms);
00940 return centroid;
00941 }
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958 void radian_direction(short int *delta_x, short int *delta_y, int rows,
00959 int cols, float **dir_radians, int xdirtag, int ydirtag)
00960 {
00961 int r, c, pos;
00962 float *dirim=NULL;
00963 double dx, dy;
00964
00965
00966
00967
00968 if((dirim = (float *) calloc(rows*cols, sizeof(float))) == NULL){
00969 fprintf(stderr, "Error allocating the gradient direction image.\n");
00970 exit(1);
00971 }
00972 *dir_radians = dirim;
00973
00974 for(r=0,pos=0;r<rows;r++){
00975 for(c=0;c<cols;c++,pos++){
00976 dx = (double)delta_x[pos];
00977 dy = (double)delta_y[pos];
00978
00979 if(xdirtag == 1) dx = -dx;
00980 if(ydirtag == -1) dy = -dy;
00981
00982 dirim[pos] = (float)angle_radians(dx, dy);
00983 }
00984 }
00985 }
00986
00987
00988
00989
00990
00991
00992
00993 double angle_radians(double x, double y)
00994 {
00995 double xu, yu, ang;
00996
00997 xu = fabs(x);
00998 yu = fabs(y);
00999
01000 if((xu == 0) && (yu == 0)) return(0);
01001
01002 ang = atan(yu/xu);
01003
01004 if(x >= 0){
01005 if(y >= 0) return(ang);
01006 else return(2*M_PI - ang);
01007 }
01008 else{
01009 if(y >= 0) return(M_PI - ang);
01010 else return(M_PI + ang);
01011 }
01012 }
01013
01014
01015
01016
01017
01018
01019
01020
01021 void magnitude_x_y(short int *delta_x, short int *delta_y, int rows, int cols,
01022 short int **magnitude)
01023 {
01024 int r, c, pos, sq1, sq2;
01025
01026
01027
01028
01029 if((*magnitude = (short *) calloc(rows*cols, sizeof(short))) == NULL){
01030 fprintf(stderr, "Error allocating the magnitude image.\n");
01031 exit(1);
01032 }
01033
01034 for(r=0,pos=0;r<rows;r++){
01035 for(c=0;c<cols;c++,pos++){
01036 sq1 = (int)delta_x[pos] * (int)delta_x[pos];
01037 sq2 = (int)delta_y[pos] * (int)delta_y[pos];
01038 (*magnitude)[pos] = (short)(0.5 + sqrt((float)sq1 + (float)sq2));
01039 }
01040 }
01041
01042 }
01043
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056 void derrivative_x_y(short int *smoothedim, int rows, int cols,
01057 short int **delta_x, short int **delta_y)
01058 {
01059 int r, c, pos;
01060
01061
01062
01063
01064 if(((*delta_x) = (short *) calloc(rows*cols, sizeof(short))) == NULL){
01065 fprintf(stderr, "Error allocating the delta_x image.\n");
01066 exit(1);
01067 }
01068 if(((*delta_y) = (short *) calloc(rows*cols, sizeof(short))) == NULL){
01069 fprintf(stderr, "Error allocating the delta_x image.\n");
01070 exit(1);
01071 }
01072
01073
01074
01075
01076
01077 for(r=0;r<rows;r++){
01078 pos = r * cols;
01079 (*delta_x)[pos] = smoothedim[pos+1] - smoothedim[pos];
01080 pos++;
01081 for(c=1;c<(cols-1);c++,pos++){
01082 (*delta_x)[pos] = smoothedim[pos+1] - smoothedim[pos-1];
01083 }
01084 (*delta_x)[pos] = smoothedim[pos] - smoothedim[pos-1];
01085 }
01086
01087
01088
01089
01090
01091 for(c=0;c<cols;c++){
01092 pos = c;
01093 (*delta_y)[pos] = smoothedim[pos+cols] - smoothedim[pos];
01094 pos += cols;
01095 for(r=1;r<(rows-1);r++,pos+=cols){
01096 (*delta_y)[pos] = smoothedim[pos+cols] - smoothedim[pos-cols];
01097 }
01098 (*delta_y)[pos] = smoothedim[pos] - smoothedim[pos-cols];
01099 }
01100 }
01101
01102
01103
01104
01105
01106
01107
01108 void gaussian_smooth(unsigned char *image, int rows, int cols, float sigma,
01109 short int **smoothedim)
01110 {
01111 int r, c, rr, cc,
01112 windowsize,
01113 center;
01114 float *tempim,
01115 *kernel,
01116 dot,
01117 sum;
01118
01119
01120
01121
01122 make_gaussian_kernel(sigma, &kernel, &windowsize);
01123 center = windowsize / 2;
01124
01125
01126
01127
01128 if((tempim = (float *) calloc(rows*cols, sizeof(float))) == NULL){
01129 fprintf(stderr, "Error allocating the buffer image.\n");
01130 exit(1);
01131 }
01132 if(((*smoothedim) = (short int *) calloc(rows*cols,
01133 sizeof(short int))) == NULL){
01134 fprintf(stderr, "Error allocating the smoothed image.\n");
01135 exit(1);
01136 }
01137
01138
01139
01140
01141 for(r=0;r<rows;r++){
01142 for(c=0;c<cols;c++){
01143 dot = 0.0;
01144 sum = 0.0;
01145 for(cc=(-center);cc<=center;cc++){
01146 if(((c+cc) >= 0) && ((c+cc) < cols)){
01147 dot += (float)image[r*cols+(c+cc)] * kernel[center+cc];
01148 sum += kernel[center+cc];
01149 }
01150 }
01151 tempim[r*cols+c] = dot/sum;
01152 }
01153 }
01154
01155
01156
01157
01158 for(c=0;c<cols;c++){
01159 for(r=0;r<rows;r++){
01160 sum = 0.0;
01161 dot = 0.0;
01162 for(rr=(-center);rr<=center;rr++){
01163 if(((r+rr) >= 0) && ((r+rr) < rows)){
01164 dot += tempim[(r+rr)*cols+c] * kernel[center+rr];
01165 sum += kernel[center+rr];
01166 }
01167 }
01168 (*smoothedim)[r*cols+c] = (short int)(dot*BOOSTBLURFACTOR/sum + 0.5);
01169 }
01170 }
01171
01172 free(tempim);
01173 free(kernel);
01174 }
01175
01176
01177
01178
01179
01180
01181
01182 void make_gaussian_kernel(float sigma, float **kernel, int *windowsize)
01183 {
01184 int i, center;
01185 float x, fx, sum=0.0;
01186
01187 *windowsize = int(1 + 2 * ceil(2.5 * sigma));
01188 center = (*windowsize) / 2;
01189
01190 if((*kernel = (float *) calloc((*windowsize), sizeof(float))) == NULL){
01191 fprintf(stderr, "Error callocing the gaussian kernel array.\n");
01192 exit(1);
01193 }
01194
01195 for(i=0;i<(*windowsize);i++){
01196 x = (float)(i - center);
01197 fx = pow(2.71828, -0.5*x*x/(sigma*sigma)) / (sigma * sqrt(6.2831853));
01198 (*kernel)[i] = fx;
01199 sum += fx;
01200 }
01201
01202 for(i=0;i<(*windowsize);i++) (*kernel)[i] /= sum;
01203
01204 }