00001 #ifndef CANNYEDGE_C
00002 #define CANNYEDGE_C
00003
00004 #include "BeoSub/CannyEdge.H"
00005
00006 #include "Util/Types.H"
00007 #include "Util/log.H"
00008 #include "Image/ColorOps.H"
00009 #include "Image/Image.H"
00010 #include "Image/MathOps.H"
00011 #include "Image/DrawOps.H"
00012 #include "Image/FilterOps.H"
00013 #include "Image/Transforms.H"
00014 #include "Raster/Raster.H"
00015 #include "rutz/shared_ptr.h"
00016 #include "BeoSub/hysteresis.H"
00017 #include "VFAT/segmentImageTrackMC.H"
00018 #include <cstdio>
00019 #include <cstdlib>
00020 #include <cstring>
00021 #include <iostream>
00022 #include <math.h>
00023 #include <list>
00024 #include "Image/MatrixOps.H"
00025
00026
00027
00028
00029
00030
00031
00032 int cannyEdge(Image<byte> &inputImage, float sigma, float tlow, float thigh, Image<byte> &outputImage) {
00033 unsigned char *edge;
00034 int ret = canny(inputImage.getArrayPtr(), inputImage.getHeight(), inputImage.getWidth(), sigma, tlow, thigh, &edge, NULL);
00035 outputImage = Image<unsigned char>(edge, inputImage.getWidth(), inputImage.getHeight());
00036 free(edge);
00037 return ret;
00038 }
00039
00040
00041
00042
00043
00044
00045
00046
00047 int canny(unsigned char *image, int rows, int cols, float sigma,
00048 float tlow, float thigh, unsigned char **edge, char *fname)
00049 {
00050 FILE *fpdir=NULL;
00051 unsigned char *nms;
00052 short int *smoothedim,
00053 *delta_x,
00054 *delta_y,
00055 *magnitude;
00056 float *dir_radians=NULL;
00057
00058
00059
00060
00061
00062 gaussian_smooth(image, rows, cols, sigma, &smoothedim);
00063
00064
00065
00066
00067
00068 derrivative_x_y(smoothedim, rows, cols, &delta_x, &delta_y);
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078 if(fname != NULL){
00079
00080
00081
00082
00083 radian_direction(delta_x, delta_y, rows, cols, &dir_radians, -1, -1);
00084
00085
00086
00087
00088 if((fpdir = fopen(fname, "wb")) == NULL){
00089 fprintf(stderr, "Error opening the file %s for writing.\n", fname);
00090 exit(1);
00091 }
00092 fwrite(dir_radians, sizeof(float), rows*cols, fpdir);
00093 fclose(fpdir);
00094 free(dir_radians);
00095 }
00096
00097
00098
00099
00100 magnitude_x_y(delta_x, delta_y, rows, cols, &magnitude);
00101
00102
00103
00104
00105 if((nms = (unsigned char *) calloc(rows*cols,sizeof(unsigned char)))==NULL){
00106 fprintf(stderr, "Error allocating the nms image.\n");
00107 exit(1);
00108 }
00109
00110 non_max_supp(magnitude, delta_x, delta_y, rows, cols, nms);
00111
00112
00113
00114
00115 if((*edge=(unsigned char *)calloc(rows*cols,sizeof(unsigned char))) ==NULL){
00116 fprintf(stderr, "Error allocating the edge image.\n");
00117 exit(1);
00118 }
00119
00120 int centroid = apply_hysteresis(magnitude, nms, rows, cols, tlow, thigh, *edge);
00121
00122
00123
00124
00125 free(smoothedim);
00126 free(delta_x);
00127 free(delta_y);
00128 free(magnitude);
00129 free(nms);
00130 return centroid;
00131 }
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148 void radian_direction(short int *delta_x, short int *delta_y, int rows,
00149 int cols, float **dir_radians, int xdirtag, int ydirtag)
00150 {
00151 int r, c, pos;
00152 float *dirim=NULL;
00153 double dx, dy;
00154
00155
00156
00157
00158 if((dirim = (float *) calloc(rows*cols, sizeof(float))) == NULL){
00159 fprintf(stderr, "Error allocating the gradient direction image.\n");
00160 exit(1);
00161 }
00162 *dir_radians = dirim;
00163
00164 for(r=0,pos=0;r<rows;r++){
00165 for(c=0;c<cols;c++,pos++){
00166 dx = (double)delta_x[pos];
00167 dy = (double)delta_y[pos];
00168
00169 if(xdirtag == 1) dx = -dx;
00170 if(ydirtag == -1) dy = -dy;
00171
00172 dirim[pos] = (float)angle_radians(dx, dy);
00173 }
00174 }
00175 }
00176
00177
00178
00179
00180
00181
00182
00183 double angle_radians(double x, double y)
00184 {
00185 double xu, yu, ang;
00186
00187 xu = fabs(x);
00188 yu = fabs(y);
00189
00190 if((xu == 0) && (yu == 0)) return(0);
00191
00192 ang = atan(yu/xu);
00193
00194 if(x >= 0){
00195 if(y >= 0) return(ang);
00196 else return(2*M_PI - ang);
00197 }
00198 else{
00199 if(y >= 0) return(M_PI - ang);
00200 else return(M_PI + ang);
00201 }
00202 }
00203
00204
00205
00206
00207
00208
00209
00210
00211 void magnitude_x_y(short int *delta_x, short int *delta_y, int rows, int cols,
00212 short int **magnitude)
00213 {
00214 int r, c, pos, sq1, sq2;
00215
00216
00217
00218
00219 if((*magnitude = (short *) calloc(rows*cols, sizeof(short))) == NULL){
00220 fprintf(stderr, "Error allocating the magnitude image.\n");
00221 exit(1);
00222 }
00223
00224 for(r=0,pos=0;r<rows;r++){
00225 for(c=0;c<cols;c++,pos++){
00226 sq1 = (int)delta_x[pos] * (int)delta_x[pos];
00227 sq2 = (int)delta_y[pos] * (int)delta_y[pos];
00228 (*magnitude)[pos] = (short)(0.5 + sqrt((float)sq1 + (float)sq2));
00229 }
00230 }
00231
00232 }
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246 void derrivative_x_y(short int *smoothedim, int rows, int cols,
00247 short int **delta_x, short int **delta_y)
00248 {
00249 int r, c, pos;
00250
00251
00252
00253
00254 if(((*delta_x) = (short *) calloc(rows*cols, sizeof(short))) == NULL){
00255 fprintf(stderr, "Error allocating the delta_x image.\n");
00256 exit(1);
00257 }
00258 if(((*delta_y) = (short *) calloc(rows*cols, sizeof(short))) == NULL){
00259 fprintf(stderr, "Error allocating the delta_x image.\n");
00260 exit(1);
00261 }
00262
00263
00264
00265
00266
00267 for(r=0;r<rows;r++){
00268 pos = r * cols;
00269 (*delta_x)[pos] = smoothedim[pos+1] - smoothedim[pos];
00270 pos++;
00271 for(c=1;c<(cols-1);c++,pos++){
00272 (*delta_x)[pos] = smoothedim[pos+1] - smoothedim[pos-1];
00273 }
00274 (*delta_x)[pos] = smoothedim[pos] - smoothedim[pos-1];
00275 }
00276
00277
00278
00279
00280
00281 for(c=0;c<cols;c++){
00282 pos = c;
00283 (*delta_y)[pos] = smoothedim[pos+cols] - smoothedim[pos];
00284 pos += cols;
00285 for(r=1;r<(rows-1);r++,pos+=cols){
00286 (*delta_y)[pos] = smoothedim[pos+cols] - smoothedim[pos-cols];
00287 }
00288 (*delta_y)[pos] = smoothedim[pos] - smoothedim[pos-cols];
00289 }
00290 }
00291
00292
00293
00294
00295
00296
00297
00298 void gaussian_smooth(unsigned char *image, int rows, int cols, float sigma,
00299 short int **smoothedim)
00300 {
00301 int r, c, rr, cc,
00302 windowsize,
00303 center;
00304 float *tempim,
00305 *kernel,
00306 dot,
00307 sum;
00308
00309
00310
00311
00312 make_gaussian_kernel(sigma, &kernel, &windowsize);
00313 center = windowsize / 2;
00314
00315
00316
00317
00318 if((tempim = (float *) calloc(rows*cols, sizeof(float))) == NULL){
00319 fprintf(stderr, "Error allocating the buffer image.\n");
00320 exit(1);
00321 }
00322 if(((*smoothedim) = (short int *) calloc(rows*cols,
00323 sizeof(short int))) == NULL){
00324 fprintf(stderr, "Error allocating the smoothed image.\n");
00325 exit(1);
00326 }
00327
00328
00329
00330
00331 for(r=0;r<rows;r++){
00332 for(c=0;c<cols;c++){
00333 dot = 0.0;
00334 sum = 0.0;
00335 for(cc=(-center);cc<=center;cc++){
00336 if(((c+cc) >= 0) && ((c+cc) < cols)){
00337 dot += (float)image[r*cols+(c+cc)] * kernel[center+cc];
00338 sum += kernel[center+cc];
00339 }
00340 }
00341 tempim[r*cols+c] = dot/sum;
00342 }
00343 }
00344
00345
00346
00347
00348 for(c=0;c<cols;c++){
00349 for(r=0;r<rows;r++){
00350 sum = 0.0;
00351 dot = 0.0;
00352 for(rr=(-center);rr<=center;rr++){
00353 if(((r+rr) >= 0) && ((r+rr) < rows)){
00354 dot += tempim[(r+rr)*cols+c] * kernel[center+rr];
00355 sum += kernel[center+rr];
00356 }
00357 }
00358 (*smoothedim)[r*cols+c] = (short int)(dot*BOOSTBLURFACTOR/sum + 0.5);
00359 }
00360 }
00361
00362 free(tempim);
00363 free(kernel);
00364 }
00365
00366
00367
00368
00369
00370
00371
00372 void make_gaussian_kernel(float sigma, float **kernel, int *windowsize)
00373 {
00374 int i, center;
00375 float x, fx, sum=0.0;
00376
00377 *windowsize = int(1 + 2 * ceil(2.5 * sigma));
00378 center = (*windowsize) / 2;
00379
00380 if((*kernel = (float *) calloc((*windowsize), sizeof(float))) == NULL){
00381 fprintf(stderr, "Error callocing the gaussian kernel array.\n");
00382 exit(1);
00383 }
00384
00385 for(i=0;i<(*windowsize);i++){
00386 x = (float)(i - center);
00387 fx = pow(2.71828, -0.5*x*x/(sigma*sigma)) / (sigma * sqrt(6.2831853));
00388 (*kernel)[i] = fx;
00389 sum += fx;
00390 }
00391
00392 for(i=0;i<(*windowsize);i++) (*kernel)[i] /= sum;
00393
00394 }
00395
00396
00397 #endif