Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
Thinning.cpp
1 /*
2 This file is part of the BIAS library (Basic ImageAlgorithmS).
3 
4 Copyright (C) 2003-2009 (see file CONTACT for details)
5  Multimediale Systeme der Informationsverarbeitung
6  Institut fuer Informatik
7  Christian-Albrechts-Universitaet Kiel
8 
9 
10 BIAS is free software; you can redistribute it and/or modify
11 it under the terms of the GNU Lesser General Public License as published by
12 the Free Software Foundation; either version 2.1 of the License, or
13 (at your option) any later version.
14 
15 BIAS is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU Lesser General Public License for more details.
19 
20 You should have received a copy of the GNU Lesser General Public License
21 along with BIAS; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
24 
25 
26 #include "Thinning.hh"
27 
28 #ifdef BIAS_DEBUG
29 #include "Base/Image/ImageIO.hh"
30 #endif
31 
32 #include <Base/Common/BIASpragma.hh>
33 
34 using namespace BIAS;
35 using namespace std;
36 
37 template <class InputStorageType, class OutputStorageType>
40  : FilterNToN<InputStorageType, OutputStorageType>()
41 {
42 }
43 
44 template <class InputStorageType, class OutputStorageType>
47  : FilterNToN<InputStorageType, OutputStorageType>(other)
48 {
49 }
50 
51 template <class InputStorageType, class OutputStorageType>
54 {
55 }
56 
57 template <class InputStorageType, class OutputStorageType>
60 {
61  BIASERR("Unimplemented interface, calling generic Filter");
62  return Filter(src, dst);
63 }
64 
65 template <class InputStorageType, class OutputStorageType>
68 {
69  BIASERR("Unimplemented interface, calling generic Filter");
70  return Filter(src, dst);
71 }
72 
73 
74 template <class InputStorageType,class OutputStorageType>
77 {
78  BIASCDOUT(D_FILTERBASE_CALLSTACK,"Thinning::Rosenfeld_\n");
79  const InputStorageType **srcstart=src.GetImageDataArray();
80  OutputStorageType **dststart=dst.GetImageDataArray();
81  int img_width=src.GetWidth();
82  int img_height=src.GetHeight();
83  int channelcount=src.GetChannelCount();
84 
85  std::vector < std::vector < bool > > Econnected_;
86  std::vector < std::vector < bool > > Eendpoint_;
87  std::vector < std::vector < bool > > Eisolated_;
88  std::vector < std::vector < bool > > Esimple_;
89 
90  std::vector < std::vector < bool > > northBorder_;
91  std::vector < std::vector < bool > > southBorder_;
92  std::vector < std::vector < bool > > eastBorder_;
93  std::vector < std::vector < bool > > westBorder_;
94 
95  //122 patterns for all possible not-simple variants for our CELLS
96  int not_simple[] = {144,136,132,80,72,68,66,65,36,34,
97  33,20,18,17,9,5,208,200,196,164,
98  148,152,146,145,140,137,133,100,98,97,
99  84,82,81,88,76,74,73,70,69,67,
100  52,50,49,41,38,37,35,25,22,21,
101  19,13,228,216,212,210,209,204,201,197,
102  116,114,113,105,102,101,99,180,165,156,
103  153,150,149,147,141,92,90,89,86,85,
104  83,78,77,75,71,57,54,53,51,45,
105  39,29,23,220,217,214,213,211,205,241,
106  229,181,157,151,125,119,95,221,215,61,
107  55,121,118,117,115,109,103,94,93,91,
108  87,79};
109 
110  //Reserve place in these arrays
111  for (int i = 0; i < img_height; i++)
112  {
113  std::vector< bool > just;
114  just.clear();
115 
116  for (int j = 0; j < img_width; j++)
117  {
118  //bEdges[i].reserve(size);
119  just.push_back(false);
120  }
121 
122  Econnected_.push_back(just);
123  Eendpoint_.push_back(just);
124  Eisolated_.push_back(just);
125  Esimple_.push_back(just);
126 
127  northBorder_.push_back(just);
128  southBorder_.push_back(just);
129  eastBorder_.push_back(just);
130  westBorder_.push_back(just);
131  }
132 
133  const InputStorageType **srcida = NULL;
134  OutputStorageType **dstida = NULL;
135 
136  if(channelcount == 1)
137  {
138  srcida = srcstart;
139  dstida = dststart;
140 
141  //copy image
142  for(int x = 0; x < img_height; x++)
143  {
144  for(int y = 0; y < img_width; y++)
145  {
146  dstida[x][y] = (OutputStorageType)srcida[x][y];
147  }
148  }
149 
150  //Do RosenFeld 4 times - for each border one time
151  for(int bord = 0; bord < 4; bord++)
152  {
153 
154  for(int x = 0; x < img_height; x++)
155  {
156  for(int y = 0; y < img_width; y++)
157  {
158  int sum8 = 0;
159  int sum8BIG = 0;
160 
161  if((int)dstida[x][y] != 0)
162  {
163  if(x > 0)
164  {
165  // x0x
166  // xcx
167  // xxx
168  if((int)dstida[x-1][y] > 0){
169  sum8++; sum8BIG += 64;}
170  else{
171  northBorder_[x][y] = true;}
172 
173  // 0xx
174  // xcx
175  // xxx
176  if((y > 0) && ((int)dstida[x-1][y-1] > 0)){
177  sum8++; sum8BIG += 128;}
178 
179  // xx0
180  // xcx
181  // xxx
182  if((y < img_width - 1) && ((int)dstida[x-1][y+1] > 0)){
183  sum8++; sum8BIG += 32;}
184  }
185  if(x < img_height - 1)
186  {
187  // xxx
188  // xcx
189  // x0x
190  if((int)dstida[x+1][y] > 0){
191  sum8++; sum8BIG += 4;}
192  else{
193  southBorder_[x][y] = true;}
194 
195  // xxx
196  // xcx
197  // 0xx
198  if((y > 0) && ((int)dstida[x+1][y-1] > 0)){
199  sum8++; sum8BIG += 2;}
200 
201  // xxx
202  // xcx
203  // xx0
204  if((y < img_width - 1) && ((int)dstida[x+1][y+1] > 0)){
205  sum8++; sum8BIG += 8;}
206  }
207 
208  if(y > 0)
209  {
210  // xxx
211  // 0cx
212  // xxx
213  if((int)dstida[x][y-1] > 0){
214  sum8++; sum8BIG += 1;}
215  else{
216  westBorder_[x][y] = true;}
217  }
218 
219  if(y < img_width - 1)
220  {
221  // xxx
222  // xc0
223  // xxx
224  if((int)dstida[x][y+1] > 0){
225  sum8++; sum8BIG += 16;}
226  else{
227  eastBorder_[x][y] = true;}
228  }
229  }
230 
231  if(sum8 > 0)
232  {
233  if(sum8 == 1)
234  {
235  Eendpoint_[x][y] = true;
236  }
237 
238  Econnected_[x][y] = true;
239  Esimple_[x][y] = true;
240  for(int i = 0; i < 122; i++)
241  {
242  if(sum8BIG == not_simple[i]){Esimple_[x][y] = false;}
243  }
244  }
245  else
246  {
247  Eisolated_[x][y] = true;
248  }
249  }
250  }
251 
252  for(int x = 0; x < img_height; x++)
253  {
254  for(int y = 0; y < img_width; y++)
255  {
256 
257  /*cout << "Point with coords: " << y << "; " << x << " has value : " << (int)srcida[x][y]
258  << " and (con, iso, sim, end, n, s, w, e): "
259  << Econnected_[x][y] << Eisolated_[x][y] << Esimple_[x][y] << Eendpoint_[x][y]
260  << northBorder_[x][y] << southBorder_[x][y] << westBorder_[x][y] << eastBorder_[x][y] << endl;*/
261 
262  if(Esimple_[x][y] &&
263  !Eendpoint_[x][y] &&
264  !Eisolated_[x][y] &&
265  (((bord == 0) && northBorder_[x][y]) ||
266  ((bord == 1) && southBorder_[x][y]) ||
267  ((bord == 2) && eastBorder_[x][y]) ||
268  ((bord == 3) && westBorder_[x][y])
269  ))
270  {
271  dstida[x][y]=(OutputStorageType)(0);
272  }
273  }
274  }
275  }
276  }
277  return 0;
278 }
279 
280 namespace BIAS{
281 #define FILTER_INSTANTIATION_CLASS Thinning
282 #include "Filterinst.hh"
283 }
unsigned int GetWidth() const
Definition: ImageBase.hh:312
generic Thinning class, uses ethe Rosenfeld algorithm to thin structures in images without erasing th...
Definition: Thinning.hh:42
virtual int FilterFloat(const Image< InputStorageType > &src, Image< OutputStorageType > &dst)
only calls filter, for consistency of params
Definition: Thinning.cpp:67
virtual ~Thinning()
Definition: Thinning.cpp:53
unsigned int GetChannelCount() const
returns the number of Color channels, e.g.
Definition: ImageBase.hh:382
base class for simple n-&gt;n filter implementations
Definition: FilterNToN.hh:43
unsigned int GetHeight() const
Definition: ImageBase.hh:319
virtual int FilterInt(const Image< InputStorageType > &src, Image< OutputStorageType > &dst)
only calls filter, for consistency of params
Definition: Thinning.cpp:59
virtual int Filter(const Image< InputStorageType > &src, Image< OutputStorageType > &dst)
makes Rosenfeld-Thinning on src-Image and puts it in Destionation-Image
Definition: Thinning.cpp:76
const StorageType ** GetImageDataArray() const
overloaded GetImageDataArray() from ImageBase
Definition: Image.hh:153