Fawkes API  Fawkes Development Version
hv_search.cpp
1 
2 /***************************************************************************
3  * hv_search.cpp - Implementation of horizontal- and vertical-search filter
4  *
5  * Created: Tue Jul 12 14:40:40 2005
6  * Copyright 2005-2007 Tim Niemueller [www.niemueller.de]
7  * 2005 Yuxiao Hu (Yuxiao.Hu@rwth-aachen.de)
8  *
9  ****************************************************************************/
10 
11 /* This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version. A runtime exception applies to
15  * this software (see LICENSE.GPL_WRE file mentioned below for details).
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  * GNU Library General Public License for more details.
21  *
22  * Read the full text in the LICENSE.GPL_WRE file in the doc directory.
23  */
24 
25 #include <fvfilters/hv_search.h>
26 
27 #include <fvutils/color/yuv.h>
28 
29 #include <cstddef>
30 #include <cstring>
31 
32 namespace firevision {
33 #if 0 /* just to make Emacs auto-indent happy */
34 }
35 #endif
36 
37 /** @class FilterHVSearch <fvfilters/hv_search.h>
38  * Horizontal/vertical search filter.
39  * This filter works similar to the horizontal search filter, but additionally
40  * it search for color changes in vertical direction.
41  * @author Yuxiao Hu
42  * @author Tim Niemueller
43  */
44 
45 
46 /** Constructor.
47  * @param cm color model to use to determine the color change
48  * @param what what to look for, this color is considered as foreground,
49  * all other colors are background.
50  */
52  : Filter("FilterHVSearch")
53 {
54  this->cm = cm;
55  this->what = what;
56 }
57 
58 
59 void
61 {
62  register unsigned int h = 0;
63  register unsigned int w = 0;
64 
65  unsigned int width = src_roi[0]->width <= dst_roi->width ? src_roi[0]->width : dst_roi->width;
66 
67  // Here use array to avoid overhead of dynamic mem allocation.
68  unsigned int top[width];
69  unsigned int bottom[width];
70  bool vflag[width];
71 
72  // y-plane
73  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);
74  // u-plane
75  register unsigned char *up = YUV422_PLANAR_U_PLANE(src[0], src_roi[0]->image_width, src_roi[0]->image_height)
76  + ((src_roi[0]->start.y * src_roi[0]->line_step) / 2 + (src_roi[0]->start.x * src_roi[0]->pixel_step) / 2) ;
77  // v-plane
78  register unsigned char *vp = YUV422_PLANAR_V_PLANE(src[0], src_roi[0]->image_width, src_roi[0]->image_height)
79  + ((src_roi[0]->start.y * src_roi[0]->line_step) / 2 + (src_roi[0]->start.x * src_roi[0]->pixel_step) / 2);
80 
81  // destination y-plane
82  register unsigned char *dyp = dst + (dst_roi->start.y * dst_roi->line_step) + (dst_roi->start.x * dst_roi->pixel_step);
83 
84  // line starts
85  unsigned char *lyp = yp; // y-plane
86  unsigned char *lup = up; // u-plane
87  unsigned char *lvp = vp; // v-plane
88  unsigned char *ldyp = dyp; // destination y-plane
89 
90  // left and right boundary of the current line
91  unsigned int left;
92  unsigned int right;
93  bool flag;
94 
95  // Confidence threshold for a line as "what" inside.
96  const unsigned int MIN_INTERIA = 9;
97  unsigned int num_what;
98 
99  // Remember the widest orange line,
100  // and if the following lines shrink dramatically,
101  // we stop searching. This help eliminate reflextion.
102  const unsigned int MAX_SHRINK = 16;
103  unsigned int max_width = 0;
104  bool not_reflect = true;
105 
106  memset(top, 0, width * sizeof(unsigned int));
107  memset(bottom, 0, width * sizeof(unsigned int));
108  memset(vflag, 0, width * sizeof(bool));
109 
110  for (h = 0; (h < src_roi[0]->height) && (h < dst_roi->height); ++h) {
111  flag = false;
112  left = right = 0;
113  num_what = 0;
114  for (w = 0; (w < src_roi[0]->width) && (w < dst_roi->width); ++w) {
115  if ( (cm->determine(*yp++, *up, *vp) == what) ) {
116  right = w;
117  if (not_reflect) bottom[w] = h;
118  flag = true;
119  vflag[w] = true;
120  ++num_what;
121  } else {
122  left = flag?left:w;
123  if (!vflag[w]) top[w] = h;
124  }
125  if ( (cm->determine(*yp++, *up++, *vp++) == what) ) {
126  right = ++w;
127  if (not_reflect) bottom[w] = h;
128  flag = true;
129  vflag[w] = true;
130  ++num_what;
131  } else {
132  ++w;
133  left = flag?left:w;
134  if (!vflag[w]) top[w] = h;
135  }
136  }
137 
138  // clear the dst buffer for this line
139  memset(ldyp, 0, dst_roi->width);
140 
141  if (num_what * MIN_INTERIA > right - left)
142  {
143  if (right - left > max_width)
144  max_width = right - left;
145  if (not_reflect)
146  {
147  if (right - left < max_width / MAX_SHRINK)
148  {
149  // cout << "In line:" << h << " \tleft = " << left
150  // << " \tright = " << right << " \tmax_width = "
151  // << max_width << endl;
152  not_reflect = false; // the reflection begins from here
153  }
154 
155  // set the left- and right-most pixel to white
156  // but if the pixel is at the boundary, we ignore it
157  // in order to eliminate a straight line at the border.
158  if (left != 0 && left < dst_roi->width-1)
159  {
160  ldyp[left] = 255;
161  // ldyp[left+1] = 255;
162  }
163  if (right != 0 && right < dst_roi->width-1)
164  {
165  ldyp[right] = 255;
166  // ldyp[right-1] = 255;
167  }
168  }
169  }
170 
171  lyp += src_roi[0]->line_step;
172  lup += src_roi[0]->line_step / 2;
173  lvp += src_roi[0]->line_step / 2;
174  ldyp += dst_roi->line_step;
175  yp = lyp;
176  up = lup;
177  vp = lvp;
178  dyp = ldyp;
179  }
180  for (w = 0; w < dst_roi->width; w++)
181  {
182  if (top[w] != 0 && top[w] != dst_roi->height - 1)
183  *(dst + ((dst_roi->start.y + top[w]) * dst_roi->line_step)
184  + ((dst_roi->start.x + w) * dst_roi->pixel_step)) = 255;
185  if (bottom[w] != 0 && bottom[w] != dst_roi->height - 1)
186  *(dst + ((dst_roi->start.y + bottom[w]) * dst_roi->line_step)
187  + ((dst_roi->start.x + w) * dst_roi->pixel_step)) = 255;
188  }
189 }
190 
191 } // end namespace firevision
Color model interface.
Definition: colormodel.h:34
FilterHVSearch(ColorModel *cm, color_t what)
Constructor.
Definition: hv_search.cpp:51
fawkes::upoint_t start
ROI start.
Definition: roi.h:119
unsigned int y
y coordinate
Definition: types.h:36
unsigned int x
x coordinate
Definition: types.h:35
unsigned int width
ROI width.
Definition: roi.h:121
unsigned char ** src
Source buffers, dynamically allocated by Filter ctor.
Definition: filter.h:65
Filter interface.
Definition: filter.h:35
ROI ** src_roi
Source ROIs, dynamically allocated by Filter ctor.
Definition: filter.h:70
unsigned int height
ROI height.
Definition: roi.h:123
virtual void apply()
Apply the filter.
Definition: hv_search.cpp:60
unsigned int line_step
line step
Definition: roi.h:129
unsigned char * dst
Destination buffer.
Definition: filter.h:67
unsigned int pixel_step
pixel step
Definition: roi.h:131
ROI * dst_roi
Destination ROI.
Definition: filter.h:72
virtual color_t determine(unsigned int y, unsigned int u, unsigned int v) const =0
Determine classification of YUV pixel.