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 
25 #include <core/exceptions/software.h>
26 
27 using std::iterator;
28 using std::list;
29 
30 using fawkes::upoint_t;
31 
32 namespace firevision {
33 
34 /** @class GradientClassifier <fvclassifiers/gradient.h>
35  * Gradient classifier.
36  * Uses the difference of the current and the last value.
37  */
38 
39 /** Constructor.
40  * @param scanlines list of scanline models (Does only work with ScanlineGrid)
41  * @param q Qualifier for a single pixel (The qualifier gets deleted by this class)
42  * @param threshold minimum rise required for classification
43  * @param max_size of an object to be detected (if 0 value will be ignored)
44  * @param use_rising_flank
45  * if true the classification can start on a rising flank
46  * @param use_falling_flank
47  * if true the classification can start on a falling flank
48  */
49 GradientClassifier::GradientClassifier(std::list<ScanlineGrid *> *scanlines,
50  Qualifier * q,
51  unsigned int threshold,
52  unsigned int max_size,
53  bool use_rising_flank,
54  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,
114  unsigned int height)
115 {
116  Classifier::set_src_buffer(yuv422_planar, width, height);
117 
118  _q->set_buffer(yuv422_planar, width, height);
119 }
120 
121 std::list<ROI> *
123 {
124  if (_q->get_buffer() == NULL) {
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  ScanlineGrid *slm = (*it);
140  slm->reset();
141 
142  _last_pos = *(*slm);
143  _last_val = _q->get(_last_pos);
144 
145  while (!slm->finished()) {
146  cur_pos = *(++(*slm));
147  cur_val = _q->get(cur_pos);
148  cur_diff = cur_val - _last_val;
149 
150  if ((cur_pos.x < _last_pos.x || cur_pos.y < _last_pos.y) //new scan line
151  || (current.pixel_step
152  && ((cur_pos.x - current.start.x) > _max_size //area found is too big
153  || (cur_pos.y - current.start.y) > _max_size))) {
154  current.set_pixel_step(0);
155 
156  edge_start.x = edge_start.y = direction = jumpSize = 0;
157  }
158 
159  int curDir = (cur_diff < 0 ? -1 : (cur_diff > 0 ? 1 : 0));
160  switch (curDir) {
161  case -1:
162  switch (direction) {
163  case -1: //drop continues
164  jumpSize -= cur_diff;
165  break;
166  case 0: //new drop
167  jumpSize = -cur_diff;
168  edge_start = cur_pos;
169  break;
170  case 1:
171  if (jumpSize < _threshold) //spike reset ramp
172  {
173  jumpSize = -cur_diff;
174  edge_start = cur_pos;
175  } else // found edge!
176  {
177  if (current.pixel_step) //this is a line end
178  {
179  current.set_width(_last_pos.x - current.start.x);
180  current.set_height(_last_pos.y - current.start.y);
181 
182  rv->push_back(ROI(current));
183 
184  current.set_pixel_step(0);
185  } else if (_use_falling_edge) {
186  current.set_pixel_step(1);
187  current.set_start(edge_start);
188  }
189 
190  edge_start = cur_pos;
191  jumpSize = -cur_diff;
192  }
193  break;
194  }
195  direction = -1;
196  break;
197 
198  case 0:
199  switch (direction) {
200  case -1: //ramp end
201  case 1: //ramp end
202  if (jumpSize >= _threshold) //found edge!
203  {
204  if (current.pixel_step) //this is a line end
205  {
206  current.set_width(_last_pos.x - current.start.x);
207  current.set_height(_last_pos.y - current.start.y);
208 
209  rv->push_back(ROI(current));
210 
211  current.set_pixel_step(0);
212  } else {
213  if ((_use_falling_edge && direction == 1) || (_use_rising_edge && direction == -1)) {
214  current.set_pixel_step(1);
215  current.set_start(edge_start);
216  }
217  }
218  }
219  break;
220 
221  case 0: break;
222  }
223  direction = jumpSize = 0;
224  edge_start.x = edge_start.y = 0;
225  break;
226 
227  case 1:
228  switch (direction) {
229  case 1: //climb continues
230  jumpSize += cur_diff;
231  break;
232  case 0: //new climb
233  jumpSize = cur_diff;
234  edge_start = cur_pos;
235  break;
236  case -1:
237  if (jumpSize < _threshold) //spike reset ramp
238  {
239  jumpSize = cur_diff;
240  edge_start = cur_pos;
241  } else // found edge!
242  {
243  if (current.pixel_step) //this is a line end
244  {
245  current.set_width(_last_pos.x - current.start.x);
246  current.set_height(_last_pos.y - current.start.y);
247 
248  rv->push_back(ROI(current));
249 
250  current.set_pixel_step(0);
251  } else if (_use_rising_edge) {
252  current.set_pixel_step(1);
253  current.set_start(edge_start);
254  }
255 
256  edge_start = cur_pos;
257  jumpSize = cur_diff;
258  }
259  break;
260  }
261  direction = 1;
262  break;
263  }
264 
265  _last_val = cur_val;
266  _last_pos = cur_pos;
267  }
268  } //END: For all scanline models
269 
270  return rv;
271 }
272 
273 } // end namespace firevision
firevision::Classifier
Definition: classifier.h:39
firevision::GradientClassifier::set_threshold
virtual void set_threshold(unsigned int threshold, unsigned int max_size=0)
Threshold setter.
Definition: gradient.cpp:83
firevision::ROI::set_width
void set_width(unsigned int width)
Set width of ROI.
Definition: roi.cpp:139
firevision::ROI::set_height
void set_height(unsigned int height)
Set height of ROI.
Definition: roi.cpp:157
firevision::GradientClassifier::classify
virtual std::list< ROI > * classify()
Definition: gradient.cpp:122
firevision::GradientClassifier::set_src_buffer
virtual void set_src_buffer(unsigned char *yuv422_planar, unsigned int width, unsigned int height)
Set source buffer.
Definition: gradient.cpp:112
fawkes::upoint_t
Point with cartesian coordinates as unsigned integers.
Definition: types.h:33
firevision::ROI
Definition: roi.h:58
firevision::GradientClassifier::~GradientClassifier
virtual ~GradientClassifier()
Destructor.
Definition: gradient.cpp:72
firevision::Qualifier
Definition: qualifiers.h:34
firevision::Qualifier::get_buffer
virtual unsigned char * get_buffer()
Get buffer.
Definition: qualifiers.cpp:79
firevision::ScanlineGrid
Definition: grid.h:37
firevision::GradientClassifier::GradientClassifier
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:49
fawkes::upoint_t::y
unsigned int y
y coordinate
Definition: types.h:36
firevision::ROI::set_start
void set_start(fawkes::upoint_t p)
Set upper left corner of ROI.
Definition: roi.cpp:118
firevision::ROI::pixel_step
unsigned int pixel_step
pixel step
Definition: roi.h:131
firevision::GradientClassifier::set_edges
virtual void set_edges(bool use_rising_edge, bool use_falling_edge)
Edge setter.
Definition: gradient.cpp:98
firevision::Classifier::set_src_buffer
virtual void set_src_buffer(unsigned char *yuv422_planar, unsigned int width, unsigned int height)
Set source buffer.
Definition: classifier.cpp:77
firevision::Qualifier::get
virtual int get(fawkes::upoint_t pixel)=0
Getter.
firevision::ROI::start
fawkes::upoint_t start
ROI start.
Definition: roi.h:119
fawkes::NullPointerException
Definition: software.h:35
fawkes::upoint_t::x
unsigned int x
x coordinate
Definition: types.h:35
firevision::Qualifier::set_buffer
virtual void set_buffer(unsigned char *buffer, unsigned int width=0, unsigned int height=0)
buffer setter
Definition: qualifiers.cpp:90
firevision::ROI::set_pixel_step
void set_pixel_step(unsigned int step)
Set pixel step.
Definition: roi.cpp:238