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
27using std::iterator;
28using std::list;
29
31
32namespace 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 */
49GradientClassifier::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 */
82void
83GradientClassifier::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 */
97void
98GradientClassifier::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 */
111void
112GradientClassifier::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
121std::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
A NULL pointer was supplied where not allowed.
Definition: software.h:32
Classifier to extract regions of interest.
Definition: classifier.h:36
virtual void set_src_buffer(unsigned char *yuv422_planar, unsigned int width, unsigned int height)
Set source buffer.
Definition: classifier.cpp:73
virtual void set_threshold(unsigned int threshold, unsigned int max_size=0)
Threshold setter.
Definition: gradient.cpp:83
virtual void set_edges(bool use_rising_edge, bool use_falling_edge)
Edge setter.
Definition: gradient.cpp:98
virtual std::list< ROI > * classify()
Classify image.
Definition: gradient.cpp:122
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
virtual void set_src_buffer(unsigned char *yuv422_planar, unsigned int width, unsigned int height)
Set source buffer.
Definition: gradient.cpp:112
virtual ~GradientClassifier()
Destructor.
Definition: gradient.cpp:72
Abstract Qualifier for a single pixel.
Definition: qualifiers.h:31
virtual unsigned char * get_buffer()
Get buffer.
Definition: qualifiers.cpp:80
virtual int get(fawkes::upoint_t pixel)=0
Getter.
virtual void set_buffer(unsigned char *buffer, unsigned int width=0, unsigned int height=0)
buffer setter
Definition: qualifiers.cpp:91
Region of interest.
Definition: roi.h:55
fawkes::upoint_t start
ROI start.
Definition: roi.h:115
void set_pixel_step(unsigned int step)
Set pixel step.
Definition: roi.cpp:239
void set_start(fawkes::upoint_t p)
Set upper left corner of ROI.
Definition: roi.cpp:119
void set_width(unsigned int width)
Set width of ROI.
Definition: roi.cpp:140
void set_height(unsigned int height)
Set height of ROI.
Definition: roi.cpp:158
unsigned int pixel_step
pixel step
Definition: roi.h:127
Scanline Grid.
Definition: grid.h:34
Point with cartesian coordinates as unsigned integers.
Definition: types.h:35
unsigned int x
x coordinate
Definition: types.h:36
unsigned int y
y coordinate
Definition: types.h:37