#define PI 3.141592654 #include #include "common.h" typedef struct { int gradient; int direction; } edge_info; /* Function to return the gradient image */ Image_data *GetGradientImage(Image_data *piData) { long i, width, height, numpixels; double dx, dy; Image_data *pproData; width = piData->n_cols; height = piData->n_rows; numpixels = width * height; /* ----------- Memory allocation stuff ------------- */ pproData = malloc(sizeof(Image_data)); pproData->image_G_ptr = malloc(numpixels); pproData->n_cols = piData->n_cols; pproData->n_rows = piData->n_rows; lstrcpy(pproData->filename, "Gradient Image"); /* ------------------------------------------------- */ /* Loop through all pixels and apply sobel operator */ for (i = width + 1; i < numpixels - width - 1; i++) { /* Apply the Sobel operator */ dx = (piData->image_G_ptr[i-1]*-2 + piData->image_G_ptr[i+1]*2 + piData->image_G_ptr[i-width-1]*-1 + piData->image_G_ptr[i-width+1]*1 + piData->image_G_ptr[i+width-1]*-1 + piData->image_G_ptr[i+width+1]*1) / 8.0; dy = (piData->image_G_ptr[i-width]*2 + piData->image_G_ptr[i+width]*-2 + piData->image_G_ptr[i-width-1]*1 + piData->image_G_ptr[i-width+1]*1 + piData->image_G_ptr[i+width-1]*-1 + piData->image_G_ptr[i+width+1]*-1) / 8.0; pproData->image_G_ptr[i] = (int)sqrt(dx*dx + dy*dy); } return pproData; } /* Function to return both gradient and direction info */ edge_info *GetGradientDirectionImage(Image_data *piData) { long i, width, height, numpixels; double dx, dy, dir; edge_info *edge; width = piData->n_cols; height = piData->n_rows; numpixels = width * height; edge = malloc(numpixels * sizeof(edge_info)); /* Loop through all pixels and apply the Sobel operator */ for (i = width + 1; i < numpixels - width - 1; i++) { /* Apply the Sobel operator */ dx = (piData->image_G_ptr[i-1]*-2 + piData->image_G_ptr[i+1]*2 + piData->image_G_ptr[i-width-1]*-1 + piData->image_G_ptr[i-width+1]*1 + piData->image_G_ptr[i+width-1]*-1 + piData->image_G_ptr[i+width+1]*1) / 8.0; dy = (piData->image_G_ptr[i-width]*2 + piData->image_G_ptr[i+width]*-2 + piData->image_G_ptr[i-width-1]*1 + piData->image_G_ptr[i-width+1]*1 + piData->image_G_ptr[i+width-1]*-1 + piData->image_G_ptr[i+width+1]*-1) / 8.0; if (dx == 0) /* Avoid divide by zero */ { if (dy == 0) dir = 0.0; else if (dy > 0) dir = PI/2.0; else dir = PI/-2.0; } else /* It's okay to compute atan() */ dir = atan2(dy, dx); edge[i].gradient = (int)sqrt(dx*dx + dy*dy); edge[i].direction = (int)(dir * 180.0/ PI); /* Converted to degress */ } return edge; } /* Function to mark edges using just the gradient information */ Image_data *FindEdgesUsingGradient(Image_data *piData, int threshold) { Image_data *pproData, *gradient; long i, numpixels; numpixels = piData->n_cols * piData->n_rows; /* ----------- Memory allocation stuff -------------- */ pproData = malloc(sizeof(Image_data)); pproData->image_G_ptr = calloc(numpixels, sizeof(unsigned char)); pproData->n_cols = piData->n_cols; pproData->n_rows = piData->n_rows; lstrcpy(pproData->filename, "Edge Image"); /* ------------------------------------------------- */ gradient = GetGradientImage(piData); /* Loop through all pixels and mark edges with gradient greater than threshold as 255 (white) */ for (i = 0; i < numpixels; i++) { if (gradient->image_G_ptr[i] > threshold) pproData->image_G_ptr[i] = 255; } /* Free up allocated memory */ free(gradient->image_G_ptr); free(gradient); return pproData; } /* Function to mark edges using gradient and direction info */ Image_data *FindEdgesUsingGradientDirection(Image_data *piData, int threshold, int direction) { Image_data *pproData; edge_info *edge; long i, numpixels; numpixels = piData->n_cols * piData->n_rows; /* ----------- Memory allocation stuff -------------- */ pproData = malloc(sizeof(Image_data)); pproData->image_G_ptr = calloc(numpixels, sizeof(unsigned char)); pproData->n_cols = piData->n_cols; pproData->n_rows = piData->n_rows; lstrcpy(pproData->filename, "Edge Image"); /* ------------------------------------------------- */ edge = GetGradientDirectionImage(piData); /* Loop through all pixels and check gradient threshold as well as direction with a +/- 10 degrees tolerance Note that user may enter any angle from -180 to +180, so we must take into account pairs like 90 and -90, 100 and -80 and so on since they lie on the same straight line... */ for (i = 0; i < numpixels; i++) { if (edge[i].gradient > threshold) if (((edge[i].direction > direction-10) && (edge[i].direction < direction+10)) || ((edge[i].direction > direction-180-10) && (edge[i].direction < direction-180+10)) || ((edge[i].direction > direction+180-10) && (edge[i].direction < direction+180+10))) pproData->image_G_ptr[i] = 255; } /* free up allocated memory */ free(edge); return pproData; }