Fawkes API  Fawkes Development Version
roi.cpp
1 
2 /***************************************************************************
3  * roi.cpp - Implementation for Region Of Interest (ROI) representation
4  *
5  * Generated: Thu Jul 14 12:01:58 2005
6  * Copyright 2005-2007 Tim Niemueller [www.niemueller.de]
7  *
8  ****************************************************************************/
9 
10 /* This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version. A runtime exception applies to
14  * this software (see LICENSE.GPL_WRE file mentioned below for details).
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU Library General Public License for more details.
20  *
21  * Read the full text in the LICENSE.GPL_WRE file in the doc directory.
22  */
23 
24 #include <fvutils/base/roi.h>
25 
26 #include <cstdlib>
27 
28 using namespace fawkes;
29 
30 namespace firevision {
31 #if 0 /* just to make Emacs auto-indent happy */
32 }
33 #endif
34 
35 /** @class ROI <fvutils/base/roi.h>
36  * Region of interest.
37  * The ROI class is central to FireVision. All image processing is concentrated
38  * on the pre-classified interesting parts of the image, denoted by the
39  * regions of interest (ROIs).
40  *
41  * A ROI is a rectangular area of the image. Its start is denoted by the upper
42  * left corner of this rectangle and the size is given by its width and height.
43  *
44  * @author Tim Niemueller
45  */
46 
47 ROI* ROI::roi_full_image = NULL;
48 
49 
50 /** Constructor. */
51 ROI::ROI()
52 {
53  num_hint_points = 1;
54  start.x = start.y = width = height = image_width = image_height = line_step = pixel_step = 0;
55  color = C_BACKGROUND;
56 }
57 
58 
59 /** Constructor.
60  * @param start_x Upper left corner of ROI X coordinate
61  * @param start_y Upper left corner of ROI y coordinate
62  * @param width Width of extent of ROI
63  * @param height height of extent of ROI
64  * @param image_width width of full image this ROI belongs to
65  * @param image_height height of full image this ROI belongs to
66  */
67 ROI::ROI(unsigned int start_x, unsigned int start_y,
68  unsigned int width, unsigned int height,
69  unsigned int image_width, unsigned int image_height)
70 {
71  num_hint_points = 1;
72  start.x = start_x;
73  start.y = start_y;
74  this->width = width;
75  this->height = height;
76  this->image_width = image_width;
77  this->image_height = image_height;
78  line_step = image_width;
79  pixel_step = 1;
80  color = C_BACKGROUND;
81 }
82 
83 
84 /** Copy constructor.
85  * @param roi reference to ROI to copy
86  */
87 ROI::ROI(const ROI &roi)
88 {
89  start = roi.start;
90  width = roi.width;
91  height = roi.height;
92  image_width = roi.image_width;
93  image_height = roi.image_height;
94  line_step = roi.line_step;
95  pixel_step = roi.pixel_step;
96  hint = roi.hint;
97  color = roi.color;
98  num_hint_points = roi.num_hint_points;
99 }
100 
101 
102 /** Copy constructor.
103  * @param roi pointer to ROI to copy
104  */
105 ROI::ROI(const ROI *roi)
106 {
107  start = roi->start;
108  width = roi->width;
109  height = roi->height;
110  image_width = roi->image_width;
111  image_height = roi->image_height;
112  line_step = roi->line_step;
113  pixel_step = roi->pixel_step;
114  hint = roi->hint;
115  color = roi->color;
116  num_hint_points = roi->num_hint_points;
117 }
118 
119 
120 /** Set upper left corner of ROI.
121  * @param p point
122  */
123 void
124 ROI::set_start(point_t p)
125 {
126  start.x = p.x;
127  start.y = p.y;
128 }
129 
130 
131 /** Set upper left corner.
132  * @param x x coordinate in image
133  * @param y y coordinate in image
134  */
135 void
136 ROI::set_start(unsigned int x, unsigned int y)
137 {
138  start.x = x;
139  start.y = y;
140 }
141 
142 
143 /** Set width of ROI.
144  * @param width new width
145  */
146 void
147 ROI::set_width(unsigned int width)
148 {
149  this->width = width;
150 }
151 
152 
153 /** Get width of ROI.
154  * @return width
155  */
156 unsigned int
157 ROI::get_width() const
158 {
159  return width;
160 }
161 
162 
163 /** Set height of ROI.
164  * @param height new height
165  */
166 void
167 ROI::set_height(unsigned int height)
168 {
169  this->height = height;
170 }
171 
172 
173 /** Get height of ROI.
174  * @return height
175  */
176 unsigned int
177 ROI::get_height() const
178 {
179  return height;
180 }
181 
182 
183 /** Set full image width.
184  * Set the width of the image that contains this ROI.
185  * @param image_width full width of image.
186  */
187 void
188 ROI::set_image_width(unsigned int image_width)
189 {
190  this->image_width = image_width;
191 }
192 
193 
194 /** Get full image width.
195  * Get the width of the image that contains this ROI.
196  * @return full width of image.
197  */
198 unsigned int
199 ROI::get_image_width() const
200 {
201  return image_width;
202 }
203 
204 
205 /** Set full image height
206  * Set the height of the image that contains this ROI.
207  * @param image_height full height of image.
208  */
209 void
210 ROI::set_image_height(unsigned int image_height)
211 {
212  this->image_height = image_height;
213 }
214 
215 
216 /** Get full image height.
217  * Get the height of the image that contains this ROI.
218  * @return full height of image.
219  */
220 unsigned int
221 ROI::get_image_height() const
222 {
223  return image_height;
224 }
225 
226 
227 /** Set linestep.
228  * The linestep is the offset in bytes from the beginning of one line
229  * in the buffer to the beginning of the next line.
230  * @param step new line step
231  */
232 void
233 ROI::set_line_step(unsigned int step)
234 {
235  line_step = step;
236 }
237 
238 
239 /** Get linestep.
240  * @return line step
241  * @see setLineStep()
242  */
243 unsigned int
244 ROI::get_line_step() const
245 {
246  return line_step;
247 }
248 
249 
250 /** Set pixel step.
251  * The pixel step is the offset in bytes to get from one pixel to the next
252  * in the buffer.
253  * @param step new pixel step.
254  */
255 void
256 ROI::set_pixel_step(unsigned int step)
257 {
258  pixel_step = step;
259 }
260 
261 
262 /** Get pixel step.
263  * @return pixel step.
264  * @see setPixelStep()
265  */
266 unsigned int
267 ROI::get_pixel_step() const
268 {
269  return pixel_step;
270 }
271 
272 
273 /** Get hint.
274  * The hint gives an intuition what is in the ROI. In most cases this will
275  * depend on the color that the classifier used.
276  * @return hint
277  */
278 unsigned int
279 ROI::get_hint() const
280 {
281  return hint;
282 }
283 
284 
285 /** Set hint.
286  * @param hint new hint
287  * @see getHint()
288  */
289 void
290 ROI::set_hint(unsigned int hint)
291 {
292  this->hint = hint;
293 }
294 
295 
296 /** Check if this ROI contains the given coordinates.
297  * @param x x coordinate in image
298  * @param y y coordinate in image
299  * @return true if this ROI contains the given point, false otherwise
300  */
301 bool
302 ROI::contains(unsigned int x, unsigned int y)
303 {
304  if ( (x >= start.x) &&
305  (x <= start.x+width) &&
306  (y >= start.y) &&
307  (y <= start.y+height) ) {
308 
309  num_hint_points += 1;
310  return true;
311  } else {
312  return false;
313  }
314 }
315 
316 
317 /** Check if this ROI neighbours a pixel.
318  * This checks if the given pixel is close to this ROI considered with
319  * the given margin.
320  * @param x x coordinate in image
321  * @param y y coordinate in image
322  * @param margin margin
323  * @return true if this ROI is a neigbour of the given pixel, false otherwise
324  */
325 bool
326 ROI::neighbours(unsigned int x, unsigned int y, unsigned int margin) const
327 {
328  return ( (static_cast<int>(x) >= static_cast<int>(start.x) - static_cast<int>(margin)) &&
329  (x <= start.x + width + margin) &&
330  (static_cast<int>(y) >= static_cast<int>(start.y) - static_cast<int>(margin)) &&
331  (y <= start.y + height + margin) );
332 }
333 
334 
335 /** Check if this ROI neighbours another ROI.
336  * This checks if the given ROI is close to this ROI considered with
337  * the given margin.
338  * @param roi ROI
339  * @param margin margin
340  * @return true if this ROI is a neigbour of the given ROI, false otherwise
341  */
342 bool
343 ROI::neighbours(ROI *roi, unsigned int margin) const
344 {
345  //Testing only x -> y test returns always true
346  bool overlapping_x = neighbours(roi->start.x, start.y, margin)
347  || neighbours(roi->start.x + roi->width, start.y, margin)
348  || roi->neighbours(start.x, roi->start.y, margin)
349  || roi->neighbours(start.x + width, roi->start.y, margin);
350 
351  //Testing only y -> x test returns always true
352  bool overlapping_y = roi->neighbours(roi->start.x, start.y, margin)
353  || roi->neighbours(roi->start.x, start.y + height, margin)
354  || neighbours(start.x, roi->start.y, margin)
355  || neighbours(start.x, roi->start.y + roi->height, margin);
356 
357  return overlapping_x && overlapping_y;
358 }
359 
360 
361 /** Extend ROI to include given pixel.
362  * @param x x coordinate of pixel to include
363  * @param y y coordinate of pixel to include
364  */
365 void
366 ROI::extend(unsigned int x, unsigned int y)
367 {
368 
369  if (x < start.x) { width += start.x - x; start.x = x; }
370  if (y < start.y) { height += start.y - y; start.y = y; }
371  if (x > start.x + width) { width += (x - (start.x + width)); }
372  if (y > start.y + height) { height += (y - (start.y + height)); }
373 
374  num_hint_points += 1;
375 }
376 
377 
378 /** Grow this ROI by a given margin.
379  * @param margin margin to grow by
380  */
381 void
382 ROI::grow(unsigned int margin)
383 {
384  if (start.x < margin) {
385  start.x = 0;
386  } else {
387  start.x -= margin;
388  }
389 
390  if (start.y < margin) {
391  start.y = 0;
392  } else {
393  start.y -= margin;
394  }
395 
396  if ((start.x + width + margin) > image_width) {
397  width += (image_width - (start.x + width));
398  } else {
399  width += margin;
400  }
401 
402  if ((start.y + height + margin) > image_height) {
403  height += (image_height - (start.y + height));
404  } else {
405  height += margin;
406  }
407 
408 }
409 
410 
411 /** Merge two ROIs.
412  * This ROI will be extended in any direction necessary to fully include the given
413  * ROI.
414  * @param roi ROI to include
415  * @return this instance
416  */
417 ROI&
418 ROI::operator+=(ROI &roi)
419 {
420 
421  if (roi.start.x < start.x) { width += start.x - roi.start.x; start.x = roi.start.x; }
422  if (roi.start.y < start.y) { height += start.y - roi.start.y; start.y = roi.start.y; }
423  if (roi.start.x + roi.width > start.x + width) { width += roi.start.x + roi.width - (start.x + width); }
424  if (roi.start.y + roi.height > start.y + height) { height += roi.start.y + roi.height - (start.y + height); }
425 
426  num_hint_points += roi.num_hint_points;
427 
428  return *this;
429 }
430 
431 
432 /** Check if this ROI contains less hint points than the given ROI.
433  * @param roi ROI to compare to.
434  * @return true, if the this ROI is smaller, false otherwise
435  */
436 bool
437 ROI::operator<(const ROI &roi) const
438 {
439  return (color < roi.color) || (num_hint_points < roi.num_hint_points);
440 }
441 
442 
443 /** Check if this ROI contains more hint points than the given ROI.
444  * @param roi ROI to compare to.
445  * @return true, if the this ROI is greater, false otherwise
446  */
447 bool
448 ROI::operator>(const ROI &roi) const
449 {
450  return (color > roi.color) || (num_hint_points > roi.num_hint_points);
451 }
452 
453 
454 /** Check if this ROI marks the same region for the same object
455  * and an image of the same base size and step parameters like the
456  * given ROI.
457  * @param roi ROI to compare to
458  * @return true, if ROIs are similar, false otherwise
459  */
460 bool
461 ROI::operator==(const ROI &roi) const
462 {
463  return (start.x == roi.start.x) &&
464  (start.y == roi.start.y) &&
465  (width == roi.width) &&
466  (height == roi.height) &&
467  (image_width == roi.image_width) &&
468  (image_height == roi.image_height) &&
469  (line_step == roi.line_step) &&
470  (pixel_step == roi.pixel_step) &&
471  (hint == roi.hint) &&
472  (color == roi.color) &&
473  (num_hint_points == roi.num_hint_points);
474 }
475 
476 
477 /** Check if this ROI does not mark the same region for the same object
478  * and an image of the same base size and step parameters like the
479  * given ROI.
480  * @param roi ROI to compare to
481  * @return true, if ROIs are not similar, false otherwise
482  */
483 bool
484 ROI::operator!=(const ROI &roi) const
485 {
486  return (num_hint_points != roi.num_hint_points);
487 }
488 
489 
490 /** Assign the given ROI data to this ROI.
491  * @param roi ROI to copy
492  * @return this instance
493  */
494 ROI&
495 ROI::operator=(const ROI &roi)
496 {
497  this->start.x = roi.start.x;
498  this->start.y = roi.start.y;
499  this->width = roi.width;
500  this->height = roi.height;
501  this->image_width = roi.image_width;
502  this->image_height = roi.image_height;
503  this->line_step = roi.line_step;
504  this->pixel_step = roi.pixel_step;
505  this->hint = roi.hint;
506  this->color = roi.color;
507  this->num_hint_points = roi.num_hint_points;
508 
509  return *this;
510 }
511 
512 /** Get ROI buffer start.
513  * This uses the ROI's step and start data to calculate where
514  * the ROI starts in the given buffer.
515  * @param buffer buffer
516  * @return pointer into buffer where the ROI starts
517  */
518 unsigned char*
519 ROI::get_roi_buffer_start(unsigned char *buffer) const
520 {
521  return (buffer + (start.y * line_step) + (start.x * pixel_step));
522 }
523 
524 
525 /** Gives an estimate of the number of points in this ROI that
526  * are classified to the given hint
527  * It is: num_hint_points <= total_num_of_scanline_points
528  * If you call contains and the point is actually included in
529  * this ROI this number is incremented. So you need to make
530  * sure to only call contains() for a point of the given hint
531  * class. This should always be the case anyway.
532  * If you extend the region by one very point the number will
533  * be incremented by one although the region may grow by more
534  * than just one point of the hint class.
535  * If you merge to ROIs by using the += operator this region
536  * adds the number of hint points of the region being merged
537  * to its own number. The region may grow by more than this
538  * number of points though.
539  * @return an estimate of the number of points of the hint class
540  *
541  */
542 unsigned int
543 ROI::get_num_hint_points() const
544 {
545  return num_hint_points;
546 }
547 
548 
549 /** Get full image ROI for given size.
550  * Shortcut to get a full size ROI. This ROI is a static member so this
551  * method is not thread-safe or reentrant. It is also only valid until the
552  * next call to full_image() with different parameters. Line step is assumed
553  * to be the image width, the pixel step is assumed to be one. So this is
554  * only useful for b/w or planar images.
555  * @param width image width
556  * @param height image height
557  * @return full image ROI
558  */
559 ROI *
560 ROI::full_image(unsigned int width, unsigned int height)
561 {
562  if (roi_full_image == NULL) {
563  roi_full_image = new ROI();
564  roi_full_image->start.x = 0;
565  roi_full_image->start.y = 0;
566  roi_full_image->pixel_step = 1;
567  }
568  roi_full_image->width = width;
569  roi_full_image->height = height;
570  roi_full_image->image_width = roi_full_image->width;
571  roi_full_image->image_height = roi_full_image->height;
572  roi_full_image->line_step = roi_full_image->width;
573 
574  return roi_full_image;
575 }
576 
577 } // end namespace firevision
Fawkes library namespace.
fawkes::point_t start
ROI start.
Definition: roi.h:118
unsigned int x
x coordinate
Definition: types.h:35
unsigned int width
ROI width.
Definition: roi.h:120
bool neighbours(unsigned int x, unsigned int y, unsigned int margin) const
Check if this ROI neighbours a pixel.
Definition: roi.cpp:326
Region of interest.
Definition: roi.h:58
unsigned int image_width
width of image that contains this ROI
Definition: roi.h:124
Point with cartesian coordinates as unsigned integers.
Definition: types.h:34
unsigned int image_height
height of image that contains this ROI
Definition: roi.h:126
unsigned int y
y coordinate
Definition: types.h:36
unsigned int hint
ROI hint.
Definition: roi.h:132
unsigned int height
ROI height.
Definition: roi.h:122
unsigned int line_step
line step
Definition: roi.h:128
unsigned int num_hint_points
Minimum estimate of points in ROI that are attributed to the ROI hint.
Definition: roi.h:138
unsigned int pixel_step
pixel step
Definition: roi.h:130
color_t color
ROI primary color.
Definition: roi.h:135