Image Component Library (ICL)
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
RegionGrower.h
Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines