|
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 #ifndef __MORPHOLOGICALFILTER_H__ 00023 #define __MORPHOLOGICALFILTER_H__ 00024 00025 namespace degate { 00026 00027 /** 00028 * Policy class for image erosion. 00029 * This policy class can be used for any single channel image. Pixel values 00030 * evaluate to 0 if they are <= 0 and evaluated to 1 if they are > 0. 00031 */ 00032 template<typename ImageType, typename PixelType> 00033 struct ErodeImagePolicy { 00034 00035 static inline PixelType calculate(std::tr1::shared_ptr<ImageType> src, 00036 unsigned int x, unsigned int y, 00037 unsigned int min_x, 00038 unsigned int max_x, 00039 unsigned int min_y, 00040 unsigned int max_y, 00041 unsigned int erosion_threshold) { 00042 00043 assert(min_x < max_x && min_y < max_y); 00044 assert(min_x < src->get_width()); 00045 assert(max_x < src->get_width()); 00046 assert(min_y < src->get_height()); 00047 assert(max_y < src->get_height()); 00048 00049 unsigned int i = 0; 00050 00051 for(unsigned int _y = min_y; _y < max_y; _y++) 00052 for(unsigned int _x = min_x; _x < max_x; _x++) 00053 if(src->get_pixel(_x, _y) > 0) i++; 00054 00055 return i <= erosion_threshold ? 0 : src->get_pixel(x, y); 00056 } 00057 }; 00058 00059 00060 /** 00061 * Filter an image with an erosion filter. 00062 */ 00063 00064 template<typename ImageTypeDst, typename ImageTypeSrc> 00065 void erode_image(std::tr1::shared_ptr<ImageTypeDst> dst, 00066 std::tr1::shared_ptr<ImageTypeSrc> src, 00067 unsigned int kernel_width = 3, 00068 unsigned int erosion_threshold = 3) { 00069 00070 filter_image<ImageTypeDst, ImageTypeSrc, 00071 ErodeImagePolicy<ImageTypeSrc, typename ImageTypeSrc::pixel_type> > 00072 (dst, src, kernel_width, erosion_threshold); 00073 } 00074 00075 00076 /** 00077 * Policy class for image dilation. 00078 * This policy class can be used for any single channel image. Pixel values 00079 * evaluate to 0 if they are <= 0 and evaluated to 1 if they are > 0. 00080 */ 00081 template<typename ImageType, typename PixelType> 00082 struct DilateImagePolicy { 00083 00084 static inline PixelType calculate(std::tr1::shared_ptr<ImageType> src, 00085 unsigned int x, unsigned int y, 00086 unsigned int min_x, 00087 unsigned int max_x, 00088 unsigned int min_y, 00089 unsigned int max_y, 00090 unsigned int dilation_threshold) { 00091 00092 assert(min_x < max_x && min_y < max_y); 00093 assert(min_x < src->get_width()); 00094 assert(max_x < src->get_width()); 00095 assert(min_y < src->get_height()); 00096 assert(max_y < src->get_height()); 00097 00098 unsigned int i = 0; 00099 00100 for(unsigned int _y = min_y; _y < max_y; _y++) 00101 for(unsigned int _x = min_x; _x < max_x; _x++) 00102 if(src->get_pixel(_x, _y) > 0) i++; 00103 return i >= dilation_threshold ? 1 : src->get_pixel(x, y); 00104 } 00105 }; 00106 00107 00108 /** 00109 * Filter an image with an erosion filter. 00110 */ 00111 00112 template<typename ImageTypeDst, typename ImageTypeSrc> 00113 void dilate_image(std::tr1::shared_ptr<ImageTypeDst> dst, 00114 std::tr1::shared_ptr<ImageTypeSrc> src, 00115 unsigned int kernel_width = 3, 00116 unsigned int dilation_threshold = 3) { 00117 00118 filter_image<ImageTypeDst, ImageTypeSrc, 00119 DilateImagePolicy<ImageTypeSrc, typename ImageTypeSrc::pixel_type> > 00120 (dst, src, kernel_width, dilation_threshold); 00121 } 00122 00123 00124 /** 00125 * Morphological open. 00126 */ 00127 template<typename ImageTypeDst, typename ImageTypeSrc> 00128 void morphological_open(std::tr1::shared_ptr<ImageTypeDst> dst, 00129 std::tr1::shared_ptr<ImageTypeSrc> src, 00130 unsigned int kernel_width = 3, 00131 unsigned int threshold_dilate = 1, 00132 unsigned int threshold_erode = 3) { 00133 00134 filter_image<ImageTypeDst, ImageTypeSrc, 00135 ErodeImagePolicy<ImageTypeSrc, typename ImageTypeSrc::pixel_type> >(dst, src, kernel_width, threshold_erode); 00136 00137 filter_image<ImageTypeDst, ImageTypeSrc, 00138 DilateImagePolicy<ImageTypeSrc, typename ImageTypeSrc::pixel_type> >(dst, src, kernel_width, threshold_dilate); 00139 } 00140 00141 00142 /** 00143 * Morphological close. 00144 */ 00145 template<typename ImageTypeDst, typename ImageTypeSrc> 00146 void morphological_close(std::tr1::shared_ptr<ImageTypeDst> dst, 00147 std::tr1::shared_ptr<ImageTypeSrc> src, 00148 unsigned int kernel_width = 3, 00149 unsigned int threshold_dilate = 1, 00150 unsigned int threshold_erode = 3) { 00151 00152 filter_image<ImageTypeDst, ImageTypeSrc, 00153 DilateImagePolicy<ImageTypeSrc, typename ImageTypeSrc::pixel_type> >(dst, src, kernel_width, threshold_dilate); 00154 00155 filter_image<ImageTypeDst, ImageTypeSrc, 00156 ErodeImagePolicy<ImageTypeSrc, typename ImageTypeSrc::pixel_type> >(dst, src, kernel_width, threshold_erode); 00157 00158 } 00159 00160 00161 /** 00162 * Helper function for the Zhang-Suen-Thinning. 00163 * @param img The image. 00164 * @param condition_switch If true, the first condition set is checked. If false, 00165 * the second condition set is checked. 00166 */ 00167 template<typename ImageType> 00168 bool zhang_suen_thinning_iteration(std::tr1::shared_ptr<ImageType> img, 00169 bool condition_switch) { 00170 assert_is_single_channel_image<ImageType>(); 00171 00172 bool running = false; 00173 unsigned int x, y; 00174 00175 for(y = 1; y < img->get_height() - 1; y++) { 00176 for(x = 1; x < img->get_width() - 1; x++) { 00177 unsigned int 00178 p1 = img->get_pixel(x, y) > 0 ? 1 : 0; 00179 00180 if(p1 > 0) { 00181 unsigned int 00182 p2 = img->get_pixel(x, y-1) > 0 ? 1 : 0, 00183 p3 = img->get_pixel(x+1, y-1) > 0 ? 1 : 0, 00184 p4 = img->get_pixel(x+1, y) > 0 ? 1 : 0, 00185 p5 = img->get_pixel(x+1, y+1) > 0 ? 1 : 0, 00186 p6 = img->get_pixel(x, y+1) > 0 ? 1 : 0, 00187 p7 = img->get_pixel(x-1, y+1) > 0 ? 1 : 0, 00188 p8 = img->get_pixel(x-1, y) > 0 ? 1 : 0, 00189 p9 = img->get_pixel(x-1, y-1)> 0 ? 1 : 0; 00190 00191 unsigned int connectivity = 00192 (p2 == 0 && p3 == 1 ? 1 : 0) + 00193 (p3 == 0 && p4 == 1 ? 1 : 0) + 00194 (p4 == 0 && p5 == 1 ? 1 : 0) + 00195 (p5 == 0 && p6 == 1 ? 1 : 0) + 00196 (p6 == 0 && p7 == 1 ? 1 : 0) + 00197 (p7 == 0 && p8 == 1 ? 1 : 0) + 00198 (p8 == 0 && p9 == 1 ? 1 : 0) + 00199 (p9 == 0 && p2 == 1 ? 1 : 0); 00200 00201 unsigned int non_zero_neighbors = p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9; 00202 00203 00204 if(2 <= non_zero_neighbors && non_zero_neighbors <= 6 && 00205 connectivity == 1) { 00206 00207 if(condition_switch == true) { 00208 00209 if(p2 * p4 * p6 == 0 && p4 * p6 * p8 == 0) { 00210 img->set_pixel(x, y, 0); 00211 running = true; 00212 } 00213 } 00214 else { 00215 if(p2 * p4 * p8 == 0 && p2 * p6 * p8 == 0) { 00216 img->set_pixel(x, y, 0); 00217 running = true; 00218 } 00219 } 00220 } 00221 } 00222 00223 } 00224 } 00225 00226 return running; 00227 } 00228 00229 /** 00230 * Zhang-Suen-Thinning of an image. 00231 */ 00232 template<typename ImageType> 00233 void thinning(std::tr1::shared_ptr<ImageType> img) { 00234 assert_is_single_channel_image<ImageType>(); 00235 00236 bool running = true; 00237 00238 do { 00239 running = zhang_suen_thinning_iteration(img, true); 00240 running = zhang_suen_thinning_iteration(img, false); 00241 }while(running); 00242 00243 } 00244 00245 00246 } 00247 #endif
1.7.4