/* This file tests all the edge detection algorithms implemented in edge_detectors.c. It also leads with input/output and with the parameters handling. Copyright (c) 2011-2013, Haldo Sponton Copyright (c) 2011-2013, Juan Cardelino This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include "classic_edge_detectors.h" // edge detection algorithms #include "io_png.h" // image input/output /* Display help function */ void displayhelp(void) { printf("Usage: edges [options] input.png\n" " -r Roberts' algorithm\n" " th threshold (float in [0,1])\n" " -p Prewitt's algorithm\n" " th threshold (float in [0,1])\n" " -s Sobel's algorithm\n" " th threshold (float in [0,1])\n" " -m Marr-Hildreth algorithm (Gaussian)\n" " sigma std dev of Gaussian kernel\n" " n size of Gaussian kernel (int)\n" " th threshold (float in [0,1])\n" " -l Marr-Hildreth algorithm (LoG)\n" " sigma std dev of LoG kernel\n" " n size of LoG kernel (int)\n" " th threshold (float in [0,1])\n" " -h Haralick's algorithm\n" " th threshold (float in [0,1])\n" " -H Display this help\n" "\nMore than one option can be used together. " "Output is written to image files.\n"); } /* Main function */ int main(int argc, char *argv[]) { /* Start */ printf("A review of classic edge detection algorithms\n"); printf("Haldo Sponton & Juan Cardelino, IPOL 2013\n\n"); /* Options and parameters handling */ int argc_sobel = 0; // int argc_prewitt = 0; // int argc_roberts = 0; // indexes in argv[] int argc_mh = 0; // int argc_mhl = 0; // int argc_haralick = 0; // int padding_method = 1; // Reflection of image boundary. Hard-coded. // Can be changed to 0 (zero-padding) for(int n = 1; n %s. Valid" " options are -r, -p, -s, -h, -m and -l" " (-H for help).\n", argv[n]); exit(1); break; } /* Error message if an option is the last input parameter or if the next parameter after an option is another option */ if( n==argc-1 ) { printf("Error: Missing parameter(s) for %s option.\n", argv[n]); exit(1); break; } else if( argv[n+1][0]=='-' ) { printf("Error: Missing parameter(s) for %s option.\n", argv[n]); exit(1); break; } /* In the case of -m and -l, three parameters are needed */ if( (argv[n][1]=='m') || (argv[n][1]=='l') ) { if( n+3>argc-1 ) { printf("Error: Missing parameter(s) for %s option.\n", argv[n]); exit(1); break; } else if( (argv[n+2][0]=='-') || (argv[n+3][0]=='-') ) { printf("Error: Missing parameter(s) for %s option.\n", argv[n]); exit(1); break; } } default: break; } } /* Check for total number of parameters */ int nparam = 2; if(argc_roberts!=0) nparam+=2; if(argc_prewitt!=0) nparam+=2; if(argc_sobel!=0) nparam+=2; if(argc_mh!=0) nparam+=4; if(argc_mhl!=0) nparam+=4; if(argc_haralick!=0) nparam+=2; if(nparam!=argc) { printf("Error: Wrong number of arguments (%d instead of %d)\n" "Usage: %s [options] input.png\n" "For help type %s -H.\n",argc-1,nparam-1,argv[0],argv[0]); exit(1); } /* Load input image */ size_t w, h; float *im = io_png_read_f32_gray(argv[argc-1], &w, &h); printf("Input image: %s\n",argv[argc-1]); printf("Size: %zd x %zd\n\n",w,h); /* Roberts edge detection algorithm */ if(argc_roberts!=0) { float th_roberts = atof(argv[argc_roberts+1]); // threshold printf("Running Roberts, threshold=%.2f",th_roberts); float *im_roberts = edges_roberts(im, w, h, th_roberts, padding_method); io_png_write_f32("out_roberts.png", im_roberts, w, h, 1); printf(" output: out_roberts.png\n"); free(im_roberts); } /* Prewitt edge detection algorithm */ if(argc_prewitt!=0) { float th_prewitt = atof(argv[argc_prewitt+1]); // threshold printf("Running Prewitt, threshold=%.2f",th_prewitt); float *im_prewitt = edges_prewitt(im, w, h, th_prewitt, padding_method); io_png_write_f32("out_prewitt.png", im_prewitt, w, h, 1); printf(" output: out_prewitt.png\n"); free(im_prewitt); } /* Sobel edge detection algorithm */ if(argc_sobel!=0) { float th_sobel = atof(argv[argc_sobel+1]); // threshold printf("Running Sobel, threshold=%.2f",th_sobel); float *im_sobel = edges_sobel(im, w, h, th_sobel, padding_method); io_png_write_f32("out_sobel.png", im_sobel, w, h, 1); printf(" output: out_sobel.png\n"); free(im_sobel); } /* Marr-Hildreth (Gaussian) edge detection algorithm */ if(argc_mh!=0) { float sigma_m = atof(argv[argc_mh+1]); // Gaussian kernel's std dev. int n_m = atoi(argv[argc_mh+2]); // kernel size float tzc_m = atof(argv[argc_mh+3]); // threshold for zero-crossing printf("Running Marr-Hildreth (Gaussian), sigma=%.2f, N=%d, TZC=%.2f", sigma_m, n_m, tzc_m); float *im_mh = edges_mh(im, w, h, sigma_m, n_m, tzc_m, padding_method); io_png_write_f32("out_mh.png", im_mh, w, h, 1); printf(" output: out_mh.png\n"); free(im_mh); } /* Marr-Hildreth (LoG) edge detection algorithm */ if(argc_mhl!=0) { float sigma_l = atof(argv[argc_mhl+1]); // Gaussian kernel's std dev. int n_l = atoi(argv[argc_mhl+2]); // kernel size float tzc_l = atof(argv[argc_mhl+3]); // threshold for zero-crossing printf("Running Marr-Hildreth (LoG), sigma=%.2f, N=%d, TZC=%.2f", sigma_l, n_l, tzc_l); float *im_mhl = edges_mh_log(im, w, h, sigma_l, n_l, tzc_l, padding_method); io_png_write_f32("out_mhl.png", im_mhl, w, h, 1); printf(" output: out_mhl.png\n"); free(im_mhl); } /* Haralick edge detection algorithm */ if(argc_haralick!=0) { float rhozero = atof(argv[argc_haralick+1]); // threshold printf("Running Haralick, rhozero=%.2f",rhozero); float *im_haralick = edges_haralick(im, w, h, rhozero, padding_method); io_png_write_f32("out_haralick.png", im_haralick, w, h, 1); printf(" output: out_haralick.png\n"); free(im_haralick); } /* Memory free */ free(im); exit(EXIT_SUCCESS); }