Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
ContourDetectorSimple.cpp
1 #include "ContourDetectorSimple.hh"
2 // std includes
3 #include <limits>
4 
5 using namespace std;
6 using namespace BIAS;
7 
8 #define MY_INFTY 10000
9 
10 /////////////////////////////////////////////////////////
11 inline unsigned short mymin(unsigned short a, unsigned short b)
12 {
13  return (a<=b)?a:b;
14 }
15 
16 inline unsigned short min(unsigned short s0,
17  unsigned short s1,
18  unsigned short s2,
19  unsigned short s3,
20  unsigned short s4)
21 {
22  return mymin(s0, mymin(s1, mymin(s2, mymin(s3, s4))));
23 }
24 
25 //////////////////////////////////////////////////////////////
26 template <class StorageType>
29 {
30  data = img.GetImageDataArray();
31 }
32 
33 template <class StorageType> StorageType
35 Get(int row, int col)
36 {
37  return data[row][col];
38 }
39 
40 template <class StorageType> void
42 Set(int row, int col, StorageType value)
43 {
44  data[row][col] = value;
45 }
46 
47 //////////////////////////////////////////////////////////////////////////
48 // instantiation
49 //////////////////////////////////////////////////////////////////////////
50 namespace BIAS{
51 template class DistImgMatAcc<unsigned char>;
52 //template class DistImgMatAcc<float>;
53 
54 // fill in instances as required
55 #ifdef BUILD_IMAGE_INT
56 //template class DistImgMatAcc<int>;
57 #endif
58 #ifdef BUILD_IMAGE_CHAR
59 //template class DistImgMatAcc<char>;
60 #endif
61 #ifdef BUILD_IMAGE_SHORT
62 #endif
63 #ifdef BUILD_IMAGE_USHORT
64 //template class DistImgMatAcc<unsigned short>;
65 #endif
66 #ifdef BUILD_IMAGE_UINT
67 #endif
68 #ifdef BUILD_IMAGE_DOUBLE
69 #endif
70 }
71 ///////////////////////////////////////////////////////////////
72 
73 
74 template <class StorageType>
77  SetBackground(StorageType(0));
78  SetGap(5);
79 }
80 
81 template <class StorageType>
84 }
85 
86 
87 template <class StorageType>
90  const std::vector<BIASContour> & contour){
91 
92  if(contour.size() == 0 || contour[0].length ==0)
93  return false;
94 
95  unsigned char** ida = image.GetImageDataArray();
96  unsigned channels = image.GetChannelCount();
97  unsigned w = image.GetWidth();
98  unsigned h = image.GetHeight();
99  //cout<<"Contour size:"<<contour.size()<<endl;
100 
101  for (unsigned int i=0;i<contour.size();i++){
102  //cout<<"ith length:"<<contour[i].length<<endl;
103  for (unsigned int k=0;k<contour[i].length;k++){
104  for (unsigned int c=0;c<channels;c++){
105  if((unsigned int)contour[i].contourPixel[k][0] > 0 && (unsigned int)contour[i].contourPixel[k][0] < w &&
106  (unsigned int)contour[i].contourPixel[k][1] > 0 && (unsigned int)contour[i].contourPixel[k][1] < h){
107  ida[(unsigned int)contour[i].contourPixel[k][1]]
108  [(unsigned int)contour[i].contourPixel[k][0]*channels+c] = 255;
109  }
110  }
111  }
112  }
113  return true;
114 }
115 
116 template <class StorageType>
118 FindFirst_(int &pos_x, int &pos_y) {
119  //check for first pixzel and return true if found
120  bool found = false;
121  for (int y = 0; y < img_h; y++)
122  for (int x = 0; x < img_w; x++)
123  if ( IsFg_(x,y) ) {
124  pos_x = x;
125  pos_y = y;
126  found = true;
127  return found;
128  }
129  //else return false
130  return found;
131 }
132 
133 template <class StorageType>
136 {
137  img_w = img.GetWidth();
138  img_h = img.GetHeight();
139  data_ = img.GetImageDataArray();
140 
141  // draw v lines
142  const int offset = img_w-1;
143  for (int i = 0; i < img_h; i++) {
144  data_[i][0] = background_;
145  data_[i][offset] = background_;
146  }
147  // draw h lines
148  for (int n = 0; n < img_h; n += (img_h-1)) {
149  StorageType *line = data_[n];
150  for (int i = 0; i < img_w; i++)
151  line[i] = background_;
152  }
153 }
154 
155 //////////////////////////////////////////////////////////////
156 template <class StorageType>
159  std::vector<BIAS::BIASContour>& contour){
160 
161  if(contour.size() < 1){
162  BIASContour cont;
163  contour.push_back(cont);
164  }
165 
166  Init_(image);
167 
168  CreateContourBase_(contour[0],image);
169  return contour[0].length;
170 }
171 
172 //////////////////////////////////////////////////////////////
173 
174 template <class StorageType>
177  const BIASContour& contour)
178 {
179  InitDistanceImage_(dist_img, contour);
180  MakeDistanceImage_(dist_img);
181 }
182 
183 template <class StorageType>
187 {
188  BIASContour contour;
189  Init_(img);
190  bool ret = CreateContourBase_( contour, img );
191 
192  if (contour.length <= 0 || !ret)
193  return -1;
194 
195  CreateDistanceImage( dist_img, contour );
196 
197  return contour.length;
198 }
199 
200 
201 //////////////////////////////////////////////////////////////
202 ////////// Protected Funcitons //////////////////////////////
203 
204 template <class StorageType> bool
208 {
209 
210  // find first foreground pixel location
211  bool ret = false;
212  int first_x = -1;
213  int first_y = -1;
214  ret = FindFirst_( first_x, first_y );
215  if ( first_x < 0 || first_y < 0 || !ret)
216  return ret;
217 
218  // create contour run
219  int x = first_x;
220  int y = first_y;
221  int d = 0;
222 
223  directionList_.clear();
224  contour.contourPixel.clear();
225  contour.length = 0;
226 
227  do {
228  contour.contourPixel.push_back ( BIAS::Vector2<double>( x,y ) );
229  contour.length++;
230 
231  d -= 3;
232  //we try 5 iterations to find the next foreground pixel
233  int stop = 8*gap_;
234  while ( !IsFg_(x,y,d) && d < stop) {
235  d++;
236  }
237  d = (d+16)%8;
238  directionList_.push_back (d);
239 
240  switch ( d ) {
241  case 0: x += 1; y += 0; break;
242  case 1: x += 1; y += 1; break;
243  case 2: x += 0; y += 1; break;
244  case 3: x -= 1; y += 1; break;
245  case 4: x -= 1; y += 0; break;
246  case 5: x -= 1; y -= 1; break;
247  case 6: x += 0; y -= 1; break;
248  case 7: x += 1; y -= 1; break;
249  }
250  } while ( x != first_x || y != first_y );
251 
252  return true;
253 }
254 
255 //////////////////////////////////////////////////////////////
256 template <class StorageType>
259  const BIASContour& contour)
260 {
261  StorageType* data = img.GetImageData();
262  int pixels = img.GetPixelCount();
263 
264  // initiate with distance infinity
265  for (int i = 0; i < pixels; i++)
266  data[i] = numeric_limits<StorageType>::max();
267 
268  // contour gets distance zero
269  for (unsigned int i = 0; i < contour.contourPixel.size(); i++)
270  img.SetPixel(0, (const unsigned)contour.contourPixel[i][0] /*col*/,
271  (const unsigned)contour.contourPixel[i][1] /*row*/);
272 }
273 
274 
275 //////////////////////////////////////////////////////////////
276 template <class StorageType>
279 {
280  DistImgMatAcc<StorageType> d ( img );
281 
282  int rows = img.GetHeight();
283  int cols = img.GetWidth();
284 
285  StorageType min;
286 
287  // forward pass
288  for (int k = 1; k <= rows-1; k++) {
289  for (int j = 1; j <= cols-1-1; j++) {
290  min = numeric_limits<StorageType>::max();
291  if (min > d.Get(k,j)) min = d.Get(k,j);
292  if (min > d.Get(k,j-1)+3) min = d.Get(k,j-1)+3;
293  if (min > d.Get(k-1,j)+3) min = d.Get(k-1,j)+3;
294  if (min > d.Get(k-1,j-1)+4) min = d.Get(k-1,j-1)+4;
295  if (min > d.Get(k-1,j+1)+4) min = d.Get(k-1,j+1)+4;
296  d.Set(k,j, min);
297  }
298  }
299 
300  // backward pass
301  for (int k = rows-1-1; k >= 0; k--) {
302  for (int j = cols-1-1; j >= 1; j--) {
303  min = numeric_limits<StorageType>::max();
304  if (min > d.Get(k,j)) min = d.Get(k,j);
305  if (min > d.Get(k,j+1)+3) min = d.Get(k,j+1)+3;
306  if (min > d.Get(k+1,j)+3) min = d.Get(k+1,j)+3;
307  if (min > d.Get(k+1,j+1)+4) min = d.Get(k+1,j+1)+4;
308  if (min > d.Get(k+1,j-1)+4) min = d.Get(k+1,j-1)+4;
309  d.Set(k, j, min);
310  }
311  }
312 }
313 
314 
315 //////////////////////////////////////////////////////////////////////////
316 // instantiation
317 //////////////////////////////////////////////////////////////////////////
318 namespace BIAS{
320 template class ContourDetectorSimple<float>;
321 
322 // fill in instances as required
323 #ifdef BUILD_IMAGE_INT
324 //template class ContourDetectorSimple<int>;
325 #endif
326 #ifdef BUILD_IMAGE_CHAR
327 //template class ContourDetectorSimple<char>;
328 #endif
329 #ifdef BUILD_IMAGE_SHORT
330 #endif
331 #ifdef BUILD_IMAGE_USHORT
332 //template class ContourDetectorSimple<unsigned short>;
333 #endif
334 #ifdef BUILD_IMAGE_UINT
335 #endif
336 #ifdef BUILD_IMAGE_DOUBLE
337 #endif
338 }
This class describes a contour using the freemancode.
std::vector< BIAS::Vector2< double > > contourPixel
All pixels contained in the contour.
unsigned int GetWidth() const
Definition: ImageBase.hh:312
a class for calculating the contour of a segmented region
unsigned int GetChannelCount() const
returns the number of Color channels, e.g.
Definition: ImageBase.hh:382
unsigned int GetHeight() const
Definition: ImageBase.hh:319
The image template class for specific storage types.
Definition: Image.hh:78
void SetPixel(const StorageType &value, const unsigned int &x, const unsigned int &y, const unsigned short int channel=0)
Set the value of a given pixel (x,y) in channel to value.
Definition: Image.hh:171
StorageType Get(int row, int col)
const StorageType * GetImageData() const
overloaded GetImageData() from ImageBase
Definition: Image.hh:137
void Set(int row, int col, StorageType value)
unsigned long int GetPixelCount() const
returns number of pixels in image
Definition: ImageBase.hh:422
const StorageType ** GetImageDataArray() const
overloaded GetImageDataArray() from ImageBase
Definition: Image.hh:153