degate 0.1.1
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 
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 <ZeroCrossingEdgeDetection.h>
00023 #include <MorphologicalFilter.h>
00024 
00025 using namespace degate;
00026 
00027 ZeroCrossingEdgeDetection::ZeroCrossingEdgeDetection(unsigned int min_x, unsigned int max_x,
00028                                                      unsigned int min_y, unsigned int max_y,
00029                                                      unsigned int median_filter_width,
00030                                                      unsigned int blur_kernel_size,
00031                                                      double sigma,
00032                                                      unsigned int _min_d,
00033                                                      unsigned int _max_d,
00034                                                      double _edge_threshold,
00035                                                      double _zero_threshold) :
00036   EdgeDetection(min_x, max_x, min_y, max_y, median_filter_width, blur_kernel_size, sigma),
00037   min_d(_min_d),
00038   max_d(_max_d),
00039   edge_threshold(_edge_threshold),
00040   zero_threshold(_zero_threshold) {
00041   }
00042 
00043 TileImage_GS_DOUBLE_shptr
00044 ZeroCrossingEdgeDetection::run(ImageBase_shptr img_in,
00045                                TileImage_GS_DOUBLE_shptr probability_map) {
00046 
00047   run_edge_detection(img_in);
00048   TileImage_GS_DOUBLE_shptr edge_image = get_edge_image(probability_map);
00049   //TileImage_GS_DOUBLE_shptr edge_magnitude_image = get_edge_magnitude_image(probability_map);
00050 
00051   TileImage_GS_DOUBLE_shptr zero_cross_img =
00052     analyze_edge_image(edge_image, probability_map, min_d, max_d);
00053 
00054   TileImage_GS_DOUBLE_shptr zero_cross_img2(new TileImage_GS_DOUBLE(get_width(), get_height()));
00055 
00056   morphological_close<TileImage_GS_DOUBLE, TileImage_GS_DOUBLE>
00057     (zero_cross_img2, zero_cross_img, 3, 1, 3);
00058 
00059   thinning<TileImage_GS_DOUBLE>(zero_cross_img2);
00060 
00061   return zero_cross_img2;
00062 }
00063 
00064 TileImage_GS_DOUBLE_shptr ZeroCrossingEdgeDetection::run(ImageBase_shptr img_in,
00065                                                          TileImage_GS_DOUBLE_shptr probability_map,
00066                                                          std::string const& directory) {
00067   set_directory(directory);
00068   assert(img_in != NULL);
00069   TileImage_GS_DOUBLE_shptr zero_cross_img = run(img_in, probability_map);
00070   assert(zero_cross_img != NULL);
00071 
00072   save_normalized_image<TileImage_GS_DOUBLE>(join_pathes(directory, "03_edge_zero_cross.tif"),
00073                                              zero_cross_img);
00074 
00075   /*
00076   overlay_result(zero_cross_img,
00077                  std::tr1::dynamic_pointer_cast<TileImage_GS_DOUBLE>(img_in),
00078                  directory);
00079   */
00080   return zero_cross_img;
00081 }
00082 
00083 
00084 bool ZeroCrossingEdgeDetection::trace(TileImage_GS_DOUBLE_shptr edge_image,
00085                                       int _x, int _y,
00086                                       int inc_x, int inc_y,
00087                                       int * start_x, int * stop_x,
00088                                       int * start_y, int * stop_y,
00089                                       double * mag,
00090                                       double edge_threshold,
00091                                       double zero_threshold,
00092                                       unsigned int min_d, unsigned int max_d) {
00093 
00094   if(start_x == NULL || start_y == NULL ||
00095      stop_x == NULL || stop_y == NULL || mag == NULL) return false;
00096 
00097   enum STATE {BEFORE, POS_EDGE, NEG_EDGE, END};
00098   STATE s = BEFORE;
00099   int x = _x, y = _y;
00100   double max_pix = 0, min_pix = 0;
00101 
00102   while(s != END) {
00103     double p = edge_image->get_pixel(x, y);
00104 
00105     if(s == BEFORE && p >= edge_threshold) {
00106       max_pix = p;
00107       *start_x = x;
00108       *start_y = y;
00109       s = POS_EDGE;
00110     }
00111 
00112     else if(s == POS_EDGE) {
00113       if(p > max_pix) {
00114         *start_x = x;
00115         *start_y = y;
00116         max_pix = p;
00117       }
00118       if(p <= -edge_threshold) {
00119         *stop_x = x;
00120         *stop_y = y;
00121         min_pix = p;
00122         s = NEG_EDGE;
00123       }
00124     }
00125     else if(s == NEG_EDGE) {
00126       if(p < min_pix) {
00127         min_pix = p;
00128         *stop_x = x;
00129         *stop_y = y;
00130       }
00131       if(p >= 0 ||
00132          x > *stop_x || y > *stop_y) { // that is at least one step beyond the maximum
00133 
00134         unsigned int
00135           d_x = abs(*stop_x - *start_x),
00136           d_y = abs(*stop_y - *start_y);
00137 
00138 
00139         if( !((d_x > min_d && d_x < max_d) ||
00140               (d_y > min_d && d_y < max_d))) return false;
00141 
00142         s = END;                //
00143         *mag = sqrt(pow(max_pix,2) + pow(min_pix, 2));
00144 
00145         double p_center = edge_image->get_pixel(*start_x + (*stop_x - *start_x)/2,
00146                                                 *start_y + (*stop_y - *start_y)/2);
00147 
00148         return fabs(p_center) < zero_threshold;
00149 
00150       }
00151     }
00152     x += inc_x;
00153     y += inc_y;
00154     if(x >= edge_image->get_width() ||
00155        y >= edge_image->get_height() ||
00156        x == 0 || y == 0) s = END;
00157   }
00158   return false;
00159 }
00160 
00161 
00162 TileImage_GS_DOUBLE_shptr
00163 ZeroCrossingEdgeDetection::analyze_edge_image(TileImage_GS_DOUBLE_shptr edge_image,
00164                                               TileImage_GS_DOUBLE_shptr probability_map,
00165                                               unsigned int min_d, unsigned int max_d) {
00166   int start_x = 0, start_y = 0, stop_x = 0, stop_y = 0, x, y;
00167   double mag = 0;
00168 
00169   normalize<TileImage_GS_DOUBLE, TileImage_GS_DOUBLE>(edge_image, edge_image, -1, 1);
00170 
00171   TileImage_GS_DOUBLE_shptr out_image(new TileImage_GS_DOUBLE(get_width(), get_height()));
00172 
00173   for(y = get_border() ; y < edge_image->get_height() - get_border(); y++) {
00174     for(x = get_border(); x < edge_image->get_width() - get_border();) {
00175 
00176       if(trace(edge_image, x, y, 1, 0,
00177                &start_x, &stop_x, &start_y, &stop_y, &mag,
00178                edge_threshold, zero_threshold,
00179                min_d, max_d)) {
00180         out_image->set_pixel(start_x + (stop_x - start_x)/2, y, mag);
00181         x += (stop_x > start_x + 1) ? stop_x - start_x - 1 : stop_x - start_x;
00182       }
00183       else x++;
00184     }
00185   }
00186 
00187   for(x = get_border(); x < edge_image->get_width() - get_border(); x++) {
00188     for(y = get_border(); y < edge_image->get_height() - get_border();) {
00189       if(trace(edge_image, x, y, 0, 1,
00190                &start_x, &stop_x, &start_y, &stop_y, &mag,
00191                edge_threshold, zero_threshold, min_d, max_d)) {
00192         out_image->set_pixel(x, start_y + (stop_y - start_y)/2, mag);
00193         y += (stop_y > start_y + 1) ? stop_y - start_y -1 : stop_y - start_y;
00194       }
00195       else y++;
00196     }
00197   }
00198 
00199 
00200       /*
00201       for(x = get_border(); x < edge_image->get_width() - get_border(); x++) {
00202         for(y = get_border(); y < edge_image->get_height() - get_border(); y++) {
00203           if(trace(edge_image, x, y, 1, 1,
00204                    &start_x, &stop_x, &start_y, &stop_y, &mag,
00205                    edge_threshold, zero_threshold, sqrt(2*min_d*min_d), sqrt(2*max_d*max_d))) {
00206             int
00207               p_x = start_x + (stop_x - start_x)/2,
00208               p_y = start_y + (stop_y - start_y)/2;
00209             if(p_x >= 0 && p_y >= 0 && p_x < out_image->get_width() && p_y < out_image->get_height())
00210               out_image->set_pixel(p_x, p_y, mag);
00211           }
00212         }
00213       }
00214 
00215 
00216       for(x = get_border(); x < edge_image->get_width() - get_border(); x++) {
00217         for(y = get_border(); y < edge_image->get_height() - get_border(); y++) {
00218           if(trace(edge_image, x, y, -1, 1,
00219                    &start_x, &stop_x, &start_y, &stop_y, &mag,
00220                    edge_threshold, zero_threshold, sqrt(2*min_d*min_d), sqrt(2*max_d*max_d))) {
00221             int
00222               p_x = start_x + (stop_x - start_x)/2,
00223               p_y = start_y + (stop_y - start_y)/2;
00224             if(p_x >= 0 && p_y >= 0 && p_x < out_image->get_width() && p_y < out_image->get_height())
00225               out_image->set_pixel(p_x, p_y, mag);
00226           }
00227         }
00228       }
00229       */
00230 
00231   return out_image;
00232 }
00233 
00234 void ZeroCrossingEdgeDetection::overlay_result(TileImage_GS_DOUBLE_shptr zc,
00235                                                TileImage_GS_DOUBLE_shptr bg,
00236                                                //TileImage_RGBA_shptr bg,
00237                                                std::string const& directory) const {
00238 
00239   assert(bg != NULL && zc != NULL);
00240 
00241   if(bg != NULL && zc != NULL) {
00242     for(unsigned int y = 0; y < get_height(); y++)
00243       for(unsigned int x = 0; x < get_width(); x++) {
00244         if(zc->get_pixel(x, y) > 0)
00245           bg->set_pixel(x, y, -1);
00246       }
00247     //save_image<TileImage_RGBA>(join_pathes(directory, "overlay.tif"),  bg);
00248     save_normalized_image<TileImage_GS_DOUBLE>(join_pathes(directory, "overlay.tif"),  bg);
00249   }
00250 }
00251