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