Fawkes API  Fawkes Development Version
gradient.cpp
1 /***************************************************************************
2  * gradient.h - Class defining a gradient (color) classifier
3  *
4  * Created: Tue Jun 10 11:48:00 2008
5  * Copyright 2008 Christof Rath <christof.rath@gmail.com>
6  *
7  ****************************************************************************/
8 
9 /* This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version. A runtime exception applies to
13  * this software (see LICENSE.GPL_WRE file mentioned below for details).
14  *
15  * This program 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 Library General Public License for more details.
19  *
20  * Read the full text in the LICENSE.GPL_WRE file in the doc directory.
21  */
22 
23 #include "gradient.h"
24 #include <core/exceptions/software.h>
25 
26 using std::list;
27 using std::iterator;
28 
29 using fawkes::upoint_t;
30 
31 namespace firevision {
32 #if 0 /* just to make Emacs auto-indent happy */
33 }
34 #endif
35 
36 /** @class GradientClassifier <fvclassifiers/gradient.h>
37  * Gradient classifier.
38  * Uses the difference of the current and the last value.
39  */
40 
41 /** Constructor.
42  * @param scanlines list of scanline models (Does only work with ScanlineGrid)
43  * @param q Qualifier for a single pixel (The qualifier gets deleted by this class)
44  * @param threshold minimum rise required for classification
45  * @param max_size of an object to be detected (if 0 value will be ignored)
46  * @param use_rising_flank
47  * if true the classification can start on a rising flank
48  * @param use_falling_flank
49  * if true the classification can start on a falling flank
50  */
51 GradientClassifier::GradientClassifier(std::list<ScanlineGrid* >* scanlines,
52  Qualifier* q,
53  unsigned int threshold, unsigned int max_size,
54  bool use_rising_flank, bool use_falling_flank)
55  : Classifier("GradientClassifier")
56 {
57  if (!scanlines)
58  throw fawkes::NullPointerException("GradientClassifier: scanlines may not be null!");
59  if (!q)
60  throw fawkes::NullPointerException("GradientClassifier: the Qualifier may not be null!");
61 
62  _scanlines = scanlines;
63  _q = q;
64 
65  _max_size = 999999; //Infinite...
66  set_threshold(threshold, max_size);
67  set_edges(use_rising_flank, use_falling_flank);
68 }
69 
70 /** Destructor.
71  */
73 {
74  if (_q)
75  delete _q;
76 }
77 
78 /** Threshold setter.
79  * @param threshold minimum rise required for classification
80  * @param max_size of an object to be detected (if 0 value will not be set)
81  */
82 void
83 GradientClassifier::set_threshold(unsigned int threshold, unsigned int max_size)
84 {
85  _threshold = threshold;
86 
87  if (max_size)
88  _max_size = max_size;
89 }
90 
91 /** Edge setter.
92  * @param use_rising_edge
93  * if true the classification can start on a rising edge
94  * @param use_falling_edge
95  * if true the classification can start on a falling edge
96  */
97 void
98 GradientClassifier::set_edges(bool use_rising_edge, bool use_falling_edge)
99 {
100  _use_rising_edge = use_rising_edge;
101  _use_falling_edge = use_falling_edge;
102 }
103 
104 /** Set source buffer.
105  * @param yuv422_planar a YUV422 planar buffer with the source image to
106  * classify. The classifier may NOT modify the image in any way. If that is
107  * required the classifier shall make a copy of the image.
108  * @param width width of buffer in pixels
109  * @param height height of buffer in pixels
110  */
111 void
112 GradientClassifier::set_src_buffer(unsigned char *yuv422_planar,
113  unsigned int width, unsigned int height)
114 {
115  Classifier::set_src_buffer(yuv422_planar, width, height);
116 
117  _q->set_buffer(yuv422_planar, width, height);
118 }
119 
120 std::list< ROI > *
122 {
123  if (_q->get_buffer() == NULL)
124  {
125  //cout << "GradientClassifier: ERROR, src buffer not set. NOT classifying." << endl;
126  return new std::list< ROI >;
127  }
128 
129  list< ROI > *rv = new list< ROI >;
130  int cur_val, cur_diff, direction = 0;
131  upoint_t cur_pos, edge_start;
132  cur_pos.x = cur_pos.y = edge_start.x = edge_start.y = 0;
133 
134  unsigned int jumpSize = 0;
135 
136  ROI current;
137 
138  for (list<ScanlineGrid*>::iterator it = _scanlines->begin(); it != _scanlines->end(); it++)
139  {
140  ScanlineGrid* slm = (*it);
141  slm->reset();
142 
143  _last_pos = *(*slm);
144  _last_val = _q->get(_last_pos);
145 
146  while(!slm->finished())
147  {
148  cur_pos = *(++(*slm));
149  cur_val = _q->get(cur_pos);
150  cur_diff = cur_val - _last_val;
151 
152  if ((cur_pos.x < _last_pos.x || cur_pos.y < _last_pos.y) //new scan line
153  || (current.pixel_step && ((cur_pos.x - current.start.x) > _max_size //area found is too big
154  || (cur_pos.y - current.start.y) > _max_size)))
155  {
156  current.set_pixel_step(0);
157 
158  edge_start.x = edge_start.y = direction = jumpSize = 0;
159  }
160 
161  int curDir = (cur_diff < 0 ? -1 : (cur_diff > 0 ? 1 : 0));
162  switch (curDir)
163  {
164  case -1:
165  switch (direction)
166  {
167  case -1: //drop continues
168  jumpSize -= cur_diff;
169  break;
170  case 0: //new drop
171  jumpSize = -cur_diff;
172  edge_start = cur_pos;
173  break;
174  case 1:
175  if (jumpSize < _threshold)//spike reset ramp
176  {
177  jumpSize = -cur_diff;
178  edge_start = cur_pos;
179  }
180  else // found edge!
181  {
182  if (current.pixel_step) //this is a line end
183  {
184  current.set_width(_last_pos.x - current.start.x);
185  current.set_height(_last_pos.y - current.start.y);
186 
187  rv->push_back(ROI(current));
188 
189  current.set_pixel_step(0);
190  }
191  else if (_use_falling_edge)
192  {
193  current.set_pixel_step(1);
194  current.set_start(edge_start);
195  }
196 
197  edge_start = cur_pos;
198  jumpSize = -cur_diff;
199  }
200  break;
201  }
202  direction = -1;
203  break;
204 
205 
206  case 0:
207  switch (direction)
208  {
209  case -1: //ramp end
210  case 1: //ramp end
211  if (jumpSize >= _threshold) //found edge!
212  {
213  if (current.pixel_step) //this is a line end
214  {
215  current.set_width(_last_pos.x - current.start.x);
216  current.set_height(_last_pos.y - current.start.y);
217 
218  rv->push_back(ROI(current));
219 
220  current.set_pixel_step(0);
221  }
222  else
223  {
224  if ((_use_falling_edge && direction == 1) || (_use_rising_edge && direction == -1))
225  {
226  current.set_pixel_step(1);
227  current.set_start(edge_start);
228  }
229  }
230  }
231  break;
232 
233  case 0:
234  break;
235  }
236  direction = jumpSize = 0;
237  edge_start.x = edge_start.y = 0;
238  break;
239 
240 
241  case 1:
242  switch (direction)
243  {
244  case 1: //climb continues
245  jumpSize += cur_diff;
246  break;
247  case 0: //new climb
248  jumpSize = cur_diff;
249  edge_start = cur_pos;
250  break;
251  case -1:
252  if (jumpSize < _threshold)//spike reset ramp
253  {
254  jumpSize = cur_diff;
255  edge_start = cur_pos;
256  }
257  else // found edge!
258  {
259  if (current.pixel_step) //this is a line end
260  {
261  current.set_width(_last_pos.x - current.start.x);
262  current.set_height(_last_pos.y - current.start.y);
263 
264  rv->push_back(ROI(current));
265 
266  current.set_pixel_step(0);
267  }
268  else if (_use_rising_edge)
269  {
270  current.set_pixel_step(1);
271  current.set_start(edge_start);
272  }
273 
274  edge_start = cur_pos;
275  jumpSize = cur_diff;
276  }
277  break;
278  }
279  direction = 1;
280  break;
281  }
282 
283 
284  _last_val = cur_val;
285  _last_pos = cur_pos;
286  }
287  } //END: For all scanline models
288 
289  return rv;
290 }
291 
292 } // end namespace firevision
Scanline Grid.
Definition: grid.h:36
GradientClassifier(std::list< ScanlineGrid * > *scanlines, Qualifier *q, unsigned int threshold, unsigned int max_size=0, bool use_rising_flank=true, bool use_falling_flank=true)
Constructor.
Definition: gradient.cpp:51
virtual std::list< ROI > * classify()
Classify image.
Definition: gradient.cpp:121
void set_height(unsigned int height)
Set height of ROI.
Definition: roi.cpp:167
fawkes::upoint_t start
ROI start.
Definition: roi.h:119
unsigned int y
y coordinate
Definition: types.h:36
unsigned int x
x coordinate
Definition: types.h:35
void set_pixel_step(unsigned int step)
Set pixel step.
Definition: roi.cpp:256
Region of interest.
Definition: roi.h:58
A NULL pointer was supplied where not allowed.
Definition: software.h:34
virtual void set_buffer(unsigned char *buffer, unsigned int width=0, unsigned int height=0)
buffer setter
Definition: qualifiers.cpp:93
virtual int get(fawkes::upoint_t pixel)=0
Getter.
virtual void set_edges(bool use_rising_edge, bool use_falling_edge)
Edge setter.
Definition: gradient.cpp:98
virtual unsigned char * get_buffer()
Get buffer.
Definition: qualifiers.cpp:82
virtual void set_src_buffer(unsigned char *yuv422_planar, unsigned int width, unsigned int height)
Set source buffer.
Definition: classifier.cpp:78
virtual void set_threshold(unsigned int threshold, unsigned int max_size=0)
Threshold setter.
Definition: gradient.cpp:83
virtual ~GradientClassifier()
Destructor.
Definition: gradient.cpp:72
Point with cartesian coordinates as unsigned integers.
Definition: types.h:34
void set_start(fawkes::upoint_t p)
Set upper left corner of ROI.
Definition: roi.cpp:124
virtual void set_src_buffer(unsigned char *yuv422_planar, unsigned int width, unsigned int height)
Set source buffer.
Definition: gradient.cpp:112
Classifier to extract regions of interest.
Definition: classifier.h:37
unsigned int pixel_step
pixel step
Definition: roi.h:131
void set_width(unsigned int width)
Set width of ROI.
Definition: roi.cpp:147
Abstract Qualifier for a single pixel.
Definition: qualifiers.h:34