Fawkes API
Fawkes Development Version
|
00001 00002 /*************************************************************************** 00003 * roi.cpp - Implementation for Region Of Interest (ROI) representation 00004 * 00005 * Generated: Thu Jul 14 12:01:58 2005 00006 * Copyright 2005-2007 Tim Niemueller [www.niemueller.de] 00007 * 00008 ****************************************************************************/ 00009 00010 /* This program is free software; you can redistribute it and/or modify 00011 * it under the terms of the GNU General Public License as published by 00012 * the Free Software Foundation; either version 2 of the License, or 00013 * (at your option) any later version. A runtime exception applies to 00014 * this software (see LICENSE.GPL_WRE file mentioned below for details). 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU Library General Public License for more details. 00020 * 00021 * Read the full text in the LICENSE.GPL_WRE file in the doc directory. 00022 */ 00023 00024 #include <fvutils/base/roi.h> 00025 00026 #include <cstdlib> 00027 00028 using namespace fawkes; 00029 00030 namespace firevision { 00031 #if 0 /* just to make Emacs auto-indent happy */ 00032 } 00033 #endif 00034 00035 /** @class ROI <fvutils/base/roi.h> 00036 * Region of interest. 00037 * The ROI class is central to FireVision. All image processing is concentrated 00038 * on the pre-classified interesting parts of the image, denoted by the 00039 * regions of interest (ROIs). 00040 * 00041 * A ROI is a rectangular area of the image. Its start is denoted by the upper 00042 * left corner of this rectangle and the size is given by its width and height. 00043 * 00044 * @author Tim Niemueller 00045 */ 00046 00047 ROI* ROI::roi_full_image = NULL; 00048 00049 00050 /** Constructor. */ 00051 ROI::ROI() 00052 { 00053 num_hint_points = 1; 00054 start.x = start.y = width = height = image_width = image_height = line_step = pixel_step = 0; 00055 color = C_BACKGROUND; 00056 } 00057 00058 00059 /** Constructor. 00060 * @param start_x Upper left corner of ROI X coordinate 00061 * @param start_y Upper left corner of ROI y coordinate 00062 * @param width Width of extent of ROI 00063 * @param height height of extent of ROI 00064 * @param image_width width of full image this ROI belongs to 00065 * @param image_height height of full image this ROI belongs to 00066 */ 00067 ROI::ROI(unsigned int start_x, unsigned int start_y, 00068 unsigned int width, unsigned int height, 00069 unsigned int image_width, unsigned int image_height) 00070 { 00071 num_hint_points = 1; 00072 start.x = start_x; 00073 start.y = start_y; 00074 this->width = width; 00075 this->height = height; 00076 this->image_width = image_width; 00077 this->image_height = image_height; 00078 line_step = image_width; 00079 pixel_step = 1; 00080 color = C_BACKGROUND; 00081 } 00082 00083 00084 /** Copy constructor. 00085 * @param roi reference to ROI to copy 00086 */ 00087 ROI::ROI(const ROI &roi) 00088 { 00089 start = roi.start; 00090 width = roi.width; 00091 height = roi.height; 00092 image_width = roi.image_width; 00093 image_height = roi.image_height; 00094 line_step = roi.line_step; 00095 pixel_step = roi.pixel_step; 00096 hint = roi.hint; 00097 color = roi.color; 00098 num_hint_points = roi.num_hint_points; 00099 } 00100 00101 00102 /** Copy constructor. 00103 * @param roi pointer to ROI to copy 00104 */ 00105 ROI::ROI(const ROI *roi) 00106 { 00107 start = roi->start; 00108 width = roi->width; 00109 height = roi->height; 00110 image_width = roi->image_width; 00111 image_height = roi->image_height; 00112 line_step = roi->line_step; 00113 pixel_step = roi->pixel_step; 00114 hint = roi->hint; 00115 color = roi->color; 00116 num_hint_points = roi->num_hint_points; 00117 } 00118 00119 00120 /** Set upper left corner of ROI. 00121 * @param p point 00122 */ 00123 void 00124 ROI::set_start(point_t p) 00125 { 00126 start.x = p.x; 00127 start.y = p.y; 00128 } 00129 00130 00131 /** Set upper left corner. 00132 * @param x x coordinate in image 00133 * @param y y coordinate in image 00134 */ 00135 void 00136 ROI::set_start(unsigned int x, unsigned int y) 00137 { 00138 start.x = x; 00139 start.y = y; 00140 } 00141 00142 00143 /** Set width of ROI. 00144 * @param width new width 00145 */ 00146 void 00147 ROI::set_width(unsigned int width) 00148 { 00149 this->width = width; 00150 } 00151 00152 00153 /** Get width of ROI. 00154 * @return width 00155 */ 00156 unsigned int 00157 ROI::get_width() const 00158 { 00159 return width; 00160 } 00161 00162 00163 /** Set height of ROI. 00164 * @param height new height 00165 */ 00166 void 00167 ROI::set_height(unsigned int height) 00168 { 00169 this->height = height; 00170 } 00171 00172 00173 /** Get height of ROI. 00174 * @return height 00175 */ 00176 unsigned int 00177 ROI::get_height() const 00178 { 00179 return height; 00180 } 00181 00182 00183 /** Set full image width. 00184 * Set the width of the image that contains this ROI. 00185 * @param image_width full width of image. 00186 */ 00187 void 00188 ROI::set_image_width(unsigned int image_width) 00189 { 00190 this->image_width = image_width; 00191 } 00192 00193 00194 /** Get full image width. 00195 * Get the width of the image that contains this ROI. 00196 * @return full width of image. 00197 */ 00198 unsigned int 00199 ROI::get_image_width() const 00200 { 00201 return image_width; 00202 } 00203 00204 00205 /** Set full image height 00206 * Set the height of the image that contains this ROI. 00207 * @param image_height full height of image. 00208 */ 00209 void 00210 ROI::set_image_height(unsigned int image_height) 00211 { 00212 this->image_height = image_height; 00213 } 00214 00215 00216 /** Get full image height. 00217 * Get the height of the image that contains this ROI. 00218 * @return full height of image. 00219 */ 00220 unsigned int 00221 ROI::get_image_height() const 00222 { 00223 return image_height; 00224 } 00225 00226 00227 /** Set linestep. 00228 * The linestep is the offset in bytes from the beginning of one line 00229 * in the buffer to the beginning of the next line. 00230 * @param step new line step 00231 */ 00232 void 00233 ROI::set_line_step(unsigned int step) 00234 { 00235 line_step = step; 00236 } 00237 00238 00239 /** Get linestep. 00240 * @return line step 00241 * @see setLineStep() 00242 */ 00243 unsigned int 00244 ROI::get_line_step() const 00245 { 00246 return line_step; 00247 } 00248 00249 00250 /** Set pixel step. 00251 * The pixel step is the offset in bytes to get from one pixel to the next 00252 * in the buffer. 00253 * @param step new pixel step. 00254 */ 00255 void 00256 ROI::set_pixel_step(unsigned int step) 00257 { 00258 pixel_step = step; 00259 } 00260 00261 00262 /** Get pixel step. 00263 * @return pixel step. 00264 * @see setPixelStep() 00265 */ 00266 unsigned int 00267 ROI::get_pixel_step() const 00268 { 00269 return pixel_step; 00270 } 00271 00272 00273 /** Get hint. 00274 * The hint gives an intuition what is in the ROI. In most cases this will 00275 * depend on the color that the classifier used. 00276 * @return hint 00277 */ 00278 unsigned int 00279 ROI::get_hint() const 00280 { 00281 return hint; 00282 } 00283 00284 00285 /** Set hint. 00286 * @param hint new hint 00287 * @see getHint() 00288 */ 00289 void 00290 ROI::set_hint(unsigned int hint) 00291 { 00292 this->hint = hint; 00293 } 00294 00295 00296 /** Check if this ROI contains the given coordinates. 00297 * @param x x coordinate in image 00298 * @param y y coordinate in image 00299 * @return true if this ROI contains the given point, false otherwise 00300 */ 00301 bool 00302 ROI::contains(unsigned int x, unsigned int y) 00303 { 00304 if ( (x >= start.x) && 00305 (x <= start.x+width) && 00306 (y >= start.y) && 00307 (y <= start.y+height) ) { 00308 00309 num_hint_points += 1; 00310 return true; 00311 } else { 00312 return false; 00313 } 00314 } 00315 00316 00317 /** Check if this ROI neighbours a pixel. 00318 * This checks if the given pixel is close to this ROI considered with 00319 * the given margin. 00320 * @param x x coordinate in image 00321 * @param y y coordinate in image 00322 * @param margin margin 00323 * @return true if this ROI is a neigbour of the given pixel, false otherwise 00324 */ 00325 bool 00326 ROI::neighbours(unsigned int x, unsigned int y, unsigned int margin) const 00327 { 00328 return ( (static_cast<int>(x) >= static_cast<int>(start.x) - static_cast<int>(margin)) && 00329 (x <= start.x + width + margin) && 00330 (static_cast<int>(y) >= static_cast<int>(start.y) - static_cast<int>(margin)) && 00331 (y <= start.y + height + margin) ); 00332 } 00333 00334 00335 /** Check if this ROI neighbours another ROI. 00336 * This checks if the given ROI is close to this ROI considered with 00337 * the given margin. 00338 * @param roi ROI 00339 * @param margin margin 00340 * @return true if this ROI is a neigbour of the given ROI, false otherwise 00341 */ 00342 bool 00343 ROI::neighbours(ROI *roi, unsigned int margin) const 00344 { 00345 //Testing only x -> y test returns always true 00346 bool overlapping_x = neighbours(roi->start.x, start.y, margin) 00347 || neighbours(roi->start.x + roi->width, start.y, margin) 00348 || roi->neighbours(start.x, roi->start.y, margin) 00349 || roi->neighbours(start.x + width, roi->start.y, margin); 00350 00351 //Testing only y -> x test returns always true 00352 bool overlapping_y = roi->neighbours(roi->start.x, start.y, margin) 00353 || roi->neighbours(roi->start.x, start.y + height, margin) 00354 || neighbours(start.x, roi->start.y, margin) 00355 || neighbours(start.x, roi->start.y + roi->height, margin); 00356 00357 return overlapping_x && overlapping_y; 00358 } 00359 00360 00361 /** Extend ROI to include given pixel. 00362 * @param x x coordinate of pixel to include 00363 * @param y y coordinate of pixel to include 00364 */ 00365 void 00366 ROI::extend(unsigned int x, unsigned int y) 00367 { 00368 00369 if (x < start.x) { width += start.x - x; start.x = x; } 00370 if (y < start.y) { height += start.y - y; start.y = y; } 00371 if (x > start.x + width) { width += (x - (start.x + width)); } 00372 if (y > start.y + height) { height += (y - (start.y + height)); } 00373 00374 num_hint_points += 1; 00375 } 00376 00377 00378 /** Grow this ROI by a given margin. 00379 * @param margin margin to grow by 00380 */ 00381 void 00382 ROI::grow(unsigned int margin) 00383 { 00384 if (start.x < margin) { 00385 start.x = 0; 00386 } else { 00387 start.x -= margin; 00388 } 00389 00390 if (start.y < margin) { 00391 start.y = 0; 00392 } else { 00393 start.y -= margin; 00394 } 00395 00396 if ((start.x + width + margin) > image_width) { 00397 width += (image_width - (start.x + width)); 00398 } else { 00399 width += margin; 00400 } 00401 00402 if ((start.y + height + margin) > image_height) { 00403 height += (image_height - (start.y + height)); 00404 } else { 00405 height += margin; 00406 } 00407 00408 } 00409 00410 00411 /** Merge two ROIs. 00412 * This ROI will be extended in any direction necessary to fully include the given 00413 * ROI. 00414 * @param roi ROI to include 00415 * @return this instance 00416 */ 00417 ROI& 00418 ROI::operator+=(ROI &roi) 00419 { 00420 00421 if (roi.start.x < start.x) { width += start.x - roi.start.x; start.x = roi.start.x; } 00422 if (roi.start.y < start.y) { height += start.y - roi.start.y; start.y = roi.start.y; } 00423 if (roi.start.x + roi.width > start.x + width) { width += roi.start.x + roi.width - (start.x + width); } 00424 if (roi.start.y + roi.height > start.y + height) { height += roi.start.y + roi.height - (start.y + height); } 00425 00426 num_hint_points += roi.num_hint_points; 00427 00428 return *this; 00429 } 00430 00431 00432 /** Check if this ROI contains less hint points than the given ROI. 00433 * @param roi ROI to compare to. 00434 * @return true, if the this ROI is smaller, false otherwise 00435 */ 00436 bool 00437 ROI::operator<(const ROI &roi) const 00438 { 00439 return (color < roi.color) || (num_hint_points < roi.num_hint_points); 00440 } 00441 00442 00443 /** Check if this ROI contains more hint points than the given ROI. 00444 * @param roi ROI to compare to. 00445 * @return true, if the this ROI is greater, false otherwise 00446 */ 00447 bool 00448 ROI::operator>(const ROI &roi) const 00449 { 00450 return (color > roi.color) || (num_hint_points > roi.num_hint_points); 00451 } 00452 00453 00454 /** Check if this ROI marks the same region for the same object 00455 * and an image of the same base size and step parameters like the 00456 * given ROI. 00457 * @param roi ROI to compare to 00458 * @return true, if ROIs are similar, false otherwise 00459 */ 00460 bool 00461 ROI::operator==(const ROI &roi) const 00462 { 00463 return (start.x == roi.start.x) && 00464 (start.y == roi.start.y) && 00465 (width == roi.width) && 00466 (height == roi.height) && 00467 (image_width == roi.image_width) && 00468 (image_height == roi.image_height) && 00469 (line_step == roi.line_step) && 00470 (pixel_step == roi.pixel_step) && 00471 (hint == roi.hint) && 00472 (color == roi.color) && 00473 (num_hint_points == roi.num_hint_points); 00474 } 00475 00476 00477 /** Check if this ROI does not mark the same region for the same object 00478 * and an image of the same base size and step parameters like the 00479 * given ROI. 00480 * @param roi ROI to compare to 00481 * @return true, if ROIs are not similar, false otherwise 00482 */ 00483 bool 00484 ROI::operator!=(const ROI &roi) const 00485 { 00486 return (num_hint_points != roi.num_hint_points); 00487 } 00488 00489 00490 /** Assign the given ROI data to this ROI. 00491 * @param roi ROI to copy 00492 * @return this instance 00493 */ 00494 ROI& 00495 ROI::operator=(const ROI &roi) 00496 { 00497 this->start.x = roi.start.x; 00498 this->start.y = roi.start.y; 00499 this->width = roi.width; 00500 this->height = roi.height; 00501 this->image_width = roi.image_width; 00502 this->image_height = roi.image_height; 00503 this->line_step = roi.line_step; 00504 this->pixel_step = roi.pixel_step; 00505 this->hint = roi.hint; 00506 this->color = roi.color; 00507 this->num_hint_points = roi.num_hint_points; 00508 00509 return *this; 00510 } 00511 00512 /** Get ROI buffer start. 00513 * This uses the ROI's step and start data to calculate where 00514 * the ROI starts in the given buffer. 00515 * @param buffer buffer 00516 * @return pointer into buffer where the ROI starts 00517 */ 00518 unsigned char* 00519 ROI::get_roi_buffer_start(unsigned char *buffer) const 00520 { 00521 return (buffer + (start.y * line_step) + (start.x * pixel_step)); 00522 } 00523 00524 00525 /** Gives an estimate of the number of points in this ROI that 00526 * are classified to the given hint 00527 * It is: num_hint_points <= total_num_of_scanline_points 00528 * If you call contains and the point is actually included in 00529 * this ROI this number is incremented. So you need to make 00530 * sure to only call contains() for a point of the given hint 00531 * class. This should always be the case anyway. 00532 * If you extend the region by one very point the number will 00533 * be incremented by one although the region may grow by more 00534 * than just one point of the hint class. 00535 * If you merge to ROIs by using the += operator this region 00536 * adds the number of hint points of the region being merged 00537 * to its own number. The region may grow by more than this 00538 * number of points though. 00539 * @return an estimate of the number of points of the hint class 00540 * 00541 */ 00542 unsigned int 00543 ROI::get_num_hint_points() const 00544 { 00545 return num_hint_points; 00546 } 00547 00548 00549 /** Get full image ROI for given size. 00550 * Shortcut to get a full size ROI. This ROI is a static member so this 00551 * method is not thread-safe or reentrant. It is also only valid until the 00552 * next call to full_image() with different parameters. Line step is assumed 00553 * to be the image width, the pixel step is assumed to be one. So this is 00554 * only useful for b/w or planar images. 00555 * @param width image width 00556 * @param height image height 00557 * @return full image ROI 00558 */ 00559 ROI * 00560 ROI::full_image(unsigned int width, unsigned int height) 00561 { 00562 if (roi_full_image == NULL) { 00563 roi_full_image = new ROI(); 00564 roi_full_image->start.x = 0; 00565 roi_full_image->start.y = 0; 00566 roi_full_image->pixel_step = 1; 00567 } 00568 roi_full_image->width = width; 00569 roi_full_image->height = height; 00570 roi_full_image->image_width = roi_full_image->width; 00571 roi_full_image->image_height = roi_full_image->height; 00572 roi_full_image->line_step = roi_full_image->width; 00573 00574 return roi_full_image; 00575 } 00576 00577 } // end namespace firevision