hv_search.cpp

00001 
00002 /***************************************************************************
00003  *  hv_search.cpp - Implementation of horizontal- and vertical-search filter
00004  *
00005  *  Created: Tue Jul 12 14:40:40 2005
00006  *  Copyright  2005-2007  Tim Niemueller [www.niemueller.de]
00007  *             2005       Yuxiao Hu (Yuxiao.Hu@rwth-aachen.de)
00008  *
00009  ****************************************************************************/
00010 
00011 /*  This program is free software; you can redistribute it and/or modify
00012  *  it under the terms of the GNU General Public License as published by
00013  *  the Free Software Foundation; either version 2 of the License, or
00014  *  (at your option) any later version. A runtime exception applies to
00015  *  this software (see LICENSE.GPL_WRE file mentioned below for details).
00016  *
00017  *  This program is distributed in the hope that it will be useful,
00018  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00019  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020  *  GNU Library General Public License for more details.
00021  *
00022  *  Read the full text in the LICENSE.GPL_WRE file in the doc directory.
00023  */
00024 
00025 #include <filters/hv_search.h>
00026 
00027 #include <fvutils/color/yuv.h>
00028 
00029 #include <cstddef>
00030 #include <cstring>
00031 
00032 namespace firevision {
00033 #if 0 /* just to make Emacs auto-indent happy */
00034 }
00035 #endif
00036 
00037 /** @class FilterHVSearch <filters/hv_search.h>
00038  * Horizontal/vertical search filter.
00039  * This filter works similar to the horizontal search filter, but additionally
00040  * it search for color changes in vertical direction.
00041  * @author Yuxiao Hu
00042  * @author Tim Niemueller
00043  */
00044 
00045 
00046 /** Constructor.
00047  * @param cm color model to use to determine the color change
00048  * @param what what to look for, this color is considered as foreground,
00049  * all other colors are background.
00050  */
00051 FilterHVSearch::FilterHVSearch(ColorModel *cm, color_t what)
00052   : Filter("FilterHVSearch")
00053 {
00054   this->cm = cm;
00055   this->what = what;
00056 }
00057 
00058 
00059 void
00060 FilterHVSearch::apply()
00061 {
00062   register unsigned int h = 0;
00063   register unsigned int w = 0;
00064 
00065   unsigned int width = src_roi[0]->width <= dst_roi->width ? src_roi[0]->width : dst_roi->width;
00066 
00067   // Here use array to avoid overhead of dynamic mem allocation.
00068   unsigned int top[width];
00069   unsigned int bottom[width];
00070   bool vflag[width];
00071 
00072   // y-plane
00073   register unsigned char *yp   = src[0] + (src_roi[0]->start.y * src_roi[0]->line_step) + (src_roi[0]->start.x * src_roi[0]->pixel_step);
00074   // u-plane
00075   register unsigned char *up   = YUV422_PLANAR_U_PLANE(src[0], src_roi[0]->image_width, src_roi[0]->image_height)
00076                                    + ((src_roi[0]->start.y * src_roi[0]->line_step) / 2 + (src_roi[0]->start.x * src_roi[0]->pixel_step) / 2) ;
00077   // v-plane
00078   register unsigned char *vp   = YUV422_PLANAR_V_PLANE(src[0], src_roi[0]->image_width, src_roi[0]->image_height)
00079                                    + ((src_roi[0]->start.y * src_roi[0]->line_step) / 2 + (src_roi[0]->start.x * src_roi[0]->pixel_step) / 2);
00080 
00081   // destination y-plane
00082   register unsigned char *dyp  = dst + (dst_roi->start.y * dst_roi->line_step) + (dst_roi->start.x * dst_roi->pixel_step);
00083 
00084   // line starts
00085   unsigned char *lyp  = yp;   // y-plane
00086   unsigned char *lup  = up;   // u-plane
00087   unsigned char *lvp  = vp;   // v-plane
00088   unsigned char *ldyp = dyp;  // destination y-plane
00089 
00090   // left and right boundary of the current line
00091   unsigned int left;
00092   unsigned int right;
00093   bool flag;
00094 
00095   // Confidence threshold for a line as "what" inside.
00096   const unsigned int    MIN_INTERIA     = 9;
00097   unsigned int          num_what;
00098 
00099   // Remember the widest orange line,
00100   // and if the following lines shrink dramatically,
00101   // we stop searching. This help eliminate reflextion.
00102   const unsigned int    MAX_SHRINK      = 16;
00103   unsigned int          max_width       = 0;
00104   bool                  not_reflect     = true;
00105 
00106   memset(top, 0, width * sizeof(unsigned int));
00107   memset(bottom, 0, width * sizeof(unsigned int));
00108   memset(vflag, 0, width * sizeof(bool));
00109 
00110   for (h = 0; (h < src_roi[0]->height) && (h < dst_roi->height); ++h) {
00111     flag = false;
00112     left = right = 0;
00113     num_what = 0;
00114     for (w = 0; (w < src_roi[0]->width) && (w < dst_roi->width); ++w) {
00115       if ( (cm->determine(*yp++, *up, *vp) == what) ) {
00116         right = w;
00117         if (not_reflect) bottom[w] = h;
00118         flag = true;
00119         vflag[w] = true;
00120         ++num_what;
00121       } else {
00122         left = flag?left:w;
00123         if (!vflag[w]) top[w] = h;
00124       }
00125       if ( (cm->determine(*yp++, *up++, *vp++) == what) ) {
00126         right = ++w;
00127         if (not_reflect) bottom[w] = h;
00128         flag = true;
00129         vflag[w] = true;
00130         ++num_what;
00131       } else {
00132         ++w;
00133         left = flag?left:w;
00134         if (!vflag[w]) top[w] = h;
00135       }
00136     }
00137 
00138     // clear the dst buffer for this line
00139     memset(ldyp, 0, dst_roi->width);
00140 
00141     if (num_what * MIN_INTERIA > right - left)
00142     {
00143       if (right - left > max_width)
00144         max_width = right - left;
00145       if (not_reflect)
00146       {
00147         if (right - left < max_width / MAX_SHRINK)
00148         {
00149           // cout << "In line:" << h << " \tleft = " << left
00150           //      << " \tright = " << right << " \tmax_width = "
00151           //      << max_width << endl;
00152           not_reflect = false; // the reflection begins from here
00153         }
00154 
00155         // set the left- and right-most pixel to white
00156         // but if the pixel is at the boundary, we ignore it
00157         // in order to eliminate a straight line at the border.
00158         if (left != 0 && left < dst_roi->width-1)
00159         {
00160           ldyp[left] = 255;
00161           // ldyp[left+1] = 255;
00162         }
00163         if (right != 0 && right < dst_roi->width-1)
00164         {
00165           ldyp[right] = 255;
00166           // ldyp[right-1] = 255;
00167         }
00168       }
00169     }
00170 
00171     lyp  += src_roi[0]->line_step;
00172     lup  += src_roi[0]->line_step / 2;
00173     lvp  += src_roi[0]->line_step / 2;
00174     ldyp += dst_roi->line_step;
00175     yp    = lyp;
00176     up    = lup;
00177     vp    = lvp;
00178     dyp   = ldyp;
00179   }
00180   for (w = 0; w < dst_roi->width; w++)
00181   {
00182     if (top[w] != 0 && top[w] != dst_roi->height - 1)
00183         *(dst + ((dst_roi->start.y + top[w]) * dst_roi->line_step)
00184               + ((dst_roi->start.x + w) * dst_roi->pixel_step)) = 255;
00185     if (bottom[w] != 0 && bottom[w] != dst_roi->height - 1)
00186         *(dst + ((dst_roi->start.y + bottom[w]) * dst_roi->line_step)
00187               + ((dst_roi->start.x + w) * dst_roi->pixel_step)) = 255;
00188   }
00189 }
00190 
00191 } // end namespace firevision

Generated on Tue Feb 22 13:32:15 2011 for Fawkes API by  doxygen 1.4.7