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