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 #include <fvutils/color/yuv.h>
27 
28 #include <cstddef>
29 #include <cstring>
30 
31 namespace firevision {
32 
33 /** @class FilterHVSearch <fvfilters/hv_search.h>
34  * Horizontal/vertical search filter.
35  * This filter works similar to the horizontal search filter, but additionally
36  * it search for color changes in vertical direction.
37  * @author Yuxiao Hu
38  * @author Tim Niemueller
39  */
40 
41 /** Constructor.
42  * @param cm color model to use to determine the color change
43  * @param what what to look for, this color is considered as foreground,
44  * all other colors are background.
45  */
46 FilterHVSearch::FilterHVSearch(ColorModel *cm, color_t what) : Filter("FilterHVSearch")
47 {
48  this->cm = cm;
49  this->what = what;
50 }
51 
52 void
54 {
55  unsigned int h = 0;
56  unsigned int w = 0;
57 
58  unsigned int width = src_roi[0]->width <= dst_roi->width ? src_roi[0]->width : dst_roi->width;
59 
60  // Here use array to avoid overhead of dynamic mem allocation.
61  unsigned int top[width];
62  unsigned int bottom[width];
63  bool vflag[width];
64 
65  // y-plane
66  unsigned char *yp = src[0] + (src_roi[0]->start.y * src_roi[0]->line_step)
67  + (src_roi[0]->start.x * src_roi[0]->pixel_step);
68  // u-plane
69  unsigned char *up =
70  YUV422_PLANAR_U_PLANE(src[0], src_roi[0]->image_width, src_roi[0]->image_height)
71  + ((src_roi[0]->start.y * src_roi[0]->line_step) / 2
72  + (src_roi[0]->start.x * src_roi[0]->pixel_step) / 2);
73  // v-plane
74  unsigned char *vp =
75  YUV422_PLANAR_V_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
77  + (src_roi[0]->start.x * src_roi[0]->pixel_step) / 2);
78 
79  // destination y-plane
80  unsigned char *dyp =
82 
83  // line starts
84  unsigned char *lyp = yp; // y-plane
85  unsigned char *lup = up; // u-plane
86  unsigned char *lvp = vp; // v-plane
87  unsigned char *ldyp = dyp; // destination y-plane
88 
89  // left and right boundary of the current line
90  unsigned int left;
91  unsigned int right;
92  bool flag;
93 
94  // Confidence threshold for a line as "what" inside.
95  const unsigned int MIN_INTERIA = 9;
96  unsigned int num_what;
97 
98  // Remember the widest orange line,
99  // and if the following lines shrink dramatically,
100  // we stop searching. This help eliminate reflextion.
101  const unsigned int MAX_SHRINK = 16;
102  unsigned int max_width = 0;
103  bool not_reflect = true;
104 
105  memset(top, 0, width * sizeof(unsigned int));
106  memset(bottom, 0, width * sizeof(unsigned int));
107  memset(vflag, 0, width * sizeof(bool));
108 
109  for (h = 0; (h < src_roi[0]->height) && (h < dst_roi->height); ++h) {
110  flag = false;
111  left = right = 0;
112  num_what = 0;
113  for (w = 0; (w < src_roi[0]->width) && (w < dst_roi->width); ++w) {
114  if ((cm->determine(*yp++, *up, *vp) == what)) {
115  right = w;
116  if (not_reflect)
117  bottom[w] = h;
118  flag = true;
119  vflag[w] = true;
120  ++num_what;
121  } else {
122  left = flag ? left : w;
123  if (!vflag[w])
124  top[w] = h;
125  }
126  if ((cm->determine(*yp++, *up++, *vp++) == what)) {
127  right = ++w;
128  if (not_reflect)
129  bottom[w] = h;
130  flag = true;
131  vflag[w] = true;
132  ++num_what;
133  } else {
134  ++w;
135  left = flag ? left : w;
136  if (!vflag[w])
137  top[w] = h;
138  }
139  }
140 
141  // clear the dst buffer for this line
142  memset(ldyp, 0, dst_roi->width);
143 
144  if (num_what * MIN_INTERIA > right - left) {
145  if (right - left > max_width)
146  max_width = right - left;
147  if (not_reflect) {
148  if (right - left < max_width / MAX_SHRINK) {
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  ldyp[left] = 255;
160  // ldyp[left+1] = 255;
161  }
162  if (right != 0 && right < dst_roi->width - 1) {
163  ldyp[right] = 255;
164  // ldyp[right-1] = 255;
165  }
166  }
167  }
168 
169  lyp += src_roi[0]->line_step;
170  lup += src_roi[0]->line_step / 2;
171  lvp += src_roi[0]->line_step / 2;
172  ldyp += dst_roi->line_step;
173  yp = lyp;
174  up = lup;
175  vp = lvp;
176  dyp = ldyp;
177  }
178  for (w = 0; w < dst_roi->width; w++) {
179  if (top[w] != 0 && top[w] != dst_roi->height - 1)
180  *(dst + ((dst_roi->start.y + top[w]) * dst_roi->line_step)
181  + ((dst_roi->start.x + w) * dst_roi->pixel_step)) = 255;
182  if (bottom[w] != 0 && bottom[w] != dst_roi->height - 1)
183  *(dst + ((dst_roi->start.y + bottom[w]) * dst_roi->line_step)
184  + ((dst_roi->start.x + w) * dst_roi->pixel_step)) = 255;
185  }
186 }
187 
188 } // end namespace firevision
Color model interface.
Definition: colormodel.h:32
virtual color_t determine(unsigned int y, unsigned int u, unsigned int v) const =0
Determine classification of YUV pixel.
virtual void apply()
Apply the filter.
Definition: hv_search.cpp:53
FilterHVSearch(ColorModel *cm, color_t what)
Constructor.
Definition: hv_search.cpp:46
Filter interface.
Definition: filter.h:33
ROI ** src_roi
Source ROIs, dynamically allocated by Filter ctor.
Definition: filter.h:66
unsigned char ** src
Source buffers, dynamically allocated by Filter ctor.
Definition: filter.h:61
unsigned char * dst
Destination buffer.
Definition: filter.h:63
ROI * dst_roi
Destination ROI.
Definition: filter.h:68
unsigned int height
ROI height.
Definition: roi.h:119
fawkes::upoint_t start
ROI start.
Definition: roi.h:115
unsigned int line_step
line step
Definition: roi.h:125
unsigned int width
ROI width.
Definition: roi.h:117
unsigned int pixel_step
pixel step
Definition: roi.h:127
unsigned int x
x coordinate
Definition: types.h:36
unsigned int y
y coordinate
Definition: types.h:37