shrinker.cpp
00001 00002 /*************************************************************************** 00003 * shrinker.cpp - Implementation of Shrinker 00004 * 00005 * Generated: Wed Aug 31 2005 21:52:28 00006 * Copyright 2005 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 <classifiers/shrinker.h> 00025 #include <fvutils/color/colorspaces.h> 00026 #include <fvutils/base/roi.h> 00027 00028 #include <cstddef> 00029 00030 /** @class Shrinker <classifiers/shrinker.h> 00031 * Shrinker class to shrink ROIs. 00032 * This shrinker shrinks a given ROI. This is done to cope with several 00033 * special problems that arise in different setups. For example if playing 00034 * downstairs in the lobby without a carpet we always have a problem with 00035 * reflections on the floor. 00036 * 00037 * This shrinker works like this: 00038 * - if ROI is vertically rectangular, we cut off the bottom part 00039 * because it is likely to contain reflection 00040 * - if ball is not close (roi->width <= 100), we tighten the ROI, such that 00041 * it only contains the ball. This helps against reflection. 00042 * (If ball is close, this does not work, because it takes away too many edge pixels.) 00043 */ 00044 00045 /** Constructor. */ 00046 Shrinker::Shrinker() 00047 { 00048 src = NULL; 00049 } 00050 00051 00052 /** Destructor. */ 00053 Shrinker::~Shrinker() 00054 { 00055 } 00056 00057 00058 /** Set the filtered buffer. 00059 * The buffer is assumed to being YUV422_PLANAR mode and the desired filter 00060 * combination has been run. 00061 * @param yuv422planar_buffer YUV422 planar buffer 00062 */ 00063 void 00064 Shrinker::setFilteredBuffer(unsigned char *yuv422planar_buffer) { 00065 src = yuv422planar_buffer; 00066 } 00067 00068 00069 /** Shrink! 00070 * Do the actual shrinking. See above for used method. 00071 * @param roi ROI to srhink 00072 */ 00073 void 00074 Shrinker::shrink( ROI *roi ) 00075 { 00076 00077 unsigned int x; 00078 unsigned int y; 00079 00080 /* if ROI is vertically rectangular, we cut off the bottom part 00081 because it is likely to contain reflection */ 00082 if (roi->height > roi->width) { 00083 roi->height = roi->width; 00084 } 00085 00086 if ( roi->width <= 100 ) { 00087 /* Ball is not close. Tighten ROI, such that it only contains the ball. 00088 This helps against reflection. 00089 (If ball is close, this does not work, because it takes away too many edge pixels.) */ 00090 00091 unsigned char *bufferTmp = roi->get_roi_buffer_start( src ); 00092 unsigned char *line_startTmp = bufferTmp; 00093 fawkes::point_t leftmostPixel = {roi->width, 0}; 00094 fawkes::point_t topmostPixel = {0, roi->height}; 00095 00096 // find leftmost hint-pixel 00097 bool pixelFound = false; 00098 for (x = 0; !pixelFound && (x < roi->width / 2); ++x) { 00099 for (y = 0; y < roi->height/2; ++y) { 00100 if (*bufferTmp > 230) { // if pixel is white or almost white = edge 00101 leftmostPixel.x = x; 00102 leftmostPixel.y = y; 00103 pixelFound = true; 00104 } 00105 ++bufferTmp; 00106 } // inner for 00107 line_startTmp += roi->line_step; 00108 bufferTmp = line_startTmp; 00109 } // outer for 00110 00111 bufferTmp = roi->get_roi_buffer_start( src ); 00112 line_startTmp = bufferTmp; 00113 00114 // find topmost hint-pixel 00115 pixelFound = false; 00116 for (y = 0; !pixelFound && (y < roi->height/2); ++y) { 00117 for (x = 0; x < roi->width; ++x) { 00118 if (*bufferTmp > 230) { 00119 topmostPixel.x = x; 00120 topmostPixel.y = y; 00121 pixelFound = true; 00122 } 00123 ++bufferTmp; 00124 } // inner for 00125 /* 00126 if (pixelFound) { 00127 // try to improve x-coordinate (too small) 00128 unsigned int x2 = topmostPixel.x; 00129 for (unsigned int a = topmostPixel.x + 1; a < roi->width; ++a) { 00130 if (TEST_IF_IS_A_PIXEL(*bufferTmp)) { 00131 x2 = a; 00132 } 00133 ++bufferTmp; 00134 } 00135 topmostPixel.x = (topmostPixel.x + x2) / 2; 00136 } 00137 */ 00138 line_startTmp += roi->line_step; 00139 bufferTmp = line_startTmp; 00140 } // outer for 00141 00142 bufferTmp = roi->get_roi_buffer_start( src ); 00143 line_startTmp = bufferTmp; 00144 00145 // tighten ROI if it makes sense 00146 if ( (leftmostPixel.x >= topmostPixel.x) || 00147 (topmostPixel.y >= leftmostPixel.y) || 00148 (2 * (topmostPixel.x - leftmostPixel.x) >= roi->width) || 00149 (2 * (leftmostPixel.y - topmostPixel.y) >= roi->height) ) { 00150 // bad pixels found 00151 } else { 00152 // tighten ROI 00153 // roi->start.x += leftmostPixel.x; 00154 // roi->start.y += topmostPixel.y; 00155 // roi->height -= topmostPixel.y; 00156 //roi->width = 2 * (topmostPixel.x - leftmostPixel.x); 00157 roi->height = 2 * (leftmostPixel.y - topmostPixel.y); 00158 /* 00159 if ( roi->width < roi->height ) { 00160 // further shrinking 00161 roi->height = roi->width; 00162 } 00163 */ 00164 //cout << "Shrinker: Shrank region!" << endl; 00165 } 00166 } // else do nothing 00167 00168 }

