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 #include "BeoSub/BeoSubShapeDetector.H"
00039
00040 #include "Image/MathOps.H"
00041 #include "Image/MorphOps.H"
00042 #include "Image/Transforms.H"
00043 #include "Util/MathFunctions.H"
00044
00045 #include <algorithm>
00046
00047
00048 BeoSubCanny::BeoSubCanny(OptionManager& mgr,
00049 const std::string& descrName,
00050 const std::string& tagName):
00051 ModelComponent(mgr, descrName, tagName)
00052 {
00053
00054 sigma = .5;
00055 tlow = .5;
00056 thigh = .5;
00057
00058 color.resize(4, 0.0F);
00059
00060 hasSetup = false;
00061 debugmode = true;
00062 }
00063
00064
00065
00066 void BeoSubCanny::setupCanny(const char* colorArg, Image< PixRGB<byte> > image, bool debug)
00067 {
00068
00069 bool useColor = true;
00070
00071 debugmode = debug;
00072
00073 if(!hasSetup){
00074 segmenter = new segmentImageTrackMC<float,unsigned int,4> (image.getWidth()*image.getHeight());
00075 int wif = image.getWidth()/4;
00076 int hif = image.getHeight()/4;
00077 segmenter->SITsetFrame(&wif,&hif);
00078
00079
00080 segmenter->SITsetCircleColor(0,255,0);
00081 segmenter->SITsetBoxColor(255,255,0,0,255,255);
00082
00083 segmenter->SITsetUseSmoothing(true,10);
00084
00085 segmenter->SITtoggleColorAdaptation(false);
00086
00087 segmenter->SITtoggleCandidateBandPass(false);
00088 }
00089
00090
00091
00092
00093
00094
00095
00096
00097 if(!strcmp(colorArg, "Red")){
00098
00099 color[0] = 0.76700F; color[1] = 0.85300F; color[2] = 0.80000F; color[3] = 0.97200F;
00100 }
00101
00102 else if(!strcmp(colorArg, "Green")){
00103
00104 color[0] = 0.53000F; color[1] = 0.36000F; color[2] = 0.44600F; color[3] = 0.92000F;
00105 }
00106
00107 else if(!strcmp(colorArg, "Orange")){
00108
00109 color[0] = 0.80000F; color[1] = 0.80000F; color[2] = 0.55000F; color[3] = 1.00000F;
00110 }
00111 else if(!strcmp(colorArg, "Blue")){
00112
00113 color[0] = 0.27500F; color[1] = 0.52500F; color[2] = 0.44500F; color[3] = 0.97200F;
00114 }
00115 else if(!strcmp(colorArg, "Yellow")){
00116
00117 color[0] = 0.89000F; color[1] = 0.65000F; color[2] = 0.90000F; color[3] = 0.97000F;
00118 }
00119 else if(!strcmp(colorArg, "White")){
00120 color[0] = 0.70000F; color[1] = 0.70000F; color[2] = 0.04000F; color[3] = 1.00000F;
00121 }
00122 else if(!strcmp(colorArg, "Black")){
00123
00124 color[0] = 0.79F; color[1] = 0.18F; color[2] = 0.22F; color[3] = 0.175F;
00125 }
00126 else{
00127 useColor = false;
00128 }
00129
00130
00131 std::vector<float> std(4,0.0F);
00132
00133 std[0] = 0.30000; std[1] = 0.30000; std[2] = 0.34500; std[3] = 0.15000;
00134
00135 if(!strcmp(colorArg, "White") || !strcmp(colorArg, "Black")){
00136 std[0] = 1.0F; std[1] = 1.0F; std[2] = 0.1F; std[3] = 0.1F;
00137 }
00138
00139
00140 std::vector<float> norm(4,0.0F);
00141 norm[0] = 1.0F; norm[1] = 1.0F; norm[2] = 1.0F; norm[3] = 1.0F;
00142
00143
00144
00145
00146 std::vector<float> adapt(4,0.0F);
00147
00148 adapt[0] = 5.0F; adapt[1] = 5.0F; adapt[2] = 5.0F; adapt[3] = 5.0F;
00149
00150 if(!strcmp(colorArg, "White") || !strcmp(colorArg, "Black")){
00151 adapt[0] = 25.0F; adapt[1] = 25.0F; adapt[2] = 0.1F; adapt[3] = 0.1F;
00152
00153 }
00154
00155
00156 std::vector<float> upperBound(4,0.0F);
00157 upperBound[0] = color[0] + 0.45F; upperBound[1] = color[1] + 0.45F; upperBound[2] = color[2] + 0.55F; upperBound[3] = color[3] + 0.55F;
00158
00159
00160 std::vector<float> lowerBound(4,0.0F);
00161 lowerBound[0] = color[0] - 0.45F; lowerBound[1] = color[1] - 0.45F; lowerBound[2] = color[2] - 0.55F; lowerBound[3] = color[3] - 0.55F;
00162
00163
00164 colorImg = image;
00165 imgW = colorImg.getWidth();
00166 imgH = colorImg.getHeight();
00167
00168
00169 segmenter->SITsetTrackColor(&color,&std,&norm,&adapt,&upperBound,&lowerBound);
00170
00171 ww = imgW/4;
00172 hh = imgH/4;
00173
00174 Image<PixRGB<byte> > Aux;
00175 Aux.resize(100,450,true);
00176 Image<byte> temp;
00177 Image< PixRGB<byte> > display = colorImg;
00178
00179 if(debugmode){
00180 if(!win.get()){
00181 win.reset( new XWindow(colorImg.getDims(), -1, -1, "test-canny window") );
00182 win->setPosition(0, 0);
00183 }
00184 win->drawImage(colorImg);
00185 }
00186
00187
00188 if(useColor){
00189
00190
00191 H2SVimage = colorImg;
00192 display = colorImg;
00193 segmenter->SITtrackImageAny(H2SVimage,&display,&Aux,true);
00194 temp = segmenter->SITreturnCandidateImage();
00195
00196
00197
00198
00199 Image<byte> se1(5, 5, ZEROS);
00200 Point2D<int> t1(2,2);
00201 drawDisk(se1, t1, 2, static_cast<byte>(255));
00202
00203 Image<byte> se2(9, 9, ZEROS);
00204 Point2D<int> t2(4,4);
00205 drawDisk(se2, t2, 3, static_cast<byte>(255));
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222 grayImg = (Image<byte>)(quickInterpolate(temp,4));
00223 }
00224 else{
00225 grayImg = luminance(colorImg);
00226 }
00227
00228 hasSetup = true;
00229 }
00230
00231
00232 bool BeoSubCanny::runCanny(rutz::shared_ptr<ShapeModel>& shapeArg){
00233
00234
00235
00236
00237 canny(grayImg.getArrayPtr(), grayImg.getHeight(), grayImg.getWidth(), sigma, tlow, thigh, &edge, NULL);
00238
00239 Image<unsigned char> cannyCharImg(edge, grayImg.getWidth(), grayImg.getHeight());
00240
00241 Image<float> cannyImg = cannyCharImg;
00242
00243 Point2D<int> cent = centroid(cannyCharImg);
00244 distMap = chamfer34(cannyImg, 5000.0f);
00245
00246 distMap = grayImg;
00247
00248
00249 if(debugmode){
00250 if(!xwin.get()){
00251 xwin.reset(new XWindow(colorImg.getDims()));
00252 xwin->setPosition(colorImg.getWidth()+10, 0);
00253 }
00254 xwin->drawImage((Image< PixRGB<byte> >)grayImg);
00255 }
00256
00257
00258
00259
00260
00261
00262 bool shapeFound = false;
00263 double** xi = (double**)calloc(6, sizeof(double));
00264
00265
00266
00267 for(int i=0; i<6; i++) {
00268 xi[i] = (double*)calloc(6, sizeof(double));
00269 xi[i][i] = 1.0;
00270 }
00271
00272 xi[0][0] = 0.5;
00273 xi[0][1] = 0.5;
00274
00275 int iter = 0;
00276 double fret = 0.0;
00277
00278
00279 shapeFound = powell(shapeArg->getDimensions(), xi, shapeArg->getNumDims(), 0.5, &iter, &fret, shapeArg);
00280
00281 if(debugmode){
00282 double* p = shapeArg->getDimensions();
00283 if(shapeFound){
00284 printf("\n\nShape found!\n");
00285 printf("Final dimensions are -- ");
00286 for(int w = 1; w <=shapeArg->getNumDims(); w++){
00287 printf("%d: %f ", w, p[w]);
00288 }
00289 printf("Certainty (lower is better): %f\n\n", fret);
00290 }else{
00291 printf("\n\nShape not found. Certainty was %f\n\n", fret);
00292 }
00293 }
00294
00295 return(shapeFound);
00296 }
00297
00298
00299
00300
00301 BeoSubCanny::~BeoSubCanny()
00302 {
00303 }
00304
00305
00306
00307 double *BeoSubCanny::nrVector(long nl, long nh)
00308
00309 {
00310 double *v;
00311
00312 v=(double *)malloc((size_t) ((nh-nl+2)*sizeof(double)));
00313 if (!v) printf("allocation failure in nrVector()");
00314 return v-nl+1;
00315 }
00316
00317
00318 void BeoSubCanny::free_nrVector(double *v, long nl, long nh)
00319
00320 {
00321 free((FREE_ARG) (v+nl-1));
00322 }
00323
00324
00325
00326 void BeoSubCanny::mnbrak(double *ax, double *bx, double *cx, double *fa,
00327 double *fb, double *fc,
00328 rutz::shared_ptr<ShapeModel>& shape)
00329 {
00330 double ulim,u,r,q,fu,dum;
00331
00332 *fa=f1dim(*ax, shape);
00333 *fb=f1dim(*bx, shape);
00334 if (*fb > *fa) {
00335 SHFT(dum,*ax,*bx,dum)
00336 SHFT(dum,*fb,*fa,dum)
00337 }
00338 *cx=(*bx)+GOLD*(*bx-*ax);
00339 *fc=f1dim(*cx, shape);
00340 while (*fb > *fc) {
00341 r=(*bx-*ax)*(*fb-*fc);
00342 q=(*bx-*cx)*(*fb-*fa);
00343 u=(*bx)-((*bx-*cx)*q-(*bx-*ax)*r)/
00344 (2.0*SIGN(std::max(fabs(q-r),TINY),q-r));
00345 ulim=(*bx)+GLIMIT*(*cx-*bx);
00346 if ((*bx-u)*(u-*cx) > 0.0) {
00347 fu=f1dim(u, shape);
00348 if (fu < *fc) {
00349 *ax=(*bx);
00350 *bx=u;
00351 *fa=(*fb);
00352 *fb=fu;
00353 return;
00354 } else if (fu > *fb) {
00355 *cx=u;
00356 *fc=fu;
00357 return;
00358 }
00359 u=(*cx)+GOLD*(*cx-*bx);
00360 fu=f1dim(u, shape);
00361 } else if ((*cx-u)*(u-ulim) > 0.0) {
00362 fu=f1dim(u, shape);
00363 if (fu < *fc) {
00364 SHFT(*bx,*cx,u,*cx+GOLD*(*cx-*bx))
00365 SHFT(*fb,*fc,fu,f1dim(u, shape))
00366 }
00367 } else if ((u-ulim)*(ulim-*cx) >= 0.0) {
00368 u=ulim;
00369 fu=f1dim(u, shape);
00370 } else {
00371 u=(*cx)+GOLD*(*cx-*bx);
00372 fu=f1dim(u, shape);
00373 }
00374 SHFT(*ax,*bx,*cx,u)
00375 SHFT(*fa,*fb,*fc,fu)
00376 }
00377 }
00378
00379 double BeoSubCanny::brent(double ax, double bx, double cx,
00380 double tol, double *xmin,
00381 rutz::shared_ptr<ShapeModel>& shape)
00382 {
00383 int iter;
00384 double a,b,d=0.0,etemp,fu,fv,fw,fx,p,q,r,tol1,tol2,u,v,w,x,xm;
00385 double e=0.0;
00386
00387 a=(ax < cx ? ax : cx);
00388 b=(ax > cx ? ax : cx);
00389 x=w=v=bx;
00390 fw=fv=fx=f1dim(x, shape);
00391 for (iter=1;iter<=ITMAXB;iter++) {
00392 xm=0.5*(a+b);
00393 tol2=2.0*(tol1=tol*fabs(x)+ZEPS);
00394 if (fabs(x-xm) <= (tol2-0.5*(b-a))) {
00395 *xmin=x;
00396 return fx;
00397 }
00398 if (fabs(e) > tol1) {
00399 r=(x-w)*(fx-fv);
00400 q=(x-v)*(fx-fw);
00401 p=(x-v)*q-(x-w)*r;
00402 q=2.0*(q-r);
00403 if (q > 0.0) p = -p;
00404 q=fabs(q);
00405 etemp=e;
00406 e=d;
00407 if (fabs(p) >= fabs(0.5*q*etemp) || p <= q*(a-x) || p >= q*(b-x))
00408 d=CGOLD*(e=(x >= xm ? a-x : b-x));
00409 else {
00410 d=p/q;
00411 u=x+d;
00412 if (u-a < tol2 || b-u < tol2)
00413 d=SIGN(tol1,xm-x);
00414 }
00415 } else {
00416 d=CGOLD*(e=(x >= xm ? a-x : b-x));
00417 }
00418 u=(fabs(d) >= tol1 ? x+d : x+SIGN(tol1,d));
00419 fu=f1dim(u, shape);
00420 if (fu <= fx) {
00421 if (u >= x) a=x; else b=x;
00422 SHFT(v,w,x,u)
00423 SHFT(fv,fw,fx,fu)
00424 } else {
00425 if (u < x) a=u; else b=u;
00426 if (fu <= fw || w == x) {
00427 v=w;
00428 w=u;
00429 fv=fw;
00430 fw=fu;
00431 } else if (fu <= fv || v == x || v == w) {
00432 v=u;
00433 fv=fu;
00434 }
00435 }
00436 }
00437 printf("Too many iterations in brent");
00438 *xmin=x;
00439 return fx;
00440 }
00441
00442 double BeoSubCanny::f1dim(double x, rutz::shared_ptr<ShapeModel>& shape)
00443 {
00444 int j;
00445 double f, *xt;
00446 xt=nrVector(1,ncom);
00447
00448 for (j=1;j<=ncom;j++) xt[j]=pcom[j]+x*xicom[j];
00449 f=shape->calcDist(xt, distMap);
00450 free_nrVector(xt,1,ncom);
00451 return f;
00452 }
00453
00454 void BeoSubCanny::linmin(double p[], double xi[], int n, double *fret,
00455 rutz::shared_ptr<ShapeModel>& optimizee)
00456 {
00457
00458 int j;
00459 double xx,xmin,fx,fb,fa,bx,ax;
00460
00461 ncom=n;
00462 pcom=nrVector(1,n);
00463 xicom=nrVector(1,n);
00464 for (j=1;j<=n;j++) {
00465 pcom[j]=p[j];
00466 xicom[j]=xi[j];
00467 }
00468
00469 ax=0.0;
00470 xx=1.0;
00471
00472 mnbrak(&ax,&xx,&bx,&fa,&fx,&fb,optimizee);
00473 *fret=brent(ax,xx,bx,TOL,&xmin, optimizee);
00474
00475 for (j=1;j<=n;j++) {
00476 xi[j] *= xmin;
00477 p[j] += xi[j];
00478 }
00479 free_nrVector(xicom,1,n);
00480 free_nrVector(pcom,1,n);
00481 }
00482
00483 bool BeoSubCanny::powell(double p[], double **xi, int n, double ftol,
00484 int *iter, double *fret, rutz::shared_ptr<ShapeModel>& optimizee)
00485 {
00486 int i,ibig,j;
00487 double del,fp,fptt,t, *pt, *ptt, *xit;
00488
00489 pt=nrVector(1,n);
00490 ptt=nrVector(1,n);
00491 xit=nrVector(1,n);
00492
00493 fptt = optimizee->getThreshold();
00494
00495 *fret=optimizee->calcDist(p, distMap);
00496 for (j=1;j<=n;j++) pt[j]=p[j];
00497 for (*iter=1;;++(*iter)) {
00498 fp=(*fret);
00499 ibig=0;
00500 del=0.0;
00501 for (i=1;i<=n;i++) {
00502 for (j = 1; j <= n; j++){
00503
00504 xit[j] = xi[j-1][i-1];
00505 }
00506 fptt=(*fret);
00507 linmin(p,xit,n,fret,optimizee);
00508 if (fabs(fptt-(*fret)) > del) {
00509 del=fabs(fptt-(*fret));
00510 ibig=i;
00511 }
00512 }
00513 if (2.0*fabs(fp-(*fret)) <= ftol*(fabs(fp)+fabs(*fret))) {
00514
00515
00516
00517
00518
00519 if(fptt < optimizee->getThreshold()){
00520 return(true);
00521 }
00522
00523 else{return(false);}
00524 }
00525 if (*iter == ITMAX){
00526
00527 printf("powell exceeding maximum iterations.");
00528 return(false);
00529 }
00530 for (j=1;j<=n;j++) {
00531 ptt[j]=2.0*p[j]-pt[j];
00532 xit[j]=p[j]-pt[j];
00533 pt[j]=p[j];
00534 }
00535
00536
00537 fptt=optimizee->calcDist(ptt, distMap);
00538 if (fptt < fp) {
00539 t=2.0*(fp-2.0*(*fret)+fptt)*squareOf(fp-(*fret)-del)-del*squareOf(fp-fptt);
00540 if (t < 0.0) {
00541 linmin(p,xit,n,fret,optimizee);
00542 for (j=0;j<n;j++) {
00543 xi[j][ibig]=xi[j][n];
00544 xi[j][n]=xit[j];
00545 }
00546 }
00547 }
00548
00549 }
00550 }
00551
00552
00553
00554
00555
00556
00557
00558
00559 int BeoSubCanny::canny(unsigned char *image, int rows, int cols, float sigma,
00560 float tlow, float thigh, unsigned char **edge, char *fname)
00561 {
00562 FILE *fpdir=NULL;
00563 unsigned char *nms;
00564 short int *smoothedim,
00565 *delta_x,
00566 *delta_y,
00567 *magnitude;
00568 float *dir_radians=NULL;
00569
00570
00571
00572
00573
00574 gaussian_smooth(image, rows, cols, sigma, &smoothedim);
00575
00576
00577
00578
00579 derrivative_x_y(smoothedim, rows, cols, &delta_x, &delta_y);
00580
00581
00582
00583
00584
00585
00586 if(fname != NULL){
00587
00588
00589
00590
00591 radian_direction(delta_x, delta_y, rows, cols, &dir_radians, -1, -1);
00592
00593
00594
00595
00596 if((fpdir = fopen(fname, "wb")) == NULL){
00597 fprintf(stderr, "Error opening the file %s for writing.\n", fname);
00598 exit(1);
00599 }
00600 fwrite(dir_radians, sizeof(float), rows*cols, fpdir);
00601 fclose(fpdir);
00602 free(dir_radians);
00603 }
00604
00605
00606
00607
00608 magnitude_x_y(delta_x, delta_y, rows, cols, &magnitude);
00609
00610
00611
00612
00613 if((nms = (unsigned char *) calloc(rows*cols,sizeof(unsigned char)))==NULL){
00614 fprintf(stderr, "Error allocating the nms image.\n");
00615 exit(1);
00616 }
00617
00618 non_max_supp(magnitude, delta_x, delta_y, rows, cols, nms);
00619
00620
00621
00622
00623 if((*edge=(unsigned char *)calloc(rows*cols,sizeof(unsigned char))) ==NULL){
00624 fprintf(stderr, "Error allocating the edge image.\n");
00625 exit(1);
00626 }
00627
00628 int centroid = apply_hysteresis(magnitude, nms, rows, cols, tlow, thigh, *edge);
00629
00630
00631
00632
00633 free(smoothedim);
00634 free(delta_x);
00635 free(delta_y);
00636 free(magnitude);
00637 free(nms);
00638 return centroid;
00639 }
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656 void BeoSubCanny::radian_direction(short int *delta_x, short int *delta_y, int rows,
00657 int cols, float **dir_radians, int xdirtag, int ydirtag)
00658 {
00659 int r, c, pos;
00660 float *dirim=NULL;
00661 double dx, dy;
00662
00663
00664
00665
00666 if((dirim = (float *) calloc(rows*cols, sizeof(float))) == NULL){
00667 fprintf(stderr, "Error allocating the gradient direction image.\n");
00668 exit(1);
00669 }
00670 *dir_radians = dirim;
00671
00672 for(r=0,pos=0;r<rows;r++){
00673 for(c=0;c<cols;c++,pos++){
00674 dx = (double)delta_x[pos];
00675 dy = (double)delta_y[pos];
00676
00677 if(xdirtag == 1) dx = -dx;
00678 if(ydirtag == -1) dy = -dy;
00679
00680 dirim[pos] = (float)angle_radians(dx, dy);
00681 }
00682 }
00683 }
00684
00685
00686
00687
00688
00689
00690
00691 double BeoSubCanny::angle_radians(double x, double y)
00692 {
00693 double xu, yu, ang;
00694
00695 xu = fabs(x);
00696 yu = fabs(y);
00697
00698 if((xu == 0) && (yu == 0)) return(0);
00699
00700 ang = atan(yu/xu);
00701
00702 if(x >= 0){
00703 if(y >= 0) return(ang);
00704 else return(2*M_PI - ang);
00705 }
00706 else{
00707 if(y >= 0) return(M_PI - ang);
00708 else return(M_PI + ang);
00709 }
00710 }
00711
00712
00713
00714
00715
00716
00717
00718
00719 void BeoSubCanny::magnitude_x_y(short int *delta_x, short int *delta_y, int rows, int cols,
00720 short int **magnitude)
00721 {
00722 int r, c, pos, sq1, sq2;
00723
00724
00725
00726
00727 if((*magnitude = (short *) calloc(rows*cols, sizeof(short))) == NULL){
00728 fprintf(stderr, "Error allocating the magnitude image.\n");
00729 exit(1);
00730 }
00731
00732 for(r=0,pos=0;r<rows;r++){
00733 for(c=0;c<cols;c++,pos++){
00734 sq1 = (int)delta_x[pos] * (int)delta_x[pos];
00735 sq2 = (int)delta_y[pos] * (int)delta_y[pos];
00736 (*magnitude)[pos] = (short)(0.5 + sqrt((float)sq1 + (float)sq2));
00737 }
00738 }
00739
00740 }
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754 void BeoSubCanny::derrivative_x_y(short int *smoothedim, int rows, int cols,
00755 short int **delta_x, short int **delta_y)
00756 {
00757 int r, c, pos;
00758
00759
00760
00761
00762 if(((*delta_x) = (short *) calloc(rows*cols, sizeof(short))) == NULL){
00763 fprintf(stderr, "Error allocating the delta_x image.\n");
00764 exit(1);
00765 }
00766 if(((*delta_y) = (short *) calloc(rows*cols, sizeof(short))) == NULL){
00767 fprintf(stderr, "Error allocating the delta_x image.\n");
00768 exit(1);
00769 }
00770
00771
00772
00773
00774
00775 for(r=0;r<rows;r++){
00776 pos = r * cols;
00777 (*delta_x)[pos] = smoothedim[pos+1] - smoothedim[pos];
00778 pos++;
00779 for(c=1;c<(cols-1);c++,pos++){
00780 (*delta_x)[pos] = smoothedim[pos+1] - smoothedim[pos-1];
00781 }
00782 (*delta_x)[pos] = smoothedim[pos] - smoothedim[pos-1];
00783 }
00784
00785
00786
00787
00788
00789 for(c=0;c<cols;c++){
00790 pos = c;
00791 (*delta_y)[pos] = smoothedim[pos+cols] - smoothedim[pos];
00792 pos += cols;
00793 for(r=1;r<(rows-1);r++,pos+=cols){
00794 (*delta_y)[pos] = smoothedim[pos+cols] - smoothedim[pos-cols];
00795 }
00796 (*delta_y)[pos] = smoothedim[pos] - smoothedim[pos-cols];
00797 }
00798 }
00799
00800
00801
00802
00803
00804
00805
00806 void BeoSubCanny::gaussian_smooth(unsigned char *image, int rows, int cols, float sigma,
00807 short int **smoothedim)
00808 {
00809 int r, c, rr, cc,
00810 windowsize,
00811 center;
00812 float *tempim,
00813 *kernel,
00814 dot,
00815 sum;
00816
00817
00818
00819
00820 make_gaussian_kernel(sigma, &kernel, &windowsize);
00821 center = windowsize / 2;
00822
00823
00824
00825
00826 if((tempim = (float *) calloc(rows*cols, sizeof(float))) == NULL){
00827 fprintf(stderr, "Error allocating the buffer image.\n");
00828 exit(1);
00829 }
00830 if(((*smoothedim) = (short int *) calloc(rows*cols,
00831 sizeof(short int))) == NULL){
00832 fprintf(stderr, "Error allocating the smoothed image.\n");
00833 exit(1);
00834 }
00835
00836
00837
00838
00839 for(r=0;r<rows;r++){
00840 for(c=0;c<cols;c++){
00841 dot = 0.0;
00842 sum = 0.0;
00843 for(cc=(-center);cc<=center;cc++){
00844 if(((c+cc) >= 0) && ((c+cc) < cols)){
00845 dot += (float)image[r*cols+(c+cc)] * kernel[center+cc];
00846 sum += kernel[center+cc];
00847 }
00848 }
00849 tempim[r*cols+c] = dot/sum;
00850 }
00851 }
00852
00853
00854
00855
00856 for(c=0;c<cols;c++){
00857 for(r=0;r<rows;r++){
00858 sum = 0.0;
00859 dot = 0.0;
00860 for(rr=(-center);rr<=center;rr++){
00861 if(((r+rr) >= 0) && ((r+rr) < rows)){
00862 dot += tempim[(r+rr)*cols+c] * kernel[center+rr];
00863 sum += kernel[center+rr];
00864 }
00865 }
00866 (*smoothedim)[r*cols+c] = (short int)(dot*BOOSTBLURFACTOR/sum + 0.5);
00867 }
00868 }
00869
00870 free(tempim);
00871 free(kernel);
00872 }
00873
00874
00875
00876
00877
00878
00879
00880 void BeoSubCanny::make_gaussian_kernel(float sigma, float **kernel, int *windowsize)
00881 {
00882 int i, center;
00883 float x, fx, sum=0.0;
00884
00885 *windowsize = int(1 + 2 * ceil(2.5 * sigma));
00886 center = (*windowsize) / 2;
00887
00888 if((*kernel = (float *) calloc((*windowsize), sizeof(float))) == NULL){
00889 fprintf(stderr, "Error callocing the gaussian kernel array.\n");
00890 exit(1);
00891 }
00892
00893 for(i=0;i<(*windowsize);i++){
00894 x = (float)(i - center);
00895 fx = pow(2.71828, -0.5*x*x/(sigma*sigma)) / (sigma * sqrt(6.2831853));
00896 (*kernel)[i] = fx;
00897 sum += fx;
00898 }
00899
00900 for(i=0;i<(*windowsize);i++) (*kernel)[i] /= sum;
00901
00902 }