Fawkes API Fawkes Development Version
|
00001 00002 /*************************************************************************** 00003 * geodesic_dilation.cpp - implementation of morphological geodesic dilation 00004 * 00005 * Created: Sat Jun 10 16:21:30 2006 00006 * Copyright 2005-2007 Tim Niemueller [www.niemueller.de] 00007 * 00008 ****************************************************************************/ 00009 00010 /* This program is free software; you can redistribute it and/or modify 00011 * it under the terms of the GNU General Public License as published by 00012 * the Free Software Foundation; either version 2 of the License, or 00013 * (at your option) any later version. A runtime exception applies to 00014 * this software (see LICENSE.GPL_WRE file mentioned below for details). 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU Library General Public License for more details. 00020 * 00021 * Read the full text in the LICENSE.GPL_WRE file in the doc directory. 00022 */ 00023 00024 #include <core/exception.h> 00025 00026 #include <filters/morphology/geodesic_dilation.h> 00027 #include <filters/morphology/segenerator.h> 00028 #include <filters/morphology/dilation.h> 00029 #include <filters/min.h> 00030 00031 #include <fvutils/statistical/imagediff.h> 00032 #include <fvutils/color/colorspaces.h> 00033 #include <fvutils/base/roi.h> 00034 00035 #include <cstdlib> 00036 #include <cstring> 00037 00038 namespace firevision { 00039 #if 0 /* just to make Emacs auto-indent happy */ 00040 } 00041 #endif 00042 00043 /** Marker */ 00044 const unsigned int FilterGeodesicDilation::MARKER = 0; 00045 /** Mask */ 00046 const unsigned int FilterGeodesicDilation::MASK = 1; 00047 00048 #define ERROR(m) { \ 00049 fawkes::Exception e("FilterGeodesicDilation failed"); \ 00050 e.append("Function: %s", __FUNCTION__); \ 00051 e.append("Message: %s", m); \ 00052 throw e; \ 00053 } 00054 00055 00056 /** @class FilterGeodesicDilation <filters/morphology/geodesic_dilation.h> 00057 * Morphological geodesic dilation. 00058 * @author Tim Niemueller 00059 */ 00060 00061 /** Constructor. 00062 * @param se_size Structuring element size. 00063 */ 00064 FilterGeodesicDilation::FilterGeodesicDilation(unsigned int se_size) 00065 : MorphologicalFilter("Morphological Geodesic Dilation", 2) 00066 { 00067 this->se_size = (se_size > 0) ? se_size : 1; 00068 iterations = 0; 00069 00070 dilate = new FilterDilation(); 00071 min = new FilterMin(); 00072 diff = new ImageDiff(); 00073 00074 isotropic_se = SEGenerator::square(this->se_size, this->se_size); 00075 00076 dilate->set_structuring_element( isotropic_se, se_size, se_size, se_size / 2, se_size / 2 ); 00077 00078 src[MARKER] = src[MASK] = dst = NULL; 00079 src_roi[MARKER] = src_roi[MASK] = dst_roi = NULL; 00080 } 00081 00082 00083 /** Destructor. */ 00084 FilterGeodesicDilation::~FilterGeodesicDilation() 00085 { 00086 delete dilate; 00087 delete min; 00088 delete diff; 00089 free( isotropic_se ); 00090 } 00091 00092 00093 void 00094 FilterGeodesicDilation::apply() 00095 { 00096 if ( dst == NULL ) ERROR("dst == NULL"); 00097 if ( src[MASK] == NULL ) ERROR("src[MASK] == NULL"); 00098 if ( src[MARKER] == NULL ) ERROR("src[MARKER] == NULL"); 00099 if ( *(src_roi[MASK]) != *(src_roi[MARKER]) ) ERROR("marker and mask ROI differ"); 00100 00101 unsigned char *tmp = (unsigned char *)malloc(colorspace_buffer_size(YUV422_PLANAR, src_roi[MARKER]->image_width, src_roi[MARKER]->image_height) ); 00102 memcpy( tmp, src[MARKER], colorspace_buffer_size(YUV422_PLANAR, src_roi[MARKER]->image_width, src_roi[MARKER]->image_height) ); 00103 00104 diff->setBufferA( tmp, src_roi[MARKER]->image_width, src_roi[MARKER]->image_height ); 00105 diff->setBufferB( dst, dst_roi->image_width, dst_roi->image_height ); 00106 00107 dilate->set_src_buffer( tmp, src_roi[MARKER] ); 00108 00109 min->set_src_buffer( src[MASK], src_roi[MASK], 0 ); 00110 min->set_src_buffer( tmp, src_roi[MARKER], 1 ); 00111 min->set_dst_buffer( tmp, src_roi[MARKER] ); 00112 00113 00114 iterations = 0; 00115 do { 00116 memcpy(dst, tmp, colorspace_buffer_size(YUV422_PLANAR, dst_roi->image_width, dst_roi->image_height) ); 00117 dilate->apply(); 00118 min->apply(); 00119 } while (diff->different() && ( ++iterations < 255) ); 00120 00121 // std::cout << i << " iterations done for geodesic dilation" << std::endl; 00122 00123 free( tmp ); 00124 00125 } 00126 00127 00128 /** Get the number of iterations. 00129 * @return the number of iterations that were necessary to get a stable result in the 00130 * last call to apply(). 00131 */ 00132 unsigned int 00133 FilterGeodesicDilation::num_iterations() 00134 { 00135 return iterations; 00136 } 00137 00138 } // end namespace firevision