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 #ifndef BEOSUB_TEST_HOUGH_C_DEFINED
00039 #define BEOSUB_TEST_HOUGH_C_DEFINED
00040
00041 #include "GUI/XWindow.H"
00042
00043 #include "Image/Image.H"
00044 #include "Image/Pixels.H"
00045
00046 #include "Component/ModelManager.H"
00047 #include "Devices/FrameGrabberFactory.H"
00048 #include "Util/Timer.H"
00049 #include "Util/Types.H"
00050 #include "Util/log.H"
00051 #include "Image/ColorOps.H"
00052 #include "Image/Image.H"
00053 #include "Image/MathOps.H"
00054 #include "Image/DrawOps.H"
00055 #include "Image/FilterOps.H"
00056 #include "Image/Transforms.H"
00057 #include "Raster/Raster.H"
00058 #include "rutz/shared_ptr.h"
00059 #include "BeoSub/hysteresis.H"
00060 #include "VFAT/segmentImageTrackMC.H"
00061 #include <cstdio>
00062 #include <cstdlib>
00063 #include <cstring>
00064 #include <iostream>
00065 #include <math.h>
00066 #include <list>
00067 #include "Image/MatrixOps.H"
00068
00069 #include "MBARI/Geometry2D.H"
00070 #include "rutz/compat_cmath.h"
00071
00072 using std::cout;
00073 using std::endl;
00074 using std::list;
00075
00076
00077
00078 #define BOOSTBLURFACTOR 90.0
00079 #define FREE_ARG char*
00080 #define PI 3.14
00081
00082 XWindow *xwin;
00083 XWindow *xwin2;
00084 XWindow *xwin3;
00085
00086 void gaussian_smooth(unsigned char *image, int rows, int cols, float sigma,
00087 short int **smoothedim);
00088 void make_gaussian_kernel(float sigma, float **kernel, int *windowsize);
00089 void derrivative_x_y(short int *smoothedim, int rows, int cols,
00090 short int **delta_x, short int **delta_y);
00091 void magnitude_x_y(short int *delta_x, short int *delta_y, int rows, int cols,
00092 short int **magnitude);
00093 void radian_direction(short int *delta_x, short int *delta_y, int rows,
00094 int cols, float **dir_radians, int xdirtag, int ydirtag);
00095 void radian_direction(short int *delta_x, short int *delta_y, int rows,
00096 int cols, float **dir_radians, int xdirtag, int ydirtag);
00097 double angle_radians(double x, double y);
00098
00099 std::vector <LineSegment2D> houghTransform(Image<byte> &inputImage, float thetaRes, float dRes, int threshold, Image< PixRGB<byte> > &output) ;
00100
00101
00102
00103
00104
00105
00106
00107
00108 int canny(unsigned char *image, int rows, int cols, float sigma,
00109 float tlow, float thigh, unsigned char **edge, char *fname)
00110 {
00111 FILE *fpdir=NULL;
00112 unsigned char *nms;
00113 short int *smoothedim,
00114 *delta_x,
00115 *delta_y,
00116 *magnitude;
00117 float *dir_radians=NULL;
00118
00119
00120
00121
00122
00123 gaussian_smooth(image, rows, cols, sigma, &smoothedim);
00124
00125
00126
00127
00128
00129 derrivative_x_y(smoothedim, rows, cols, &delta_x, &delta_y);
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139 if(fname != NULL){
00140
00141
00142
00143
00144 radian_direction(delta_x, delta_y, rows, cols, &dir_radians, -1, -1);
00145
00146
00147
00148
00149 if((fpdir = fopen(fname, "wb")) == NULL){
00150 fprintf(stderr, "Error opening the file %s for writing.\n", fname);
00151 exit(1);
00152 }
00153 fwrite(dir_radians, sizeof(float), rows*cols, fpdir);
00154 fclose(fpdir);
00155 free(dir_radians);
00156 }
00157
00158
00159
00160
00161 magnitude_x_y(delta_x, delta_y, rows, cols, &magnitude);
00162
00163
00164
00165
00166 if((nms = (unsigned char *) calloc(rows*cols,sizeof(unsigned char)))==NULL){
00167 fprintf(stderr, "Error allocating the nms image.\n");
00168 exit(1);
00169 }
00170
00171 non_max_supp(magnitude, delta_x, delta_y, rows, cols, nms);
00172
00173
00174
00175
00176 if((*edge=(unsigned char *)calloc(rows*cols,sizeof(unsigned char))) ==NULL){
00177 fprintf(stderr, "Error allocating the edge image.\n");
00178 exit(1);
00179 }
00180
00181 int centroid = apply_hysteresis(magnitude, nms, rows, cols, tlow, thigh, *edge);
00182
00183
00184
00185
00186 free(smoothedim);
00187 free(delta_x);
00188 free(delta_y);
00189 free(magnitude);
00190 free(nms);
00191 return centroid;
00192 }
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209 void radian_direction(short int *delta_x, short int *delta_y, int rows,
00210 int cols, float **dir_radians, int xdirtag, int ydirtag)
00211 {
00212 int r, c, pos;
00213 float *dirim=NULL;
00214 double dx, dy;
00215
00216
00217
00218
00219 if((dirim = (float *) calloc(rows*cols, sizeof(float))) == NULL){
00220 fprintf(stderr, "Error allocating the gradient direction image.\n");
00221 exit(1);
00222 }
00223 *dir_radians = dirim;
00224
00225 for(r=0,pos=0;r<rows;r++){
00226 for(c=0;c<cols;c++,pos++){
00227 dx = (double)delta_x[pos];
00228 dy = (double)delta_y[pos];
00229
00230 if(xdirtag == 1) dx = -dx;
00231 if(ydirtag == -1) dy = -dy;
00232
00233 dirim[pos] = (float)angle_radians(dx, dy);
00234 }
00235 }
00236 }
00237
00238
00239
00240
00241
00242
00243
00244 double angle_radians(double x, double y)
00245 {
00246 double xu, yu, ang;
00247
00248 xu = fabs(x);
00249 yu = fabs(y);
00250
00251 if((xu == 0) && (yu == 0)) return(0);
00252
00253 ang = atan(yu/xu);
00254
00255 if(x >= 0){
00256 if(y >= 0) return(ang);
00257 else return(2*M_PI - ang);
00258 }
00259 else{
00260 if(y >= 0) return(M_PI - ang);
00261 else return(M_PI + ang);
00262 }
00263 }
00264
00265
00266
00267
00268
00269
00270
00271
00272 void magnitude_x_y(short int *delta_x, short int *delta_y, int rows, int cols,
00273 short int **magnitude)
00274 {
00275 int r, c, pos, sq1, sq2;
00276
00277
00278
00279
00280 if((*magnitude = (short *) calloc(rows*cols, sizeof(short))) == NULL){
00281 fprintf(stderr, "Error allocating the magnitude image.\n");
00282 exit(1);
00283 }
00284
00285 for(r=0,pos=0;r<rows;r++){
00286 for(c=0;c<cols;c++,pos++){
00287 sq1 = (int)delta_x[pos] * (int)delta_x[pos];
00288 sq2 = (int)delta_y[pos] * (int)delta_y[pos];
00289 (*magnitude)[pos] = (short)(0.5 + sqrt((float)sq1 + (float)sq2));
00290 }
00291 }
00292
00293 }
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307 void derrivative_x_y(short int *smoothedim, int rows, int cols,
00308 short int **delta_x, short int **delta_y)
00309 {
00310 int r, c, pos;
00311
00312
00313
00314
00315 if(((*delta_x) = (short *) calloc(rows*cols, sizeof(short))) == NULL){
00316 fprintf(stderr, "Error allocating the delta_x image.\n");
00317 exit(1);
00318 }
00319 if(((*delta_y) = (short *) calloc(rows*cols, sizeof(short))) == NULL){
00320 fprintf(stderr, "Error allocating the delta_x image.\n");
00321 exit(1);
00322 }
00323
00324
00325
00326
00327
00328 for(r=0;r<rows;r++){
00329 pos = r * cols;
00330 (*delta_x)[pos] = smoothedim[pos+1] - smoothedim[pos];
00331 pos++;
00332 for(c=1;c<(cols-1);c++,pos++){
00333 (*delta_x)[pos] = smoothedim[pos+1] - smoothedim[pos-1];
00334 }
00335 (*delta_x)[pos] = smoothedim[pos] - smoothedim[pos-1];
00336 }
00337
00338
00339
00340
00341
00342 for(c=0;c<cols;c++){
00343 pos = c;
00344 (*delta_y)[pos] = smoothedim[pos+cols] - smoothedim[pos];
00345 pos += cols;
00346 for(r=1;r<(rows-1);r++,pos+=cols){
00347 (*delta_y)[pos] = smoothedim[pos+cols] - smoothedim[pos-cols];
00348 }
00349 (*delta_y)[pos] = smoothedim[pos] - smoothedim[pos-cols];
00350 }
00351 }
00352
00353
00354
00355
00356
00357
00358
00359 void gaussian_smooth(unsigned char *image, int rows, int cols, float sigma,
00360 short int **smoothedim)
00361 {
00362 int r, c, rr, cc,
00363 windowsize,
00364 center;
00365 float *tempim,
00366 *kernel,
00367 dot,
00368 sum;
00369
00370
00371
00372
00373 make_gaussian_kernel(sigma, &kernel, &windowsize);
00374 center = windowsize / 2;
00375
00376
00377
00378
00379 if((tempim = (float *) calloc(rows*cols, sizeof(float))) == NULL){
00380 fprintf(stderr, "Error allocating the buffer image.\n");
00381 exit(1);
00382 }
00383 if(((*smoothedim) = (short int *) calloc(rows*cols,
00384 sizeof(short int))) == NULL){
00385 fprintf(stderr, "Error allocating the smoothed image.\n");
00386 exit(1);
00387 }
00388
00389
00390
00391
00392 for(r=0;r<rows;r++){
00393 for(c=0;c<cols;c++){
00394 dot = 0.0;
00395 sum = 0.0;
00396 for(cc=(-center);cc<=center;cc++){
00397 if(((c+cc) >= 0) && ((c+cc) < cols)){
00398 dot += (float)image[r*cols+(c+cc)] * kernel[center+cc];
00399 sum += kernel[center+cc];
00400 }
00401 }
00402 tempim[r*cols+c] = dot/sum;
00403 }
00404 }
00405
00406
00407
00408
00409 for(c=0;c<cols;c++){
00410 for(r=0;r<rows;r++){
00411 sum = 0.0;
00412 dot = 0.0;
00413 for(rr=(-center);rr<=center;rr++){
00414 if(((r+rr) >= 0) && ((r+rr) < rows)){
00415 dot += tempim[(r+rr)*cols+c] * kernel[center+rr];
00416 sum += kernel[center+rr];
00417 }
00418 }
00419 (*smoothedim)[r*cols+c] = (short int)(dot*BOOSTBLURFACTOR/sum + 0.5);
00420 }
00421 }
00422
00423 free(tempim);
00424 free(kernel);
00425 }
00426
00427
00428
00429
00430
00431
00432
00433 void make_gaussian_kernel(float sigma, float **kernel, int *windowsize)
00434 {
00435 int i, center;
00436 float x, fx, sum=0.0;
00437
00438 *windowsize = int(1 + 2 * ceil(2.5 * sigma));
00439 center = (*windowsize) / 2;
00440
00441 if((*kernel = (float *) calloc((*windowsize), sizeof(float))) == NULL){
00442 fprintf(stderr, "Error callocing the gaussian kernel array.\n");
00443 exit(1);
00444 }
00445
00446 for(i=0;i<(*windowsize);i++){
00447 x = (float)(i - center);
00448 fx = pow(2.71828, -0.5*x*x/(sigma*sigma)) / (sigma * sqrt(6.2831853));
00449 (*kernel)[i] = fx;
00450 sum += fx;
00451 }
00452
00453 for(i=0;i<(*windowsize);i++) (*kernel)[i] /= sum;
00454
00455 }
00456
00457
00458
00459
00460
00461
00462
00463 std::vector <LineSegment2D> houghTransform(Image<byte> &inputImage, float thetaRes, float dRes, int threshold, Image< PixRGB<byte> > &output)
00464 {
00465 int r;
00466
00467 int numangle = (int) (PI / thetaRes);
00468 int numD = (int) (((inputImage.getWidth() + inputImage.getHeight()) * 2 + 1) / dRes);
00469
00470 std::vector <LineSegment2D> lines;
00471 cout << "Performing Hough Line Transform:" << endl;
00472 cout << "numD: " << numD << endl;
00473 cout << "numangle: " << numangle << endl;
00474
00475
00476 int accumulator[numD][numangle];
00477
00478 for(int i = 0; i<numD; i++)
00479 for(int j = 0; j < numangle; j++)
00480 accumulator[i][j] = 0;
00481
00482
00483
00484
00485 for(int j = 0; j < inputImage.getHeight(); j++ )
00486 for(int i = 0; i < inputImage.getWidth(); i++ )
00487 {
00488 if( inputImage.getVal(i,j) != 0 )
00489 for(int n = 0; n < numangle; n++ )
00490 {
00491 r = (int)(i * cos(n*thetaRes) + j * sin(n*thetaRes));
00492 r += (numD -1)/2;
00493 accumulator[r][n]++;
00494 }
00495 }
00496
00497 Point2D<int> p1;
00498 Point2D<int> p2;
00499 Point2D<int> storage[inputImage.getWidth()*inputImage.getHeight()];
00500 double a;
00501 int totalLines = 0;
00502 int pointCount = 0;
00503
00504
00505 for(int i = 0; i<numD; i++)
00506 for(int j = 0; j < numangle; j++)
00507 {
00508 if(accumulator[i][j] > threshold && accumulator[i][j]> accumulator[i-1][j]
00509 && accumulator[i][j]> accumulator[i+1][j] && accumulator[i][j]> accumulator[i][j-1]
00510 && accumulator[i][j]> accumulator[i][j+1])
00511 {
00512 totalLines++;
00513
00514
00515 a = cos(j*thetaRes);
00516
00517
00518 for(int x = 0; x < inputImage.getWidth(); x++)
00519 for(int y = 0; y < inputImage.getHeight(); y++)
00520 if( inputImage.getVal(x,y) != 0 )
00521 if(((int)(x * cos(j*thetaRes) + y * sin(j*thetaRes))) + ((numD -1)/2) == i)
00522 {
00523 storage[pointCount].i = x;
00524 storage[pointCount].j = y;
00525 pointCount++;
00526 }
00527
00528
00529 bool isolated = true;
00530 int numtoDiscard = 0;
00531 float discardPoints[inputImage.getWidth() * inputImage.getHeight()];
00532 for(int y = 0; y < pointCount; y++){
00533 for(int x = 0; x <pointCount; x++){
00534 if(storage[0].distance(storage[x]) < 1 && x != y)
00535 isolated = false;
00536
00537 }
00538 if(isolated)
00539 {
00540 discardPoints[numtoDiscard++] = y;
00541 }
00542 }
00543
00544
00545
00546
00547 for(int x=0; x < numtoDiscard; x++)
00548 for(int y = 0; y < pointCount; y++)
00549 if(discardPoints[x] != y){
00550 p1.i = p2.i = storage[y].i;
00551 p1.j = p2.j = storage[y].j;
00552
00553 }
00554
00555
00556 if(fabs(a) < .001)
00557 {
00558
00559
00560 for(int x = 0; x < pointCount; x++)
00561 {
00562 bool discard = false;
00563 for(int k = 0; k < numtoDiscard; k++)
00564 if(discardPoints[k] == x)
00565 discard = true;
00566 if(!discard){
00567 if(p1.j < storage[x].j)
00568 {
00569 p1.j = storage[x].j;
00570 p1.i = storage[x].i;
00571 }
00572 if(p2.j > storage[x].j)
00573 {
00574 p2.j = storage[x].j;
00575 p2.i = storage[x].i;
00576
00577 }
00578 }
00579 }
00580
00581 }
00582 else
00583 {
00584
00585 for(int x = 0; x < pointCount; x++)
00586 {
00587 bool discard = false;
00588 for(int k = 0; k < numtoDiscard; k++)
00589 if(discardPoints[k] == x)
00590 discard = true;
00591 if(!discard){
00592
00593 if(p1.i < storage[x].i)
00594 {
00595 p1.j = storage[x].j;
00596 p1.i = storage[x].i;
00597 }
00598 if(p2.i > storage[x].i)
00599 {
00600 p2.j = storage[x].j;
00601 p2.i = storage[x].i;
00602
00603 }
00604 }
00605 }
00606 }
00607 pointCount = 0;
00608 LineSegment2D thisLine(p1, p2);
00609 lines.push_back(thisLine);
00610 drawLine(output,p1, p2, PixRGB<byte> (255,0,0), 1);
00611
00612
00613 }
00614 }
00615 return lines;
00616
00617 }
00618
00619
00620
00621
00622
00623 double sigma(double* r, int N) {
00624 double sum=0.0;
00625 for(int i=0;i<N;++i)
00626 sum += r[i];
00627 return(sum);
00628 }
00629 double sigma(double* r,double* s, int N) {
00630 double sum=0.0;
00631 for(int i=0;i<N;++i)
00632 sum += r[i]*s[i];
00633 return(sum);
00634 }
00635 void findTanLine(int N, double *x, double *y, float &slope, float &Intercept) {
00636 float delta=N*sigma(x,x, N)-pow(sigma(x,N),2.0);
00637 Intercept = (1.0/delta)*(sigma(x,x,N)*sigma(y,N)-sigma(x,N)*sigma(x,y,N));
00638 slope = (1.0/delta)*(N*sigma(x,y, N)-sigma(x, N)*sigma(y,N));
00639 }
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651 void
00652 find_biggest_entry_2x2(double m[][3], int *i, int *j)
00653 {
00654 if ((fabs(m[1][1]) > fabs(m[1][2])) && (fabs(m[1][1]) > fabs(m[2][1])) && (fabs(m[1][1]) > fabs(m[2][2])))
00655 {
00656 *i = 1;
00657 *j = 1;
00658 }
00659 else if ((fabs(m[1][2]) > fabs(m[2][1])) && (fabs(m[1][2]) > fabs(m[2][2])))
00660 {
00661 *i = 1;
00662 *j = 2;
00663 }
00664 else if (fabs(m[2][1]) > fabs(m[2][2]))
00665 {
00666 *i = 2;
00667 *j = 1;
00668 }
00669 else
00670 {
00671 *i = 2;
00672 *j = 2;
00673 }
00674
00675 }
00676
00677
00678
00679
00680
00681 void
00682 find_eigenvectors_2x2_positive_semi_def_real_matrix(double **covar, double *eig_val, double **eig_vec)
00683 {
00684 double a, b, c, d;
00685 int i, j;
00686 double tmp[3][3];
00687
00688
00689
00690
00691 a = 1;
00692 b = -covar[1][1] - covar[2][2];
00693 c = covar[1][1]*covar[2][2] - covar[1][2]*covar[2][1];
00694
00695 d = squareOf(b) - 4*a*c;
00696 if (d <= 10e-5)
00697 {
00698 eig_val[1] = -b / 2.0;
00699 eig_val[2] = -b / 2.0;
00700 eig_vec[1][1] = 1.0; eig_vec[1][2] = 0.0;
00701 eig_vec[2][1] = 0.0; eig_vec[2][2] = 1.0;
00702 }
00703 else
00704 {
00705 eig_val[1] = (-b + sqrt(d)) / 2.0;
00706 eig_val[2] = (-b - sqrt(d)) / 2.0;
00707
00708
00709
00710 if (eig_val[1] < eig_val[2])
00711 {
00712 d = eig_val[1];
00713 eig_val[1] = eig_val[2];
00714 eig_val[2] = d;
00715 }
00716
00717
00718
00719 tmp[1][1] = covar[1][1] - eig_val[1];
00720 tmp[1][2] = covar[1][2];
00721 tmp[2][1] = covar[2][1];
00722 tmp[2][2] = covar[2][2] - eig_val[1];
00723
00724
00725 find_biggest_entry_2x2(tmp, &i, &j);
00726 if (j == 1)
00727 {
00728 eig_vec[2][1] = 1.0;
00729 eig_vec[1][1] = -tmp[i][2] / tmp[i][1];
00730 }
00731 else
00732 {
00733 eig_vec[1][1] = 1.0;
00734 eig_vec[2][1] = -tmp[i][1] / tmp[i][2];
00735 }
00736
00737
00738 d = sqrt(squareOf(eig_vec[1][1]) + squareOf(eig_vec[2][1]));
00739 eig_vec[1][1] /= d;
00740 eig_vec[2][1] /= d;
00741
00742
00743
00744
00745 eig_vec[1][2] = -eig_vec[2][1];
00746 eig_vec[2][2] = eig_vec[1][1];
00747
00748 }
00749
00750
00751
00752 }
00753
00754
00755 void
00756 SwapRows(double *A, double *B, int els)
00757 {
00758 double temp;
00759 int a;
00760
00761 for(a=1;a<=els;a++)
00762 {
00763 temp=A[a];
00764 A[a]=B[a];
00765 B[a]=temp;
00766 }
00767 }
00768
00769
00770 void
00771 TakeWeightRow(double *A, double *B, double num, double denom, int els)
00772 {
00773 int a;
00774
00775 for(a=1;a<=els;a++)
00776 A[a]=(A[a]*denom-B[a]*num)/denom;
00777
00778 }
00779
00780 void
00781 ScaleRow(double *A, double fact, int els)
00782 {
00783 int a;
00784
00785 for(a=1;a<=els;a++)
00786 A[a]/=fact;
00787
00788 }
00789 double **
00790 alloc_array(int row, int column)
00791 {
00792 double **rowp;
00793 int a;
00794
00795
00796 if ( (rowp=(double **)malloc((unsigned )(row+1) * sizeof(double *)) ) == NULL)
00797 return(NULL);
00798 for(a=1;a<=row;a++)
00799 {
00800 if ((rowp[a]=(double *)malloc((unsigned)(column+1)*sizeof(double))) == NULL)
00801 return(NULL);
00802 }
00803
00804 return(rowp);
00805
00806 }
00807
00808
00809 void
00810 free_array(double **A, int row)
00811 {
00812 int i;
00813
00814 for (i=1; i <= row; i++)
00815 free(A[i]);
00816 free(A);
00817
00818 }
00819
00820 double *alloc_vector(int dim)
00821 {
00822 return( (double *)malloc(( (unsigned )(dim+1) ) * sizeof(double)) );
00823 }
00824
00825
00826
00827
00828 void
00829 find_inverse(double **MAT, double **I, int dim)
00830 {
00831
00832 int a,b,R;
00833 double num,denom;
00834 double **M;
00835
00836 M = alloc_array(dim, dim);
00837 for (a=1; a<=dim; a++)
00838 for (b=1; b<=dim; b++)
00839 M[a][b] = MAT[a][b];
00840
00841 for(R=1;R<=dim;R++)
00842 for(a=1;a<=dim;a++)
00843 I[R][a]=(R==a)?1:0;
00844 for(R=1;R<=dim;R++)
00845 {
00846 if(M[R][R]==0)
00847 {
00848 for(a=R+1;a<=dim;a++)
00849 if (M[a][R]!=0) break;
00850 if (a==(dim+1))
00851 {
00852 fprintf(stderr, "Matrix non-invertable, fail on row %d left.\n",R);
00853 fprintf(stderr, "in find_inverse() in lin_algebra.c\n");
00854 exit(1);
00855 }
00856 SwapRows(M[R],M[a],dim);
00857 SwapRows(I[R],I[a],dim);
00858 }
00859 denom=M[R][R];
00860 for(a=R+1;a<=dim;a++)
00861 {
00862 num=M[a][R];
00863 TakeWeightRow(M[a],M[R],num,denom,dim);
00864 TakeWeightRow(I[a],I[R],num,denom,dim);
00865 }
00866 }
00867 for(R=dim;R>=1;R--)
00868 {
00869 for(a=R+1;a<=dim;a++)
00870 {
00871 num=M[R][a];
00872 denom=M[a][a];
00873 TakeWeightRow(M[R],M[a],num,denom,dim);
00874 TakeWeightRow(I[R],I[a],num,denom,dim);
00875 }
00876 }
00877 for(R=1;R<=dim;R++)
00878 ScaleRow(I[R],M[R][R],dim);
00879
00880 free_array(M, dim);
00881
00882
00883 }
00884
00885
00886
00887
00888
00889
00890
00891 #define TINY_VALUE 1.0e-20;
00892 int
00893 lu_decomposition(double **M, int n, int *indx, double *d)
00894 {
00895 int i, imax, j, k;
00896 double big,dum,sum,temp;
00897 double *vec;
00898
00899 vec = alloc_vector(n);
00900 *d = 1.0;
00901 for (i=1; i <= n; i++)
00902 {
00903 big=0.0;
00904 for (j=1; j <= n; j++)
00905 if ((temp=fabs(M[i][j])) > big) big=temp;
00906 if (big == 0.0)
00907 {
00908
00909
00910 return(-1);
00911 }
00912 vec[i]=1.0/big;
00913 }
00914 for (j=1; j <= n; j++)
00915 {
00916 for (i=1; i < j; i++)
00917 {
00918 sum=M[i][j];
00919 for (k=1;k<i;k++)
00920 sum -= M[i][k]*M[k][j];
00921 M[i][j]=sum;
00922 }
00923 big=0.0;
00924 imax = 0;
00925 for (i=j; i <= n; i++)
00926 {
00927 sum = M[i][j];
00928 for (k=1; k < j; k++)
00929 sum -= M[i][k]*M[k][j];
00930 M[i][j]=sum;
00931 if ( (dum=vec[i]*fabs(sum)) >= big)
00932 {
00933 big = dum;
00934 imax = i;
00935 }
00936 }
00937 if (j != imax)
00938 {
00939 for (k=1; k <= n; k++)
00940 {
00941 dum=M[imax][k];
00942 M[imax][k]=M[j][k];
00943 M[j][k]=dum;
00944 }
00945 *d = -(*d);
00946 vec[imax]=vec[j];
00947 }
00948 indx[j]=imax;
00949 if (M[j][j] == 0.0)
00950 M[j][j] = TINY_VALUE;
00951 if (j != n)
00952 {
00953 dum=1.0/(M[j][j]);
00954 for (i=j+1; i<=n; i++)
00955 M[i][j] *= dum;
00956 }
00957 }
00958 free(vec);
00959
00960
00961 return(0);
00962
00963 }
00964 #undef TINY_VALUE
00965
00966
00967
00968
00969
00970
00971 void
00972 lu_back_substitution(double **M, int n, int *indx, double *b)
00973 {
00974 int i, ii=0, ip, j;
00975 double sum;
00976
00977 for (i=1;i<=n;i++)
00978 {
00979 ip=indx[i];
00980 sum=b[ip];
00981 b[ip]=b[i];
00982 if (ii)
00983 for (j=ii;j<=i-1;j++)
00984 sum -= M[i][j]*b[j];
00985 else if (sum) ii=i;
00986 b[i] = sum;
00987 }
00988 for (i=n; i >=1 ;i--)
00989 {
00990 sum = b[i];
00991 for (j=i+1;j<=n;j++)
00992 sum -= M[i][j]*b[j];
00993 b[i] = sum/M[i][i];
00994 }
00995 }
00996
00997
00998
00999
01000 bool
01001 transform_ellipse_parameters(double a, double b, double c,
01002 double *r1, double *r2, double *theta)
01003 {
01004 double **M, **C, **eig_vec;
01005 double *eig_val;
01006
01007
01008 M = alloc_array(2, 2);
01009 C = alloc_array(2, 2);
01010 eig_vec = alloc_array(2, 2);
01011 eig_val = alloc_vector(2);
01012
01013 if ((M == NULL) || (C == NULL) || (eig_val == NULL) || (eig_vec == NULL))
01014 {
01015 fprintf(stderr, "malloc failed in transform_ellipse_parameters() in rht.c\n");
01016 exit(1);
01017 }
01018
01019
01020 M[1][1] = a;
01021 M[1][2] = M[2][1] = b;
01022 M[2][2] = c;
01023 find_inverse(M, C, 2);
01024 find_eigenvectors_2x2_positive_semi_def_real_matrix(C, eig_val, eig_vec);
01025
01026 if ((eig_val[1] <= 0) || (eig_val[2] <= 0))
01027 {
01028 return( false );
01029 }
01030
01031
01032 *r1 = sqrt(eig_val[1]);
01033 *r2 = sqrt(eig_val[2]);
01034 *theta = atan2(eig_vec[2][1], eig_vec[1][1]);
01035
01036
01037 free_array(M, 2);
01038 free_array(C, 2);
01039 free_array(eig_vec, 2);
01040 free(eig_val);
01041
01042
01043 return( true );
01044
01045 }
01046
01047
01048
01049
01050
01051
01052
01053 struct ellipse {
01054 int x, y, confidence;
01055 double r1, r2, theta;
01056 };
01057
01058
01059 void drawEllipse(Image< PixRGB<byte> > &output, list<ellipse> &houghSpace)
01060 {
01061
01062 list<ellipse>::iterator Iter;
01063
01064 for(Iter = houghSpace.begin(); Iter != houghSpace.end(); Iter++)
01065 {
01066
01067
01068
01069
01070
01071
01072
01073
01074
01075 int width = 20;
01076 int x, y;
01077 int x1, y1, x2, y2;
01078 double perimeter, incr, grad, rho;
01079 double M[3][3];
01080 int offset;
01081 bool error = false;
01082
01083 if (((*Iter).r1 <= 20) || ((*Iter).r2 <= 20))
01084 error = true;
01085
01086
01087
01088
01089
01090
01091
01092 perimeter = 3.14159 * ( 3*(fabs((*Iter).r1)+fabs((*Iter).r2)) - sqrt( (fabs((*Iter).r1)+3*fabs((*Iter).r2))*(3*fabs((*Iter).r1)+fabs((*Iter).r2)) ) );
01093
01094
01095
01096
01097
01098 if (perimeter <= 20)
01099 error = true;
01100
01101
01102 if(!error && (*Iter).confidence > 10)
01103 {
01104
01105 incr = 60.0/perimeter;
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122 M[1][1] = (*Iter).r1*pow(cos((*Iter).theta),2) + (*Iter).r2*pow(sin((*Iter).theta),2);
01123 M[1][2] = M[2][1] = ((*Iter).r1-(*Iter).r2)*sin((*Iter).theta)*cos((*Iter).theta);
01124 M[2][2] = (*Iter).r1*(pow(sin((*Iter).theta),2)) + (*Iter).r2*(pow(cos((*Iter).theta),2));
01125
01126 x1 = (int )((*Iter).x + M[1][1]*cos(0.0) + M[1][2]*sin(0.0));
01127 y1 = (int )((*Iter).y + M[2][1]*cos(0.0) + M[2][2]*sin(0.0));
01128
01129
01130 for (rho=incr; rho < (2*M_PI + incr); rho += incr)
01131 {
01132 x2 = (int )((*Iter).x + M[1][1]*cos(rho) + M[1][2]*sin(rho));
01133 y2 = (int )((*Iter).y + M[2][1]*cos(rho) + M[2][2]*sin(rho));
01134 if ((x1 >= 0) && (x1 < output.getWidth()) && (y1 >= 0) && (y1 < output.getHeight()) &&
01135 (x2 >= 0) && (x2 < output.getWidth()) && (y2 >= 0) && (y2 < output.getHeight()))
01136 {
01137 if (fabs(x2-x1) >= fabs(y2-y1))
01138 {
01139
01140
01141 if (x1 < x2)
01142 {
01143 grad = ((double )(y2-y1)) / (double )(x2-x1);
01144 for (x=x1; x <= x2; x++)
01145 {
01146 y = y1 + (int )(grad*(double )(x - x1));
01147 for (offset=-width/2; offset < (width+1)/2; offset++)
01148 {
01149 if (((y+offset) >= 0) && ((y+offset) < output.getHeight()))
01150 {
01151 drawPoint(output,x,y,PixRGB<byte> (255,0,0));
01152
01153 }
01154 }
01155 }
01156 }
01157 else if (x1 > x2)
01158 {
01159 grad = ((double )(y1-y2)) / (double )(x1-x2);
01160 for (x=x2; x <= x1; x++)
01161 {
01162 y = y2 + (int )(grad*(double )(x - x2));
01163 for (offset=-width/2; offset < (width+1)/2; offset++)
01164 {
01165 if (((y+offset) >= 0) && ((y+offset) < output.getHeight()))
01166 {
01167 drawPoint(output,x,y,PixRGB<byte> (255,0,0));
01168
01169 }
01170 }
01171 }
01172 }
01173 }
01174 else
01175 {
01176
01177
01178 if (y1 < y2)
01179 {
01180 grad = ((double )(x2-x1)) / (double )(y2-y1);
01181 for (y=y1; y <= y2; y++)
01182 {
01183 x = x1 + (int )(grad*(double )(y-y1));
01184 for (offset=-width/2; offset < (width+1)/2; offset++)
01185 {
01186 if (((x+offset) >= 0) && ((x+offset) < output.getWidth()))
01187 {
01188 drawPoint(output,x,y,PixRGB<byte> (255,0,0));
01189
01190 }
01191 }
01192 }
01193 }
01194 else if (y1 > y2)
01195 {
01196 grad = ((double )(x1-x2)) / (double )(y1-y2);
01197 for (y=y2; y <= y1; y++)
01198 {
01199 x = x2 + (int )(grad*(double )(y - y2));
01200 for (offset=-width/2; offset < (width+1)/2; offset++)
01201 {
01202 if (((x+offset) >= 0) && ((x+offset) < output.getWidth()))
01203 {
01204 drawPoint(output,x,y,PixRGB<byte> (255,0,0));
01205
01206 }
01207 }
01208 }
01209 }
01210 }
01211 }
01212 x1 = x2;
01213 y1 = y2;
01214 }
01215 }
01216 }
01217
01218 }
01219
01220
01221 int
01222 count_pixels(Image<byte> &output, double x_centre, double y_centre,
01223 double r1, double r2, double theta)
01224 {
01225
01226
01227
01228
01229
01230 int width = 20;
01231 int x, y;
01232 int x1, y1, x2, y2;
01233 double perimeter, incr, grad, rho;
01234 double M[3][3];
01235 int offset;
01236 int num_pixels = 0;
01237
01238 if ((r1 <= width) || (r2 <= width))
01239 return(0);
01240
01241
01242
01243
01244
01245
01246
01247
01248 perimeter = M_PI * ( 3*(fabs(r1)+fabs(r2)) - sqrt( (fabs(r1)+3*fabs(r2))*(3*fabs(r1)+fabs(r2)) ) );
01249
01250
01251
01252
01253 if (perimeter <= width)
01254 return( 0 );
01255
01256
01257
01258
01259
01260 incr = 60.0/perimeter;
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277 M[1][1] = r1*squareOf(cos(theta)) + r2*squareOf(sin(theta));
01278 M[1][2] = M[2][1] = (r1-r2)*sin(theta)*cos(theta);
01279 M[2][2] = r1*squareOf(sin(theta)) + r2*squareOf(cos(theta));
01280
01281 x1 = (int )(x_centre + M[1][1]*cos(0.0) + M[1][2]*sin(0.0));
01282 y1 = (int )(y_centre + M[2][1]*cos(0.0) + M[2][2]*sin(0.0));
01283
01284
01285 for (rho=incr; rho < (2*M_PI + incr); rho += incr)
01286 {
01287 x2 = (int )(x_centre + M[1][1]*cos(rho) + M[1][2]*sin(rho));
01288 y2 = (int )(y_centre + M[2][1]*cos(rho) + M[2][2]*sin(rho));
01289 if ((x1 >= 0) && (x1 < output.getWidth()) && (y1 >= 0) && (y1 < output.getHeight()) &&
01290 (x2 >= 0) && (x2 < output.getWidth()) && (y2 >= 0) && (y2 < output.getHeight()))
01291 {
01292 if (abs(x2-x1) >= abs(y2-y1))
01293 {
01294
01295
01296 if (x1 < x2)
01297 {
01298 grad = ((double )(y2-y1)) / (double )(x2-x1);
01299 for (x=x1; x <= x2; x++)
01300 {
01301 y = y1 + (int )(grad*(double )(x - x1));
01302 for (offset=-width/2; offset < (width+1)/2; offset++)
01303 {
01304 if (((y+offset) >= 0) && ((y+offset) < output.getHeight()))
01305 {
01306 if ((output.getVal(x,y+offset) == 255))
01307 {
01308 num_pixels++;
01309 }
01310 }
01311 }
01312 }
01313 }
01314 else if (x1 > x2)
01315 {
01316 grad = ((double )(y1-y2)) / (double )(x1-x2);
01317 for (x=x2; x <= x1; x++)
01318 {
01319 y = y2 + (int )(grad*(double )(x - x2));
01320 for (offset=-width/2; offset < (width+1)/2; offset++)
01321 {
01322 if (((y+offset) >= 0) && ((y+offset) < output.getHeight()))
01323 {
01324 if ((output.getVal(x,y+offset) == 255))
01325 {
01326 num_pixels++;
01327 }
01328 }
01329 }
01330 }
01331 }
01332 }
01333 else
01334 {
01335
01336
01337 if (y1 < y2)
01338 {
01339 grad = ((double )(x2-x1)) / (double )(y2-y1);
01340 for (y=y1; y <= y2; y++)
01341 {
01342 x = x1 + (int )(grad*(double )(y-y1));
01343 for (offset=-width/2; offset < (width+1)/2; offset++)
01344 {
01345 if (((x+offset) >= 0) && ((x+offset) < output.getWidth()))
01346 {
01347 if ((output.getVal(x+offset,y) == 255))
01348 {
01349 num_pixels++;
01350 }
01351 }
01352 }
01353 }
01354 }
01355 else if (y1 > y2)
01356 {
01357 grad = ((double )(x1-x2)) / (double )(y1-y2);
01358 for (y=y2; y <= y1; y++)
01359 {
01360 x = x2 + (int )(grad*(double )(y - y2));
01361 for (offset=-width/2; offset < (width+1)/2; offset++)
01362 {
01363 if (((x+offset) >= 0) && ((x+offset) < output.getWidth()))
01364 {
01365 if ((output.getVal(x+offset,y) == 255))
01366 {
01367 num_pixels++;
01368 }
01369 }
01370 }
01371 }
01372 }
01373 }
01374 }
01375 x1 = x2;
01376 y1 = y2;
01377 }
01378
01379
01380 return( num_pixels );
01381
01382
01383 }
01384
01385
01386
01387 void houghEllipse(Image<byte> inputImage, int threshold, Image< PixRGB<byte> > &output) {
01388
01389 Point2D<int> randomPixels[3];
01390 double pointX[3][25];
01391 double pointY[3][25];
01392 float slopeTan[3];
01393 float InterTan[3];
01394 float slopeCenterLine[2] = { 0.0F, 0.0F };
01395 float InterCenterLine[2] = { 0.0F, 0.0F };
01396
01397 bool foundCenterPoint = true;
01398 bool foundOtherParams = true;
01399
01400 int p, q;
01401 double a,b,c,r1,r2,theta;
01402 double **matrixA;
01403 double *vectorB;
01404 double d;
01405 int* indx= (int *)malloc(4 * sizeof(int) );
01406
01407 matrixA = alloc_array(3,3);
01408 vectorB = alloc_vector(3);
01409
01410 list<ellipse> houghSpace;
01411 list<ellipse>::iterator Iter;
01412 int NUMBER=0;
01413 int Iterations = 0;
01414
01415 int max = 0;
01416 list<ellipse>::iterator indexOfMax;
01417 list<ellipse> tempSpace;
01418
01419 srand( time(NULL));
01420 while(Iterations < inputImage.getWidth() * inputImage.getHeight())
01421 {
01422
01423
01424 int pixelCount = 0;
01425 while(pixelCount != 3)
01426 {
01427 randomPixels[pixelCount].i = rand()%320;
01428 randomPixels[pixelCount].j = rand()%240;
01429 if(inputImage.getVal(randomPixels[pixelCount].i, randomPixels[pixelCount].j) == 255)
01430 {
01431 if(pixelCount == 1)
01432 {
01433 if(!(randomPixels[pixelCount].i == randomPixels[0].i))
01434 {
01435 pixelCount++;
01436
01437
01438 }
01439
01440 }else if(pixelCount == 2)
01441 {
01442 if(!(randomPixels[pixelCount].i == randomPixels[0].i || randomPixels[pixelCount].i == randomPixels[1].i))
01443 {
01444 pixelCount++;
01445
01446
01447 }
01448 }
01449 else
01450 {
01451 pixelCount++;
01452
01453
01454 }
01455
01456 }
01457
01458
01459
01460 }
01461
01462
01463
01464 foundCenterPoint = true;
01465 foundOtherParams = true;
01466
01467
01468
01469
01470 int count[3] = {0,0,0};
01471 int tempI = 0, tempJ = 0;
01472 for(int j = 0; j < 3; j++)
01473 {
01474 for(int i = 0; i < 5; i++)
01475 for(int k = 0; k < 5; k++)
01476 {
01477 tempI = randomPixels[j].i + (i-2);
01478 tempJ = randomPixels[j].j + (k-2);
01479 if(tempI >=0 && tempI <320 && tempJ >= 0 && tempJ < 240){
01480 if(inputImage.getVal(tempI,tempJ)==255 || (tempI == randomPixels[j].i && tempJ == randomPixels[j].j))
01481 {
01482 if(randomPixels[j].j != tempJ || (randomPixels[j].j == tempJ && randomPixels[j].i == tempI)){
01483 pointX[j][count[j]] = tempI;
01484 pointY[j][count[j]] = tempJ;
01485 count[j]++;
01486 }
01487 }
01488 }
01489
01490 }
01491
01492 }
01493
01494
01495 for(int i = 0; i < 3; i++){
01496 findTanLine(count[i], pointX[i], pointY[i], slopeTan[i], InterTan[i]);
01497
01498 }
01499
01500
01501 for(int i = 0; i < 2; i++){
01502 if(!isnan(slopeTan[i]) && !isnan(slopeTan[i+1]))
01503 {
01504 slopeCenterLine[i] = ((slopeTan[i] *((InterTan[i+1]-InterTan[i])/(slopeTan[i]-slopeTan[i+1]))) + InterTan[i] - ((randomPixels[i].j+randomPixels[i+1].j)/2.0))/(((InterTan[i+1]-InterTan[i])/(slopeTan[i]-slopeTan[i+1])) - ((randomPixels[i].i+randomPixels[i+1].i)/2.0));
01505 InterCenterLine[i] = ((randomPixels[i].j + randomPixels[i+1].j)/2.0) - slopeCenterLine[i] * ((randomPixels[i].i + randomPixels[i+1].i)/2.0);
01506 if(isnan(slopeCenterLine[i]))
01507 {
01508 InterCenterLine[i] = (randomPixels[i].i + randomPixels[i+1].i)/2.0;
01509 }
01510 }
01511 else if(!isnan(slopeTan[i]) && isnan(slopeTan[i+1]))
01512 {
01513 slopeCenterLine[i] = ((slopeTan[i] * randomPixels[i+1].i + InterTan[i]) - ((randomPixels[i].j + randomPixels[i+1].j)/2.0)) / (randomPixels[i+1].i - ((randomPixels[i].i + randomPixels[i+1].i)/2.0));
01514 InterCenterLine[i] = ((randomPixels[i].j + randomPixels[i+1].j)/2.0) - slopeCenterLine[i] * ((randomPixels[i].i + randomPixels[i+1].i)/2.0);
01515 if(isnan(slopeCenterLine[i]))
01516 {
01517 InterCenterLine[i] = randomPixels[i].i;
01518 }
01519 }
01520 else if(!isnan(slopeTan[i+1]) && isnan(slopeTan[i]))
01521 {
01522 slopeCenterLine[i] = ((slopeTan[i+1] * randomPixels[i].i + InterTan[i+1]) - ((randomPixels[i].j + randomPixels[i+1].j)/2.0)) / (randomPixels[i+1].i - ((randomPixels[i].i + randomPixels[i+1].i)/2.0));
01523 InterCenterLine[i] = ((randomPixels[i].j + randomPixels[i+1].j)/2.0) - slopeCenterLine[i] * ((randomPixels[i].i + randomPixels[i+1].i)/2.0);
01524 if(isnan(slopeCenterLine[i]))
01525 {
01526 InterCenterLine[i] = ((randomPixels[i].i + randomPixels[i+1].i)/2.0);
01527 }
01528 }
01529 else
01530 {
01531 foundCenterPoint = false;
01532 }
01533
01534 }
01535 if(foundCenterPoint)
01536 {
01537
01538 if(!isnan(slopeCenterLine[0]) && !isnan(slopeCenterLine[1]))
01539 {
01540
01541 p = (int)((InterCenterLine[1]-InterCenterLine[0])/(slopeCenterLine[0]-slopeCenterLine[1]));
01542 q = (int)((slopeCenterLine[0]*p)+InterCenterLine[0]);
01543 }
01544 else if(!isnan(slopeCenterLine[0]) && isnan(slopeCenterLine[1]) )
01545 {
01546 p = (int) InterCenterLine[1];
01547 q = (int) ((slopeCenterLine[0] * InterCenterLine[1]) + InterCenterLine[0]);
01548 }
01549 else if(!isnan(slopeCenterLine[1]) && isnan(slopeCenterLine[0]) )
01550 {
01551 p = (int) InterCenterLine[0];
01552 q = (int) ((slopeCenterLine[1] * InterCenterLine[0]) + InterCenterLine[1]);
01553 }
01554 else
01555 {
01556 p = -1;
01557 q = -1;
01558
01559 foundCenterPoint = false;
01560
01561 }
01562 if(p < 0 || p > 320 || q < 0 || q > 240)
01563 foundCenterPoint = false;
01564 }
01565
01566 if(foundCenterPoint)
01567 {
01568 for(int i = 1; i < 4; i++)
01569 {
01570
01571 matrixA[i][1] = (randomPixels[i-1].i - p) * (randomPixels[i-1].i- p);
01572 matrixA[i][2] =(randomPixels[i-1].i-p) * (randomPixels[i-1].j-q) * 2;
01573 matrixA[i][3] = (randomPixels[i-1].j-q) * (randomPixels[i-1].j-q);
01574 vectorB[i] = 1;
01575 }
01576
01577
01578 if (lu_decomposition(matrixA, 3, indx, &d) != 0)
01579 {
01580 foundOtherParams = false;
01581 }
01582 if(foundOtherParams)
01583 {
01584 lu_back_substitution(matrixA, 3, indx,vectorB);
01585
01586 a = vectorB[1];
01587 b = vectorB[2];
01588 c = vectorB[3];
01589
01590 if(a * c - b * b > 0)
01591 {
01592 if(transform_ellipse_parameters(a, b, c,&r1, &r2, &theta))
01593 {
01594
01595
01596
01597 if(true)
01598 {
01599
01600
01601 bool found = false;
01602
01603 for(Iter = houghSpace.begin(); Iter != houghSpace.end(); Iter++)
01604 {
01605 if(( fabs((*Iter).x - p) < 10 && fabs((*Iter).y - q) < 10 && fabs((*Iter).r1 - r1) < 5 && fabs((*Iter).r2 - r2) < 5 && fabs((*Iter).theta - theta) < .4487))
01606 {
01607 found = true;
01608 (*Iter).confidence++;
01609 if((*Iter).confidence > max)
01610 {
01611 max = (*Iter).confidence;
01612 indexOfMax = Iter;
01613 }
01614 }
01615 }
01616 if(!found)
01617 {
01618 ellipse temp;
01619 temp.x = p;
01620 temp.y = q;
01621 temp.r1 = r1;
01622 temp.r2 = r2;
01623 temp.theta = theta;
01624 temp.confidence = 1;
01625 houghSpace.push_back(temp);
01626 }
01627 NUMBER++;
01628 }
01629 }
01630 }
01631 }
01632 }
01633 Iterations++;
01634
01635 }
01636
01637 ellipse temp;
01638 temp.x = (*indexOfMax).x;
01639 temp.y = (*indexOfMax).y;
01640 temp.r1 = (*indexOfMax).r1;
01641 temp.r2 = (*indexOfMax).r2;
01642 temp.theta = (*indexOfMax).theta;
01643 temp.confidence = (*indexOfMax).confidence;
01644 cout<<temp.confidence<<endl;
01645 tempSpace.push_back(temp);
01646 drawEllipse(output, tempSpace);
01647 free(indx);
01648
01649 }
01650
01651
01652
01653
01654
01655
01656
01657
01658 int main() {
01659 float sigma = .7;
01660 float tlow = 0.2;
01661 float thigh = .97;
01662
01663 unsigned char *edge;
01664
01665 char *dirfilename = NULL;
01666
01667
01668 ModelManager camManager("ColorTracker Tester");
01669 nub::soft_ref<FrameIstream>
01670 gb(makeIEEE1394grabber(camManager, "COcam", "cocam"));
01671
01672 camManager.addSubComponent(gb);
01673
01674 camManager.loadConfig("camconfig.pmap");
01675
01676 gb->setModelParamVal("FrameGrabberSubChan", 0);
01677 gb->setModelParamVal("FrameGrabberBrightness", 128);
01678 gb->setModelParamVal("FrameGrabberHue", 180);
01679
01680
01681
01682 camManager.start();
01683
01684 Image< PixRGB<byte> > cameraImage;
01685 Image<byte> grayImg;
01686 Image< PixRGB<byte> > houghImg(320,240,ZEROS) ;
01687
01688 cameraImage = gb->readRGB();
01689 xwin = new XWindow(cameraImage.getDims());
01690 xwin2 = new XWindow(cameraImage.getDims());
01691 xwin3 = new XWindow(cameraImage.getDims());
01692
01693 while(1) {
01694
01695 printf(".");
01696 cameraImage = gb->readRGB();
01697
01698 xwin->drawImage(cameraImage);
01699 grayImg = luminance(cameraImage);
01700
01701 canny(grayImg.getArrayPtr(), grayImg.getHeight(), grayImg.getWidth(), sigma, tlow, thigh, &edge, dirfilename);
01702 Image<unsigned char> edgeImage(edge, grayImg.getWidth(), grayImg.getHeight());
01703 xwin2->drawImage(edgeImage);
01704 houghImg = edgeImage;
01705
01706 std::vector <LineSegment2D> lines = houghTransform(edgeImage, PI/180, 1, 80, houghImg);
01707
01708 xwin3->drawImage(houghImg);
01709
01710
01711 }
01712
01713
01714 }
01715
01716
01717
01718
01719
01720
01721
01722
01723 #endif // BEOSUB_TEST_HOUGH_C_DEFINED