Fawkes API
Fawkes Development Version
|
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