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/BeoSubCanny.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 color[0] = 0.60001F; color[1] = 0.66000F; color[2] = 0.24000F; color[3] = 0.70000F;
00124 }
00125 else{
00126 useColor = false;
00127 }
00128
00129
00130 std::vector<float> std(4,0.0F);
00131
00132 std[0] = 0.30000; std[1] = 0.30000; std[2] = 0.34500; std[3] = 0.15000;
00133
00134 if(!strcmp(colorArg, "White") || !strcmp(colorArg, "Black")){
00135 std[0] = 1.0F; std[1] = 1.0F; std[2] = 0.1F; std[3] = 0.1F;
00136
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 canny(grayImg.getArrayPtr(), grayImg.getHeight(), grayImg.getWidth(), sigma, tlow, thigh, &edge, NULL);
00237
00238 Image<unsigned char> cannyCharImg(edge, grayImg.getWidth(), grayImg.getHeight());
00239
00240 Image<float> cannyImg = cannyCharImg;
00241
00242
00243
00244 if(debugmode){
00245 if(!xwin.get()){
00246 xwin.reset(new XWindow(colorImg.getDims()));
00247 xwin->setPosition(colorImg.getWidth()+10, 0);
00248 }
00249 xwin->drawImage((Image< PixRGB<byte> >)grayImg);
00250 }
00251
00252 centroid(cannyCharImg);
00253 distMap = chamfer34(cannyImg, 5000.0f);
00254
00255
00256
00257
00258 bool shapeFound = false;
00259 double** xi = (double**)calloc(6, sizeof(double));
00260
00261
00262
00263 for(int i=0; i<6; i++) {
00264 xi[i] = (double*)calloc(6, sizeof(double));
00265 xi[i][i] = 1.0;
00266 }
00267
00268 xi[0][0] = 0.5;
00269 xi[0][1] = 0.5;
00270
00271 int iter = 0;
00272 double fret = 0.0;
00273
00274
00275 shapeFound = powell(shapeArg->getDimensions(), xi, shapeArg->getNumDims(), 0.5, &iter, &fret, shapeArg);
00276
00277 if(debugmode){
00278 double* p = shapeArg->getDimensions();
00279 if(shapeFound){
00280 printf("\n\nShape found!\n");
00281 printf("Final dimensions are -- ");
00282 for(int w = 1; w <=shapeArg->getNumDims(); w++){
00283 printf("%d: %f ", w, p[w]);
00284 }
00285 printf("Certainty (lower is better): %f\n\n", fret);
00286 }else{
00287 printf("\n\nShape not found. Certainty was %f\n\n", fret);
00288 }
00289 }
00290
00291 return(shapeFound);
00292 }
00293
00294
00295
00296
00297 BeoSubCanny::~BeoSubCanny()
00298 {
00299 }
00300
00301
00302
00303 double *BeoSubCanny::nrVector(long nl, long nh)
00304
00305 {
00306 double *v;
00307
00308 v=(double *)malloc((size_t) ((nh-nl+2)*sizeof(double)));
00309 if (!v) printf("allocation failure in nrVector()");
00310 return v-nl+1;
00311 }
00312
00313
00314 void BeoSubCanny::free_nrVector(double *v, long nl, long nh)
00315
00316 {
00317 free((FREE_ARG) (v+nl-1));
00318 }
00319
00320
00321
00322 void BeoSubCanny::mnbrak(double *ax, double *bx, double *cx, double *fa,
00323 double *fb, double *fc,
00324 rutz::shared_ptr<ShapeModel>& shape)
00325 {
00326 double ulim,u,r,q,fu,dum;
00327
00328 *fa=f1dim(*ax, shape);
00329 *fb=f1dim(*bx, shape);
00330 if (*fb > *fa) {
00331 SHFT(dum,*ax,*bx,dum)
00332 SHFT(dum,*fb,*fa,dum)
00333 }
00334 *cx=(*bx)+GOLD*(*bx-*ax);
00335 *fc=f1dim(*cx, shape);
00336 while (*fb > *fc) {
00337 r=(*bx-*ax)*(*fb-*fc);
00338 q=(*bx-*cx)*(*fb-*fa);
00339 u=(*bx)-((*bx-*cx)*q-(*bx-*ax)*r)/
00340 (2.0*SIGN(std::max(fabs(q-r),TINY),q-r));
00341 ulim=(*bx)+GLIMIT*(*cx-*bx);
00342 if ((*bx-u)*(u-*cx) > 0.0) {
00343 fu=f1dim(u, shape);
00344 if (fu < *fc) {
00345 *ax=(*bx);
00346 *bx=u;
00347 *fa=(*fb);
00348 *fb=fu;
00349 return;
00350 } else if (fu > *fb) {
00351 *cx=u;
00352 *fc=fu;
00353 return;
00354 }
00355 u=(*cx)+GOLD*(*cx-*bx);
00356 fu=f1dim(u, shape);
00357 } else if ((*cx-u)*(u-ulim) > 0.0) {
00358 fu=f1dim(u, shape);
00359 if (fu < *fc) {
00360 SHFT(*bx,*cx,u,*cx+GOLD*(*cx-*bx))
00361 SHFT(*fb,*fc,fu,f1dim(u, shape))
00362 }
00363 } else if ((u-ulim)*(ulim-*cx) >= 0.0) {
00364 u=ulim;
00365 fu=f1dim(u, shape);
00366 } else {
00367 u=(*cx)+GOLD*(*cx-*bx);
00368 fu=f1dim(u, shape);
00369 }
00370 SHFT(*ax,*bx,*cx,u)
00371 SHFT(*fa,*fb,*fc,fu)
00372 }
00373 }
00374
00375 double BeoSubCanny::brent(double ax, double bx, double cx,
00376 double tol, double *xmin,
00377 rutz::shared_ptr<ShapeModel>& shape)
00378 {
00379 int iter;
00380 double a,b,d=0.0,etemp,fu,fv,fw,fx,p,q,r,tol1,tol2,u,v,w,x,xm;
00381 double e=0.0;
00382
00383 a=(ax < cx ? ax : cx);
00384 b=(ax > cx ? ax : cx);
00385 x=w=v=bx;
00386 fw=fv=fx=f1dim(x, shape);
00387 for (iter=1;iter<=ITMAXB;iter++) {
00388 xm=0.5*(a+b);
00389 tol2=2.0*(tol1=tol*fabs(x)+ZEPS);
00390 if (fabs(x-xm) <= (tol2-0.5*(b-a))) {
00391 *xmin=x;
00392 return fx;
00393 }
00394 if (fabs(e) > tol1) {
00395 r=(x-w)*(fx-fv);
00396 q=(x-v)*(fx-fw);
00397 p=(x-v)*q-(x-w)*r;
00398 q=2.0*(q-r);
00399 if (q > 0.0) p = -p;
00400 q=fabs(q);
00401 etemp=e;
00402 e=d;
00403 if (fabs(p) >= fabs(0.5*q*etemp) || p <= q*(a-x) || p >= q*(b-x))
00404 d=CGOLD*(e=(x >= xm ? a-x : b-x));
00405 else {
00406 d=p/q;
00407 u=x+d;
00408 if (u-a < tol2 || b-u < tol2)
00409 d=SIGN(tol1,xm-x);
00410 }
00411 } else {
00412 d=CGOLD*(e=(x >= xm ? a-x : b-x));
00413 }
00414 u=(fabs(d) >= tol1 ? x+d : x+SIGN(tol1,d));
00415 fu=f1dim(u, shape);
00416 if (fu <= fx) {
00417 if (u >= x) a=x; else b=x;
00418 SHFT(v,w,x,u)
00419 SHFT(fv,fw,fx,fu)
00420 } else {
00421 if (u < x) a=u; else b=u;
00422 if (fu <= fw || w == x) {
00423 v=w;
00424 w=u;
00425 fv=fw;
00426 fw=fu;
00427 } else if (fu <= fv || v == x || v == w) {
00428 v=u;
00429 fv=fu;
00430 }
00431 }
00432 }
00433 printf("Too many iterations in brent");
00434 *xmin=x;
00435 return fx;
00436 }
00437
00438 double BeoSubCanny::f1dim(double x, rutz::shared_ptr<ShapeModel>& shape)
00439 {
00440 int j;
00441 double f, *xt;
00442 xt=nrVector(1,ncom);
00443
00444 for (j=1;j<=ncom;j++) xt[j]=pcom[j]+x*xicom[j];
00445 f=shape->calcDist(xt, distMap);
00446 free_nrVector(xt,1,ncom);
00447 return f;
00448 }
00449
00450 void BeoSubCanny::linmin(double p[], double xi[], int n, double *fret,
00451 rutz::shared_ptr<ShapeModel>& optimizee)
00452 {
00453
00454 int j;
00455 double xx,xmin,fx,fb,fa,bx,ax;
00456
00457 ncom=n;
00458 pcom=nrVector(1,n);
00459 xicom=nrVector(1,n);
00460 for (j=1;j<=n;j++) {
00461 pcom[j]=p[j];
00462 xicom[j]=xi[j];
00463 }
00464
00465 ax=0.0;
00466 xx=1.0;
00467
00468 mnbrak(&ax,&xx,&bx,&fa,&fx,&fb,optimizee);
00469 *fret=brent(ax,xx,bx,TOL,&xmin, optimizee);
00470
00471 for (j=1;j<=n;j++) {
00472 xi[j] *= xmin;
00473 p[j] += xi[j];
00474 }
00475 free_nrVector(xicom,1,n);
00476 free_nrVector(pcom,1,n);
00477 }
00478
00479 bool BeoSubCanny::powell(double p[], double **xi, int n, double ftol,
00480 int *iter, double *fret, rutz::shared_ptr<ShapeModel>& optimizee)
00481 {
00482 int i,ibig,j;
00483 double del,fp,fptt,t, *pt, *ptt, *xit;
00484
00485 pt=nrVector(1,n);
00486 ptt=nrVector(1,n);
00487 xit=nrVector(1,n);
00488
00489 fptt = optimizee->getThreshold();
00490
00491 *fret=optimizee->calcDist(p, distMap);
00492 for (j=1;j<=n;j++) pt[j]=p[j];
00493 for (*iter=1;;++(*iter)) {
00494 fp=(*fret);
00495 ibig=0;
00496 del=0.0;
00497 for (i=1;i<=n;i++) {
00498 for (j = 1; j <= n; j++){
00499
00500 xit[j] = xi[j-1][i-1];
00501 }
00502 fptt=(*fret);
00503 linmin(p,xit,n,fret,optimizee);
00504 if (fabs(fptt-(*fret)) > del) {
00505 del=fabs(fptt-(*fret));
00506 ibig=i;
00507 }
00508 }
00509 if (2.0*fabs(fp-(*fret)) <= ftol*(fabs(fp)+fabs(*fret))) {
00510
00511
00512
00513
00514
00515 if(fptt < optimizee->getThreshold()){
00516 return(true);
00517 }
00518
00519 else{return(false);}
00520 }
00521 if (*iter == ITMAX){
00522
00523 printf("powell exceeding maximum iterations.");
00524 return(false);
00525 }
00526 for (j=1;j<=n;j++) {
00527 ptt[j]=2.0*p[j]-pt[j];
00528 xit[j]=p[j]-pt[j];
00529 pt[j]=p[j];
00530 }
00531
00532
00533 fptt=optimizee->calcDist(ptt, distMap);
00534 if (fptt < fp) {
00535 t=2.0*(fp-2.0*(*fret)+fptt)*squareOf(fp-(*fret)-del)-del*squareOf(fp-fptt);
00536 if (t < 0.0) {
00537 linmin(p,xit,n,fret,optimizee);
00538 for (j=0;j<n;j++) {
00539 xi[j][ibig]=xi[j][n];
00540 xi[j][n]=xit[j];
00541 }
00542 }
00543 }
00544
00545 }
00546 }
00547
00548
00549
00550
00551
00552
00553
00554
00555 int BeoSubCanny::canny(unsigned char *image, int rows, int cols, float sigma,
00556 float tlow, float thigh, unsigned char **edge, char *fname)
00557 {
00558 FILE *fpdir=NULL;
00559 unsigned char *nms;
00560 short int *smoothedim,
00561 *delta_x,
00562 *delta_y,
00563 *magnitude;
00564 float *dir_radians=NULL;
00565
00566
00567
00568
00569
00570 gaussian_smooth(image, rows, cols, sigma, &smoothedim);
00571
00572
00573
00574
00575 derrivative_x_y(smoothedim, rows, cols, &delta_x, &delta_y);
00576
00577
00578
00579
00580
00581
00582 if(fname != NULL){
00583
00584
00585
00586
00587 radian_direction(delta_x, delta_y, rows, cols, &dir_radians, -1, -1);
00588
00589
00590
00591
00592 if((fpdir = fopen(fname, "wb")) == NULL){
00593 fprintf(stderr, "Error opening the file %s for writing.\n", fname);
00594 exit(1);
00595 }
00596 fwrite(dir_radians, sizeof(float), rows*cols, fpdir);
00597 fclose(fpdir);
00598 free(dir_radians);
00599 }
00600
00601
00602
00603
00604 magnitude_x_y(delta_x, delta_y, rows, cols, &magnitude);
00605
00606
00607
00608
00609 if((nms = (unsigned char *) calloc(rows*cols,sizeof(unsigned char)))==NULL){
00610 fprintf(stderr, "Error allocating the nms image.\n");
00611 exit(1);
00612 }
00613
00614 non_max_supp(magnitude, delta_x, delta_y, rows, cols, nms);
00615
00616
00617
00618
00619 if((*edge=(unsigned char *)calloc(rows*cols,sizeof(unsigned char))) ==NULL){
00620 fprintf(stderr, "Error allocating the edge image.\n");
00621 exit(1);
00622 }
00623
00624 int centroid = apply_hysteresis(magnitude, nms, rows, cols, tlow, thigh, *edge);
00625
00626
00627
00628
00629 free(smoothedim);
00630 free(delta_x);
00631 free(delta_y);
00632 free(magnitude);
00633 free(nms);
00634 return centroid;
00635 }
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652 void BeoSubCanny::radian_direction(short int *delta_x, short int *delta_y, int rows,
00653 int cols, float **dir_radians, int xdirtag, int ydirtag)
00654 {
00655 int r, c, pos;
00656 float *dirim=NULL;
00657 double dx, dy;
00658
00659
00660
00661
00662 if((dirim = (float *) calloc(rows*cols, sizeof(float))) == NULL){
00663 fprintf(stderr, "Error allocating the gradient direction image.\n");
00664 exit(1);
00665 }
00666 *dir_radians = dirim;
00667
00668 for(r=0,pos=0;r<rows;r++){
00669 for(c=0;c<cols;c++,pos++){
00670 dx = (double)delta_x[pos];
00671 dy = (double)delta_y[pos];
00672
00673 if(xdirtag == 1) dx = -dx;
00674 if(ydirtag == -1) dy = -dy;
00675
00676 dirim[pos] = (float)angle_radians(dx, dy);
00677 }
00678 }
00679 }
00680
00681
00682
00683
00684
00685
00686
00687 double BeoSubCanny::angle_radians(double x, double y)
00688 {
00689 double xu, yu, ang;
00690
00691 xu = fabs(x);
00692 yu = fabs(y);
00693
00694 if((xu == 0) && (yu == 0)) return(0);
00695
00696 ang = atan(yu/xu);
00697
00698 if(x >= 0){
00699 if(y >= 0) return(ang);
00700 else return(2*M_PI - ang);
00701 }
00702 else{
00703 if(y >= 0) return(M_PI - ang);
00704 else return(M_PI + ang);
00705 }
00706 }
00707
00708
00709
00710
00711
00712
00713
00714
00715 void BeoSubCanny::magnitude_x_y(short int *delta_x, short int *delta_y, int rows, int cols,
00716 short int **magnitude)
00717 {
00718 int r, c, pos, sq1, sq2;
00719
00720
00721
00722
00723 if((*magnitude = (short *) calloc(rows*cols, sizeof(short))) == NULL){
00724 fprintf(stderr, "Error allocating the magnitude image.\n");
00725 exit(1);
00726 }
00727
00728 for(r=0,pos=0;r<rows;r++){
00729 for(c=0;c<cols;c++,pos++){
00730 sq1 = (int)delta_x[pos] * (int)delta_x[pos];
00731 sq2 = (int)delta_y[pos] * (int)delta_y[pos];
00732 (*magnitude)[pos] = (short)(0.5 + sqrt((float)sq1 + (float)sq2));
00733 }
00734 }
00735
00736 }
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750 void BeoSubCanny::derrivative_x_y(short int *smoothedim, int rows, int cols,
00751 short int **delta_x, short int **delta_y)
00752 {
00753 int r, c, pos;
00754
00755
00756
00757
00758 if(((*delta_x) = (short *) calloc(rows*cols, sizeof(short))) == NULL){
00759 fprintf(stderr, "Error allocating the delta_x image.\n");
00760 exit(1);
00761 }
00762 if(((*delta_y) = (short *) calloc(rows*cols, sizeof(short))) == NULL){
00763 fprintf(stderr, "Error allocating the delta_x image.\n");
00764 exit(1);
00765 }
00766
00767
00768
00769
00770
00771 for(r=0;r<rows;r++){
00772 pos = r * cols;
00773 (*delta_x)[pos] = smoothedim[pos+1] - smoothedim[pos];
00774 pos++;
00775 for(c=1;c<(cols-1);c++,pos++){
00776 (*delta_x)[pos] = smoothedim[pos+1] - smoothedim[pos-1];
00777 }
00778 (*delta_x)[pos] = smoothedim[pos] - smoothedim[pos-1];
00779 }
00780
00781
00782
00783
00784
00785 for(c=0;c<cols;c++){
00786 pos = c;
00787 (*delta_y)[pos] = smoothedim[pos+cols] - smoothedim[pos];
00788 pos += cols;
00789 for(r=1;r<(rows-1);r++,pos+=cols){
00790 (*delta_y)[pos] = smoothedim[pos+cols] - smoothedim[pos-cols];
00791 }
00792 (*delta_y)[pos] = smoothedim[pos] - smoothedim[pos-cols];
00793 }
00794 }
00795
00796
00797
00798
00799
00800
00801
00802 void BeoSubCanny::gaussian_smooth(unsigned char *image, int rows, int cols, float sigma,
00803 short int **smoothedim)
00804 {
00805 int r, c, rr, cc,
00806 windowsize,
00807 center;
00808 float *tempim,
00809 *kernel,
00810 dot,
00811 sum;
00812
00813
00814
00815
00816 make_gaussian_kernel(sigma, &kernel, &windowsize);
00817 center = windowsize / 2;
00818
00819
00820
00821
00822 if((tempim = (float *) calloc(rows*cols, sizeof(float))) == NULL){
00823 fprintf(stderr, "Error allocating the buffer image.\n");
00824 exit(1);
00825 }
00826 if(((*smoothedim) = (short int *) calloc(rows*cols,
00827 sizeof(short int))) == NULL){
00828 fprintf(stderr, "Error allocating the smoothed image.\n");
00829 exit(1);
00830 }
00831
00832
00833
00834
00835 for(r=0;r<rows;r++){
00836 for(c=0;c<cols;c++){
00837 dot = 0.0;
00838 sum = 0.0;
00839 for(cc=(-center);cc<=center;cc++){
00840 if(((c+cc) >= 0) && ((c+cc) < cols)){
00841 dot += (float)image[r*cols+(c+cc)] * kernel[center+cc];
00842 sum += kernel[center+cc];
00843 }
00844 }
00845 tempim[r*cols+c] = dot/sum;
00846 }
00847 }
00848
00849
00850
00851
00852 for(c=0;c<cols;c++){
00853 for(r=0;r<rows;r++){
00854 sum = 0.0;
00855 dot = 0.0;
00856 for(rr=(-center);rr<=center;rr++){
00857 if(((r+rr) >= 0) && ((r+rr) < rows)){
00858 dot += tempim[(r+rr)*cols+c] * kernel[center+rr];
00859 sum += kernel[center+rr];
00860 }
00861 }
00862 (*smoothedim)[r*cols+c] = (short int)(dot*BOOSTBLURFACTOR/sum + 0.5);
00863 }
00864 }
00865
00866 free(tempim);
00867 free(kernel);
00868 }
00869
00870
00871
00872
00873
00874
00875
00876 void BeoSubCanny::make_gaussian_kernel(float sigma, float **kernel, int *windowsize)
00877 {
00878 int i, center;
00879 float x, fx, sum=0.0;
00880
00881 *windowsize = int(1 + 2 * ceil(2.5 * sigma));
00882 center = (*windowsize) / 2;
00883
00884 if((*kernel = (float *) calloc((*windowsize), sizeof(float))) == NULL){
00885 fprintf(stderr, "Error callocing the gaussian kernel array.\n");
00886 exit(1);
00887 }
00888
00889 for(i=0;i<(*windowsize);i++){
00890 x = (float)(i - center);
00891 fx = pow(2.71828, -0.5*x*x/(sigma*sigma)) / (sigma * sqrt(6.2831853));
00892 (*kernel)[i] = fx;
00893 sum += fx;
00894 }
00895
00896 for(i=0;i<(*windowsize);i++) (*kernel)[i] /= sum;
00897
00898 }