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(upoint_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 /** Intersect this ROI with another.
318  * @param roi The other roi
319  * @return A new ROI that covers the intersection of this and the other ROI.
320  * If there's no intersection, width = height = 0.
321  */
322 ROI
323 ROI::intersect(ROI const &roi) const
324 {
325  ROI rv;
326  if (start.x + width <= roi.start.x
327  || roi.start.x + roi.width <= start.x
328  || start.y + height <= roi.start.y
329  || roi.start.y + roi.height <= start.y) {
330 
331  return rv;
332 
333  } else {
334 
335  rv = new ROI(this);
336  rv.start.x = start.x <= roi.start.x ? roi.start.x : start.x;
337  rv.start.y = start.y <= roi.start.y ? roi.start.y : start.y;
338  if (start.x + width < roi.start.x + roi.width) {
339  rv.width = start.x + width - rv.start.x;
340  } else {
341  rv.width = roi.start.x + roi.width - rv.start.x;
342  }
343  if (start.y + height < roi.start.y + roi.height) {
344  rv.height = start.y + height - rv.start.y;
345  } else {
346  rv.height = roi.start.y + roi.height - rv.start.y;
347  }
348 
349  }
350  return rv;
351 }
352 
353 
354 /** Check if this ROI neighbours a pixel.
355  * This checks if the given pixel is close to this ROI considered with
356  * the given margin.
357  * @param x x coordinate in image
358  * @param y y coordinate in image
359  * @param margin margin
360  * @return true if this ROI is a neigbour of the given pixel, false otherwise
361  */
362 bool
363 ROI::neighbours(unsigned int x, unsigned int y, unsigned int margin) const
364 {
365  return ( (static_cast<int>(x) >= static_cast<int>(start.x) - static_cast<int>(margin)) &&
366  (x <= start.x + width + margin) &&
367  (static_cast<int>(y) >= static_cast<int>(start.y) - static_cast<int>(margin)) &&
368  (y <= start.y + height + margin) );
369 }
370 
371 
372 /** Check if this ROI neighbours another ROI.
373  * This checks if the given ROI is close to this ROI considered with
374  * the given margin.
375  * @param roi ROI
376  * @param margin margin
377  * @return true if this ROI is a neigbour of the given ROI, false otherwise
378  */
379 bool
380 ROI::neighbours(ROI *roi, unsigned int margin) const
381 {
382  //Testing only x -> y test returns always true
383  bool overlapping_x = neighbours(roi->start.x, start.y, margin)
384  || neighbours(roi->start.x + roi->width, start.y, margin)
385  || roi->neighbours(start.x, roi->start.y, margin)
386  || roi->neighbours(start.x + width, roi->start.y, margin);
387 
388  //Testing only y -> x test returns always true
389  bool overlapping_y = roi->neighbours(roi->start.x, start.y, margin)
390  || roi->neighbours(roi->start.x, start.y + height, margin)
391  || neighbours(start.x, roi->start.y, margin)
392  || neighbours(start.x, roi->start.y + roi->height, margin);
393 
394  return overlapping_x && overlapping_y;
395 }
396 
397 
398 /** Extend ROI to include given pixel.
399  * @param x x coordinate of pixel to include
400  * @param y y coordinate of pixel to include
401  */
402 void
403 ROI::extend(unsigned int x, unsigned int y)
404 {
405 
406  if (x < start.x) { width += start.x - x; start.x = x; }
407  if (y < start.y) { height += start.y - y; start.y = y; }
408  if (x >= start.x + width) { width += (x - (start.x + width) + 1); }
409  if (y >= start.y + height) { height += (y - (start.y + height) + 1); }
410 
411  num_hint_points += 1;
412 }
413 
414 
415 /** Grow this ROI by a given margin.
416  * @param margin margin to grow by
417  */
418 void
419 ROI::grow(unsigned int margin)
420 {
421  if (start.x < margin) {
422  start.x = 0;
423  } else {
424  start.x -= margin;
425  }
426 
427  if (start.y < margin) {
428  start.y = 0;
429  } else {
430  start.y -= margin;
431  }
432 
433  if ((start.x + width + margin) > image_width) {
434  width += (image_width - (start.x + width));
435  } else {
436  width += margin;
437  }
438 
439  if ((start.y + height + margin) > image_height) {
440  height += (image_height - (start.y + height));
441  } else {
442  height += margin;
443  }
444 
445 }
446 
447 
448 /** Merge two ROIs.
449  * This ROI will be extended in any direction necessary to fully include the given
450  * ROI.
451  * @param roi ROI to include
452  * @return this instance
453  */
454 ROI&
455 ROI::operator+=(ROI &roi)
456 {
457 
458  if (roi.start.x < start.x) { width += start.x - roi.start.x; start.x = roi.start.x; }
459  if (roi.start.y < start.y) { height += start.y - roi.start.y; start.y = roi.start.y; }
460  if (roi.start.x + roi.width > start.x + width) { width += roi.start.x + roi.width - (start.x + width); }
461  if (roi.start.y + roi.height > start.y + height) { height += roi.start.y + roi.height - (start.y + height); }
462 
463  num_hint_points += roi.num_hint_points;
464 
465  return *this;
466 }
467 
468 
469 /** Check if this ROI contains less hint points than the given ROI.
470  * @param roi ROI to compare to.
471  * @return true, if the this ROI is smaller, false otherwise
472  */
473 bool
474 ROI::operator<(const ROI &roi) const
475 {
476  return (color < roi.color) || (num_hint_points < roi.num_hint_points);
477 }
478 
479 
480 /** Check if this ROI contains more hint points than the given ROI.
481  * @param roi ROI to compare to.
482  * @return true, if the this ROI is greater, false otherwise
483  */
484 bool
485 ROI::operator>(const ROI &roi) const
486 {
487  return (color > roi.color) || (num_hint_points > roi.num_hint_points);
488 }
489 
490 
491 /** Check if this ROI marks the same region for the same object
492  * and an image of the same base size and step parameters like the
493  * given ROI.
494  * @param roi ROI to compare to
495  * @return true, if ROIs are similar, false otherwise
496  */
497 bool
498 ROI::operator==(const ROI &roi) const
499 {
500  return (start.x == roi.start.x) &&
501  (start.y == roi.start.y) &&
502  (width == roi.width) &&
503  (height == roi.height) &&
504  (image_width == roi.image_width) &&
505  (image_height == roi.image_height) &&
506  (line_step == roi.line_step) &&
507  (pixel_step == roi.pixel_step) &&
508  (hint == roi.hint) &&
509  (color == roi.color) &&
510  (num_hint_points == roi.num_hint_points);
511 }
512 
513 
514 /** Check if this ROI does not mark the same region for the same object
515  * and an image of the same base size and step parameters like the
516  * given ROI.
517  * @param roi ROI to compare to
518  * @return true, if ROIs are not similar, false otherwise
519  */
520 bool
521 ROI::operator!=(const ROI &roi) const
522 {
523  return (num_hint_points != roi.num_hint_points);
524 }
525 
526 
527 /** Assign the given ROI data to this ROI.
528  * @param roi ROI to copy
529  * @return this instance
530  */
531 ROI&
532 ROI::operator=(const ROI &roi)
533 {
534  this->start.x = roi.start.x;
535  this->start.y = roi.start.y;
536  this->width = roi.width;
537  this->height = roi.height;
538  this->image_width = roi.image_width;
539  this->image_height = roi.image_height;
540  this->line_step = roi.line_step;
541  this->pixel_step = roi.pixel_step;
542  this->hint = roi.hint;
543  this->color = roi.color;
544  this->num_hint_points = roi.num_hint_points;
545 
546  return *this;
547 }
548 
549 /** Get ROI buffer start.
550  * This uses the ROI's step and start data to calculate where
551  * the ROI starts in the given buffer.
552  * @param buffer buffer
553  * @return pointer into buffer where the ROI starts
554  */
555 unsigned char*
556 ROI::get_roi_buffer_start(unsigned char *buffer) const
557 {
558  return (buffer + (start.y * line_step) + (start.x * pixel_step));
559 }
560 
561 
562 /** Gives an estimate of the number of points in this ROI that
563  * are classified to the given hint
564  * It is: num_hint_points <= total_num_of_scanline_points
565  * If you call contains and the point is actually included in
566  * this ROI this number is incremented. So you need to make
567  * sure to only call contains() for a point of the given hint
568  * class. This should always be the case anyway.
569  * If you extend the region by one very point the number will
570  * be incremented by one although the region may grow by more
571  * than just one point of the hint class.
572  * If you merge to ROIs by using the += operator this region
573  * adds the number of hint points of the region being merged
574  * to its own number. The region may grow by more than this
575  * number of points though.
576  * @return an estimate of the number of points of the hint class
577  *
578  */
579 unsigned int
580 ROI::get_num_hint_points() const
581 {
582  return num_hint_points;
583 }
584 
585 
586 /** Get full image ROI for given size.
587  * Shortcut to get a full size ROI. This ROI is a static member so this
588  * method is not thread-safe or reentrant. It is also only valid until the
589  * next call to full_image() with different parameters. Line step is assumed
590  * to be the image width, the pixel step is assumed to be one. So this is
591  * only useful for b/w or planar images.
592  * @param width image width
593  * @param height image height
594  * @return full image ROI
595  */
596 ROI *
597 ROI::full_image(unsigned int width, unsigned int height)
598 {
599  if (roi_full_image == NULL) {
600  roi_full_image = new ROI();
601  roi_full_image->start.x = 0;
602  roi_full_image->start.y = 0;
603  roi_full_image->pixel_step = 1;
604  }
605  roi_full_image->width = width;
606  roi_full_image->height = height;
607  roi_full_image->image_width = roi_full_image->width;
608  roi_full_image->image_height = roi_full_image->height;
609  roi_full_image->line_step = roi_full_image->width;
610 
611  return roi_full_image;
612 }
613 
614 } // end namespace firevision
Fawkes library namespace.
fawkes::upoint_t start
ROI start.
Definition: roi.h:119
unsigned int y
y coordinate
Definition: types.h:36
bool neighbours(unsigned int x, unsigned int y, unsigned int margin) const
Check if this ROI neighbours a pixel.
Definition: roi.cpp:363
unsigned int x
x coordinate
Definition: types.h:35
unsigned int width
ROI width.
Definition: roi.h:121
Region of interest.
Definition: roi.h:58
unsigned int image_width
width of image that contains this ROI
Definition: roi.h:125
unsigned int image_height
height of image that contains this ROI
Definition: roi.h:127
Point with cartesian coordinates as unsigned integers.
Definition: types.h:34
unsigned int hint
ROI hint.
Definition: roi.h:133
unsigned int height
ROI height.
Definition: roi.h:123
unsigned int line_step
line step
Definition: roi.h:129
unsigned int num_hint_points
Minimum estimate of points in ROI that are attributed to the ROI hint.
Definition: roi.h:139
unsigned int pixel_step
pixel step
Definition: roi.h:131
color_t color
ROI primary color.
Definition: roi.h:136