degate  0.1.2
ZeroCrossingEdgeDetection.cc
Go to the documentation of this file.
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  Copyright 2012 Robert Nitsch
00007 
00008  Degate is free software: you can redistribute it and/or modify
00009  it under the terms of the GNU General Public License as published by
00010  the Free Software Foundation, either version 3 of the License, or
00011  any later version.
00012 
00013  Degate is distributed in the hope that it will be useful,
00014  but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  GNU General Public License for more details.
00017 
00018  You should have received a copy of the GNU General Public License
00019  along with degate. If not, see <http://www.gnu.org/licenses/>.
00020 
00021 */
00022 
00023 #include <ZeroCrossingEdgeDetection.h>
00024 #include <MorphologicalFilter.h>
00025 
00026 using namespace degate;
00027 
00028 ZeroCrossingEdgeDetection::ZeroCrossingEdgeDetection(unsigned int min_x, unsigned int max_x,
00029                                                      unsigned int min_y, unsigned int max_y,
00030                                                      unsigned int median_filter_width,
00031                                                      unsigned int blur_kernel_size,
00032                                                      double sigma,
00033                                                      unsigned int _min_d,
00034                                                      unsigned int _max_d,
00035                                                      double _edge_threshold,
00036                                                      double _zero_threshold) :
00037   EdgeDetection(min_x, max_x, min_y, max_y, median_filter_width, blur_kernel_size, sigma),
00038   min_d(_min_d),
00039   max_d(_max_d),
00040   edge_threshold(_edge_threshold),
00041   zero_threshold(_zero_threshold) {
00042   }
00043 
00044 TileImage_GS_DOUBLE_shptr
00045 ZeroCrossingEdgeDetection::run(ImageBase_shptr img_in,
00046                                TileImage_GS_DOUBLE_shptr probability_map) {
00047 
00048   run_edge_detection(img_in);
00049   TileImage_GS_DOUBLE_shptr edge_image = get_edge_image(probability_map);
00050   //TileImage_GS_DOUBLE_shptr edge_magnitude_image = get_edge_magnitude_image(probability_map);
00051 
00052   TileImage_GS_DOUBLE_shptr zero_cross_img =
00053     analyze_edge_image(edge_image, probability_map, min_d, max_d);
00054 
00055   TileImage_GS_DOUBLE_shptr zero_cross_img2(new TileImage_GS_DOUBLE(get_width(), get_height()));
00056 
00057   morphological_close<TileImage_GS_DOUBLE, TileImage_GS_DOUBLE>
00058     (zero_cross_img2, zero_cross_img, 3, 1, 3);
00059 
00060   thinning<TileImage_GS_DOUBLE>(zero_cross_img2);
00061 
00062   return zero_cross_img2;
00063 }
00064 
00065 TileImage_GS_DOUBLE_shptr ZeroCrossingEdgeDetection::run(ImageBase_shptr img_in,
00066                                                          TileImage_GS_DOUBLE_shptr probability_map,
00067                                                          std::string const& directory) {
00068   set_directory(directory);
00069   assert(img_in != NULL);
00070   TileImage_GS_DOUBLE_shptr zero_cross_img = run(img_in, probability_map);
00071   assert(zero_cross_img != NULL);
00072 
00073   save_normalized_image<TileImage_GS_DOUBLE>(join_pathes(directory, "03_edge_zero_cross.tif"),
00074                                              zero_cross_img);
00075 
00076   /*
00077   overlay_result(zero_cross_img,
00078                  std::dynamic_pointer_cast<TileImage_GS_DOUBLE>(img_in),
00079                  directory);
00080   */
00081   return zero_cross_img;
00082 }
00083 
00084 
00085 bool ZeroCrossingEdgeDetection::trace(TileImage_GS_DOUBLE_shptr edge_image,
00086                                       int _x, int _y,
00087                                       int inc_x, int inc_y,
00088                                       int * start_x, int * stop_x,
00089                                       int * start_y, int * stop_y,
00090                                       double * mag,
00091                                       double edge_threshold,
00092                                       double zero_threshold,
00093                                       unsigned int min_d, unsigned int max_d) {
00094 
00095   if(start_x == NULL || start_y == NULL ||
00096      stop_x == NULL || stop_y == NULL || mag == NULL) return false;
00097 
00098   enum STATE {BEFORE, POS_EDGE, NEG_EDGE, END};
00099   STATE s = BEFORE;
00100   int x = _x, y = _y;
00101   double max_pix = 0, min_pix = 0;
00102 
00103   while(s != END) {
00104     double p = edge_image->get_pixel(x, y);
00105 
00106     if(s == BEFORE && p >= edge_threshold) {
00107       max_pix = p;
00108       *start_x = x;
00109       *start_y = y;
00110       s = POS_EDGE;
00111     }
00112 
00113     else if(s == POS_EDGE) {
00114       if(p > max_pix) {
00115         *start_x = x;
00116         *start_y = y;
00117         max_pix = p;
00118       }
00119       if(p <= -edge_threshold) {
00120         *stop_x = x;
00121         *stop_y = y;
00122         min_pix = p;
00123         s = NEG_EDGE;
00124       }
00125     }
00126     else if(s == NEG_EDGE) {
00127       if(p < min_pix) {
00128         min_pix = p;
00129         *stop_x = x;
00130         *stop_y = y;
00131       }
00132       if(p >= 0 ||
00133          x > *stop_x || y > *stop_y) { // that is at least one step beyond the maximum
00134 
00135         unsigned int
00136           d_x = abs(*stop_x - *start_x),
00137           d_y = abs(*stop_y - *start_y);
00138 
00139 
00140         if( !((d_x > min_d && d_x < max_d) ||
00141               (d_y > min_d && d_y < max_d))) return false;
00142 
00143         s = END;                //
00144         *mag = sqrt(pow(max_pix,2) + pow(min_pix, 2));
00145 
00146         double p_center = edge_image->get_pixel(*start_x + (*stop_x - *start_x)/2,
00147                                                 *start_y + (*stop_y - *start_y)/2);
00148 
00149         return fabs(p_center) < zero_threshold;
00150 
00151       }
00152     }
00153     x += inc_x;
00154     y += inc_y;
00155     
00156     assert(x >= 0);
00157     assert(y >= 0);
00158     
00159     if(unsigned(x) >= edge_image->get_width() ||
00160        unsigned(y) >= edge_image->get_height() ||
00161        x == 0 || y == 0) s = END;
00162   }
00163   return false;
00164 }
00165 
00166 
00167 TileImage_GS_DOUBLE_shptr
00168 ZeroCrossingEdgeDetection::analyze_edge_image(TileImage_GS_DOUBLE_shptr edge_image,
00169                                               TileImage_GS_DOUBLE_shptr probability_map,
00170                                               unsigned int min_d, unsigned int max_d) {
00171   int start_x = 0, start_y = 0, stop_x = 0, stop_y = 0;
00172   unsigned x, y;
00173   double mag = 0;
00174 
00175   normalize<TileImage_GS_DOUBLE, TileImage_GS_DOUBLE>(edge_image, edge_image, -1, 1);
00176 
00177   TileImage_GS_DOUBLE_shptr out_image(new TileImage_GS_DOUBLE(get_width(), get_height()));
00178 
00179   for(y = get_border() ; y < edge_image->get_height() - get_border(); y++) {
00180     for(x = get_border(); x < edge_image->get_width() - get_border();) {
00181 
00182       if(trace(edge_image, x, y, 1, 0,
00183                &start_x, &stop_x, &start_y, &stop_y, &mag,
00184                edge_threshold, zero_threshold,
00185                min_d, max_d)) {
00186         out_image->set_pixel(start_x + (stop_x - start_x)/2, y, mag);
00187         x += (stop_x > start_x + 1) ? stop_x - start_x - 1 : stop_x - start_x;
00188       }
00189       else x++;
00190     }
00191   }
00192 
00193   for(x = get_border(); x < edge_image->get_width() - get_border(); x++) {
00194     for(y = get_border(); y < edge_image->get_height() - get_border();) {
00195       if(trace(edge_image, x, y, 0, 1,
00196                &start_x, &stop_x, &start_y, &stop_y, &mag,
00197                edge_threshold, zero_threshold, min_d, max_d)) {
00198         out_image->set_pixel(x, start_y + (stop_y - start_y)/2, mag);
00199         y += (stop_y > start_y + 1) ? stop_y - start_y -1 : stop_y - start_y;
00200       }
00201       else y++;
00202     }
00203   }
00204 
00205 
00206       /*
00207       for(x = get_border(); x < edge_image->get_width() - get_border(); x++) {
00208         for(y = get_border(); y < edge_image->get_height() - get_border(); y++) {
00209           if(trace(edge_image, x, y, 1, 1,
00210                    &start_x, &stop_x, &start_y, &stop_y, &mag,
00211                    edge_threshold, zero_threshold, sqrt(2*min_d*min_d), sqrt(2*max_d*max_d))) {
00212             int
00213               p_x = start_x + (stop_x - start_x)/2,
00214               p_y = start_y + (stop_y - start_y)/2;
00215             if(p_x >= 0 && p_y >= 0 && p_x < out_image->get_width() && p_y < out_image->get_height())
00216               out_image->set_pixel(p_x, p_y, mag);
00217           }
00218         }
00219       }
00220 
00221 
00222       for(x = get_border(); x < edge_image->get_width() - get_border(); x++) {
00223         for(y = get_border(); y < edge_image->get_height() - get_border(); y++) {
00224           if(trace(edge_image, x, y, -1, 1,
00225                    &start_x, &stop_x, &start_y, &stop_y, &mag,
00226                    edge_threshold, zero_threshold, sqrt(2*min_d*min_d), sqrt(2*max_d*max_d))) {
00227             int
00228               p_x = start_x + (stop_x - start_x)/2,
00229               p_y = start_y + (stop_y - start_y)/2;
00230             if(p_x >= 0 && p_y >= 0 && p_x < out_image->get_width() && p_y < out_image->get_height())
00231               out_image->set_pixel(p_x, p_y, mag);
00232           }
00233         }
00234       }
00235       */
00236 
00237   return out_image;
00238 }
00239 
00240 void ZeroCrossingEdgeDetection::overlay_result(TileImage_GS_DOUBLE_shptr zc,
00241                                                TileImage_GS_DOUBLE_shptr bg,
00242                                                //TileImage_RGBA_shptr bg,
00243                                                std::string const& directory) const {
00244 
00245   assert(bg != NULL && zc != NULL);
00246 
00247   if(bg != NULL && zc != NULL) {
00248     for(unsigned int y = 0; y < get_height(); y++)
00249       for(unsigned int x = 0; x < get_width(); x++) {
00250         if(zc->get_pixel(x, y) > 0)
00251           bg->set_pixel(x, y, -1);
00252       }
00253     //save_image<TileImage_RGBA>(join_pathes(directory, "overlay.tif"),  bg);
00254     save_normalized_image<TileImage_GS_DOUBLE>(join_pathes(directory, "overlay.tif"),  bg);
00255   }
00256 }
00257