|
degate 0.1.1
|
00001 /* -*-c++-*- 00002 00003 This file is part of the IC reverse engineering tool degate. 00004 00005 Copyright 2008, 2009, 2010 by Martin Schobert 00006 00007 Degate is free software: you can redistribute it and/or modify 00008 it under the terms of the GNU General Public License as published by 00009 the Free Software Foundation, either version 3 of the License, or 00010 any later version. 00011 00012 Degate is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 GNU General Public License for more details. 00016 00017 You should have received a copy of the GNU General Public License 00018 along with degate. If not, see <http://www.gnu.org/licenses/>. 00019 00020 */ 00021 00022 #include <CannyEdgeDetection.h> 00023 #include <IPPipe.h> 00024 #include <IPCopy.h> 00025 #include <IPConvolve.h> 00026 #include <IPNormalize.h> 00027 #include <IPThresholding.h> 00028 #include <ImageManipulation.h> 00029 #include <IPImageWriter.h> 00030 00031 using namespace degate; 00032 00033 CannyEdgeDetection::CannyEdgeDetection(unsigned int min_x, unsigned int max_x, 00034 unsigned int min_y, unsigned int max_y, 00035 unsigned int wire_diameter, 00036 unsigned int median_filter_width, 00037 unsigned int blur_kernel_size, 00038 double sigma, 00039 double _hysteresis_min, 00040 double _hysteresis_max) : 00041 EdgeDetection(min_x, max_x, min_y, max_y, median_filter_width, blur_kernel_size, sigma), 00042 hysteresis_min(_hysteresis_min), 00043 hysteresis_max(_hysteresis_max) { 00044 } 00045 00046 CannyEdgeDetection::~CannyEdgeDetection() {} 00047 00048 00049 TileImage_GS_DOUBLE_shptr CannyEdgeDetection::run(ImageBase_shptr img_in, 00050 TileImage_GS_DOUBLE_shptr probability_map) { 00051 run_edge_detection(img_in); 00052 TileImage_GS_DOUBLE_shptr edge_image = get_edge_image(probability_map); 00053 TileImage_GS_DOUBLE_shptr edge_magnitude_image = get_edge_magnitude_image(probability_map); 00054 00055 TileImage_GS_DOUBLE_shptr sup_edge_image(new TileImage_GS_DOUBLE(get_width(), get_height())); 00056 non_maximum_supression(get_horizontal_edges(), get_vertical_edges(), 00057 edge_magnitude_image, sup_edge_image); 00058 00059 normalize<TileImage_GS_DOUBLE, TileImage_GS_DOUBLE>(sup_edge_image, sup_edge_image, 0, 1); 00060 00061 hysteresis(sup_edge_image); 00062 00063 return sup_edge_image; 00064 } 00065 00066 TileImage_GS_DOUBLE_shptr CannyEdgeDetection::run(ImageBase_shptr img_in, 00067 TileImage_GS_DOUBLE_shptr probability_map, 00068 std::string const& directory) { 00069 00070 set_directory(directory); 00071 TileImage_GS_DOUBLE_shptr sup_edge_image = run(img_in, probability_map); 00072 00073 save_normalized_image<TileImage_GS_DOUBLE>(join_pathes(directory, "06_hysteresis.tif"), 00074 sup_edge_image); 00075 00076 return sup_edge_image; 00077 } 00078 00079 00080 void CannyEdgeDetection::hysteresis(TileImage_GS_DOUBLE_shptr sup_edge_image) { 00081 unsigned int x, y; 00082 for(y = get_border(); y < sup_edge_image->get_height() - get_border(); y++) { 00083 for(x = get_border(); x < sup_edge_image->get_width() - get_border(); x++) { 00084 if(sup_edge_image->get_pixel(x, y) >= hysteresis_max) 00085 sup_edge_image->set_pixel(x, y, 1); 00086 else if(sup_edge_image->get_pixel(x, y) <= hysteresis_min) 00087 sup_edge_image->set_pixel(x, y, 0); 00088 else 00089 sup_edge_image->set_pixel(x, y, 2); 00090 } 00091 } 00092 00093 00094 bool running = true; 00095 while(running) { 00096 running = false; 00097 00098 for(y = get_border(); y < sup_edge_image->get_height() - get_border(); y++) { 00099 for(x = get_border(); x < sup_edge_image->get_width() - get_border(); x++) { 00100 if(sup_edge_image->get_pixel(x, y) == 2 && 00101 ( sup_edge_image->get_pixel(x-1, y-1) == 1 || 00102 sup_edge_image->get_pixel(x , y-1) == 1 || 00103 sup_edge_image->get_pixel(x+1, y-1) == 1 || 00104 00105 sup_edge_image->get_pixel(x-1, y) == 1 || 00106 sup_edge_image->get_pixel(x+1, y) == 1 || 00107 00108 sup_edge_image->get_pixel(x-1, y+1) == 1 || 00109 sup_edge_image->get_pixel(x , y+1) == 1 || 00110 sup_edge_image->get_pixel(x+1, y+1) == 1)) { 00111 00112 sup_edge_image->set_pixel(x, y, 1); 00113 running = true; 00114 } 00115 } 00116 } 00117 } 00118 00119 } 00120 00121 00122 void CannyEdgeDetection::non_maximum_supression(TileImage_GS_DOUBLE_shptr horizontal_edges, 00123 TileImage_GS_DOUBLE_shptr vertical_edges, 00124 TileImage_GS_DOUBLE_shptr edge_image, 00125 TileImage_GS_DOUBLE_shptr sup_edge_image) { 00126 00127 for(unsigned int y = get_border(); y < edge_image->get_height() - get_border(); y++) { 00128 for(unsigned int x = get_border(); x < edge_image->get_width() - get_border(); x++) { 00129 00130 int gradient_direction = get_gradient_direction(horizontal_edges, 00131 vertical_edges, edge_image, x, y); 00132 00133 gs_double_pixel_t pix = edge_image->get_pixel(x, y); 00134 if(pix > 0 && gradient_direction == -1) 00135 sup_edge_image->set_pixel(x, y, pix); 00136 00137 } 00138 } 00139 00140 if(has_directory()) 00141 save_normalized_image<TileImage_GS_DOUBLE>(join_pathes(get_directory(), 00142 "04_non_max_suppression.tif"), 00143 sup_edge_image); 00144 } 00145 00146 00147 00148 // returns the direction in degrees 00149 int CannyEdgeDetection::get_gradient_direction(TileImage_GS_DOUBLE_shptr horizontal_edges, 00150 TileImage_GS_DOUBLE_shptr vertical_edges, 00151 TileImage_GS_DOUBLE_shptr edge_mag_image, 00152 unsigned int x, unsigned int y) { 00153 double tangent = 5; 00154 // determine gradient direction 00155 if(vertical_edges->get_pixel(x, y) != 0) 00156 tangent = horizontal_edges->get_pixel(x, y) / vertical_edges->get_pixel(x, y); 00157 00158 double 00159 nw = edge_mag_image->get_pixel(x - 1, y - 1), 00160 n = edge_mag_image->get_pixel(x , y - 1), 00161 ne = edge_mag_image->get_pixel(x + 1, y - 1), 00162 w = edge_mag_image->get_pixel(x - 1, y ), 00163 e = edge_mag_image->get_pixel(x + 1, y ), 00164 sw = edge_mag_image->get_pixel(x - 1, y + 1), 00165 s = edge_mag_image->get_pixel(x , y + 1), 00166 se = edge_mag_image->get_pixel(x + 1, y + 1), 00167 curr = edge_mag_image->get_pixel(x, y); 00168 00169 // comment specifies gradient 00170 if(fabs(tangent) <= 0.4142) { // - 00171 if(curr < w && curr < nw && curr < sw) return 180; 00172 if(curr < e && curr < ne && curr < se) return 90; 00173 if(curr < w) return 180; 00174 if(curr < e) return 90; 00175 } 00176 if(0.4142 < tangent && tangent <= 2.4142) { // / 00177 if(curr < ne && curr < n && curr < e) return 45; 00178 if(curr < sw && curr < s && curr < w) return 225; 00179 if(curr < ne) return 45; 00180 if(curr < sw) return 225; 00181 } 00182 if(fabs(tangent) > 2.4142) { // | 00183 if(curr < n && curr < nw && curr < ne) return 90; 00184 if(curr < s && curr < sw && curr < se) return 270; 00185 if(curr < n) return 90; 00186 if(curr < s) return 270; 00187 } 00188 if(-2.4142 < tangent && tangent <= -0.4142) { // 00189 if(curr < nw && curr < n && curr < w) return 135; 00190 if(curr < se && curr < s && curr < e) return 315; 00191 if(curr < nw) return 135; 00192 if(curr < se) return 315; 00193 } 00194 return -1; 00195 } 00196
1.7.4