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 }