Image Component Library (ICL)
|
00001 /******************************************************************** 00002 ** Image Component Library (ICL) ** 00003 ** ** 00004 ** Copyright (C) 2006-2013 CITEC, University of Bielefeld ** 00005 ** Neuroinformatics Group ** 00006 ** Website: www.iclcv.org and ** 00007 ** http://opensource.cit-ec.de/projects/icl ** 00008 ** ** 00009 ** File : ICLCV/src/ICLCV/RegionGrower.h ** 00010 ** Module : ICLCV ** 00011 ** Authors: Andre Ueckermann ** 00012 ** ** 00013 ** ** 00014 ** GNU LESSER GENERAL PUBLIC LICENSE ** 00015 ** This file may be used under the terms of the GNU Lesser General ** 00016 ** Public License version 3.0 as published by the ** 00017 ** ** 00018 ** Free Software Foundation and appearing in the file LICENSE.LGPL ** 00019 ** included in the packaging of this file. Please review the ** 00020 ** following information to ensure the license requirements will ** 00021 ** be met: http://www.gnu.org/licenses/lgpl-3.0.txt ** 00022 ** ** 00023 ** The development of this software was supported by the ** 00024 ** Excellence Cluster EXC 277 Cognitive Interaction Technology. ** 00025 ** The Excellence Cluster EXC 277 is a grant of the Deutsche ** 00026 ** Forschungsgemeinschaft (DFG) in the context of the German ** 00027 ** Excellence Initiative. ** 00028 ** ** 00029 ********************************************************************/ 00030 00031 #pragma once 00032 00033 #include <ICLMath/FixedVector.h> 00034 #include <ICLCore/Img.h> 00035 #include <ICLCore/DataSegment.h> 00036 #include <ICLMath/HomogeneousMath.h> 00037 #include <ICLUtils/Exception.h> 00038 00039 namespace icl{ 00040 namespace cv{ 00041 00043 00047 class RegionGrower{ 00048 00049 public: 00050 00052 00059 template<class Criterion> 00060 const core::Img32s &apply(const core::Img8u &image, Criterion crit, core::Img8u *initialMask = 0, 00061 const unsigned int minSize=0, const unsigned int startID=1){ 00062 this->result=core::Img32s(image.getParams()); 00063 //this->mask=Img8u(image.getParams()); 00064 core::Img8u &useMask = initialMask ? *initialMask : this->mask; 00065 if(image.getChannels() == 1){ 00066 region_grow<core::Img8u,icl8u,1, Criterion>(image, useMask, this->result, crit, minSize, startID); 00067 }else{ 00068 throw utils::ICLException("wrong number of image channels"); 00069 } 00070 return this->result; 00071 } 00072 00073 00075 00082 template<class Criterion> 00083 const core::Img32s &apply(const core::DataSegment<float,4> &dataseg, Criterion crit, core::Img8u *initialMask = 0, 00084 const unsigned int minSize=0, const unsigned int startID=1){ 00085 core::Img8u &useMask = initialMask ? *initialMask : this->mask; 00086 this->result.setSize(dataseg.getSize()); 00087 this->result.setChannels(1); 00088 region_grow<core::DataSegment<float,4>,float,4, Criterion>(dataseg, useMask, this->result, crit, minSize, startID); 00089 return this->result; 00090 } 00091 00092 00094 00101 const core::Img32s &applyFloat4EuclideanDistance(const core::DataSegment<float,4> &dataseg, core::Img8u mask, 00102 const int threshold, const unsigned int minSize=0, const unsigned int startID=1){ 00103 return apply(dataseg, Float4EuclideanDistance(threshold), &mask, minSize, startID); 00104 } 00105 00106 00108 00115 const core::Img32s &applyEqualThreshold(const core::Img8u &image, core::Img8u mask, const int threshold, 00116 const unsigned int minSize=0, const unsigned int startID=1){ 00117 return apply(image, EqualThreshold(threshold), &mask, minSize, startID); 00118 } 00119 00120 00122 00124 std::vector<std::vector<int> > getRegions(){ 00125 return regions; 00126 } 00127 00128 00129 private: 00130 00131 core::Img8u mask; 00132 core::Img32s result; 00133 std::vector<std::vector<int> > regions; 00134 00135 template<class T, class DataT, int DIM> 00136 struct RegionGrowerDataAccessor{ 00137 RegionGrowerDataAccessor(const T &t){}; 00138 int w() const { return 0; } 00139 int h() const { return 0; } 00140 math::FixedColVector<DataT, DIM> operator()(int x, int y) const { return math::FixedColVector<DataT,DIM>(); } 00141 }; 00142 00143 00144 struct EqualThreshold{ 00145 int t; 00146 EqualThreshold(int t):t(t){} 00147 bool operator()(icl8u a, icl8u b) const{ 00148 return (int)b == t; 00149 } 00150 }; 00151 00152 00153 struct Float4EuclideanDistance{ 00154 float t; 00155 Float4EuclideanDistance(float t):t(t){} 00156 bool operator()(const math::FixedColVector<float,4> &a, const math::FixedColVector<float,4> &b) const{ 00157 return math::dist3(a,b) < t; 00158 } 00159 }; 00160 00161 00162 template<class T, class DataT, int DIM, class Criterion> 00163 static void flood_fill(const RegionGrowerDataAccessor<T,DataT,DIM> &a, int xStart, int yStart, 00164 core::Channel8u &processed, Criterion crit, std::vector<int> &result, core::Channel32s &result2, int id); 00165 00166 00167 template<class T, class DataT, int DIM, class Criterion> 00168 void region_grow(const T &data, core::Img8u &mask, core::Img32s &result, Criterion crit, const unsigned int minSize, const unsigned int startID=1){ 00169 RegionGrowerDataAccessor<T,DataT,DIM> a(data); 00170 00171 core::Img8u processed = mask; 00172 core::Channel8u p = processed[0]; 00173 std::vector<int> r; 00174 core::Channel32s res = result[0]; 00175 result.fill(0); 00176 00177 int nextID = startID; 00178 regions.clear(); 00179 00180 std::vector<std::vector<int> > clear; 00181 00182 for(int y=0;y<a.h();++y){ 00183 for(int x=0;x<a.w();++x){ 00184 if(!p(x,y) && crit(a(x,y),a(x,y))){ 00185 r.clear(); 00186 flood_fill<T,DataT,DIM,Criterion>(a ,x ,y ,p, crit, r, res, nextID++); 00187 if(r.size()<minSize){ 00188 nextID--; 00189 clear.push_back(r);//delete later 00190 }else{ 00191 regions.push_back(r);//add region 00192 } 00193 } 00194 } 00195 } 00196 00197 //clear regions smaller minSize 00198 for(unsigned int i=0; i<clear.size(); i++){ 00199 for(unsigned int j=0; j<clear.at(i).size(); j++){ 00200 p[clear.at(i).at(j)]=false; 00201 res[clear.at(i).at(j)]=0; 00202 } 00203 } 00204 } 00205 00206 }; 00207 00208 00209 template<> 00210 struct RegionGrower::RegionGrowerDataAccessor<core::Img8u, icl8u, 1>{ 00211 const core::Channel8u c; 00212 RegionGrowerDataAccessor(const core::Img8u &image):c(image[0]){} 00213 int w() const { return c.getWidth(); } 00214 int h() const { return c.getHeight(); } 00215 math::FixedColVector<icl8u, 1> operator()(int x, int y) const { return c(x,y); } 00216 }; 00217 00218 template<> 00219 struct RegionGrower::RegionGrowerDataAccessor<core::Img8u, icl8u, 3>{ 00220 core::Channel8u c[3]; 00221 RegionGrowerDataAccessor(const core::Img8u &image){ 00222 for(int i=0;i<3;++i){ 00223 c[i] = ((core::Img8u&)image)[i]; 00224 } 00225 } 00226 int w() const { return c[0].getWidth(); } 00227 int h() const { return c[0].getHeight(); } 00228 math::FixedColVector<icl8u, 3> operator()(int x, int y) const { 00229 return math::FixedColVector<icl8u,3>(c[0](x,y), c[1](x,y), c[2](x,y)); 00230 } 00231 }; 00232 00233 template<> 00234 struct RegionGrower::RegionGrowerDataAccessor<core::DataSegment<float,4>, float, 4>{ 00235 core::DataSegment<float,4> data; 00236 int ww,hh; 00237 RegionGrowerDataAccessor(const core::DataSegment<float,4> &data):data(data){ 00238 ww = data.getSize().width; 00239 hh = data.getSize().height; 00240 } 00241 int w() const { return ww; } 00242 int h() const { return hh; } 00243 math::FixedColVector<float,4> operator()(int x, int y) const { return data(x,y); } 00244 }; 00245 00246 template<class T, class DataT, int DIM, class Criterion> 00247 void RegionGrower::flood_fill(const RegionGrowerDataAccessor<T,DataT,DIM> &a, int xStart, int yStart, 00248 core::Channel8u &processed, Criterion crit, std::vector<int> &result, core::Channel32s &result2, int id){ 00249 std::vector<utils::Point> stack(1,utils::Point(xStart,yStart)); 00250 processed(xStart,yStart) = true;//update mask 00251 result2(xStart,yStart) = id;//update result image 00252 result.push_back(xStart+yStart*a.w());//add to region vector 00253 unsigned int next = 0; 00254 while(next < stack.size()){ 00255 const utils::Point p = stack[next]; 00256 next++; 00257 for(int dy=-1;dy<=1;++dy){ 00258 const int y = p.y+dy; 00259 if(y < 0 || y >=a.h()) continue; 00260 for(int dx=-1;dx<=1;++dx){ 00261 const int x = p.x+dx; 00262 if(x < 0 || x >=a.w()) continue; 00263 if(dx==0 && dy==0) continue; 00264 00265 if(crit(a(p.x,p.y),a(x,y)) && processed(x,y)==false){ 00266 stack.push_back(utils::Point(x,y)); 00267 processed(x,y) = true; 00268 result2(x,y) = id; 00269 result.push_back(x+y*a.w()); 00270 } 00271 } 00272 } 00273 } 00274 } 00275 00276 } // namespace cv 00277 }