Fawkes API  Fawkes Development Version
ht_lines.cpp
1 
2 /***************************************************************************
3  * ht_lines.cpp - Implementation of a lines shape finder
4  * with Randomized Hough Transform
5  *
6  * Created: Fri Jan 13 12:42:53 2006
7  * Copyright 2005-2006 Tim Niemueller [www.niemueller.de]
8  * Hu Yuxiao <Yuxiao.Hu@rwth-aachen.de>
9  *
10  ****************************************************************************/
11 
12 /* This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version. A runtime exception applies to
16  * this software (see LICENSE.GPL_WRE file mentioned below for details).
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU Library General Public License for more details.
22  *
23  * Read the full text in the LICENSE.GPL_WRE file in the doc directory.
24  */
25 
26 #include <cmath>
27 #include <sys/time.h>
28 #include <fvmodels/shape/ht_lines.h>
29 #include <utils/math/angle.h>
30 
31 using namespace std;
32 using namespace fawkes;
33 
34 namespace firevision {
35 #if 0 /* just to make Emacs auto-indent happy */
36 }
37 #endif
38 
39 #define TEST_IF_IS_A_PIXEL(x) ((x)>230)
40 
41 /** @class HtLinesModel <fvmodels/shape/ht_lines.h>
42  * Hough-Transform line matcher.
43  */
44 
45 /** Constructor.
46  * @param nr_candidates number of candidates
47  * @param angle_from slope of lines from
48  * @param angle_range angle range
49  * @param r_scale r scale
50  * @param min_votes_ratio min votes ratio
51  * @param min_votes minimum number of votes for a candidate to consider
52  */
53 HtLinesModel::HtLinesModel(unsigned int nr_candidates, float angle_from, float angle_range, int r_scale, float min_votes_ratio, int min_votes)
54 {
55  RHT_NR_CANDIDATES = nr_candidates;
56 
57  RHT_R_SCALE = r_scale;
58 
59  RHT_MIN_VOTES = min_votes;
60  RHT_MIN_VOTES_RATIO = min_votes_ratio;
61 
62  RHT_ANGLE_FROM = angle_from - (floor(angle_from / (2 * M_PI )) * (2 * M_PI));
63  RHT_ANGLE_RANGE = angle_range - (floor(angle_range / (2 * M_PI )) * (2 * M_PI));
64  RHT_ANGLE_INCREMENT = RHT_ANGLE_RANGE / RHT_NR_CANDIDATES;
65 }
66 
67 
68 /** Destructor. */
69 HtLinesModel::~HtLinesModel(void)
70 {
71  m_Lines.clear();
72 }
73 
74 int
75 HtLinesModel::parseImage( unsigned char *buf,
76  ROI *roi )
77 {
78  unsigned char *buffer = roi->get_roi_buffer_start(buf);
79 
80  // clear the accumulator
81  accumulator.reset();
82 
83  // clear all the remembered lines
84  m_Lines.clear();
85 
86  // First, find all the edge pixels,
87  // and store them in the 'pixels' vector.
88  unsigned char *line_start = buffer;
89  unsigned int x, y;
90  vector<upoint_t> pixels;
91 
92  for (y = 0; y < roi->height; ++y) {
93  for (x = 0; x < roi->width; ++x) {
94  if (TEST_IF_IS_A_PIXEL(*buffer)) {
95  upoint_t pt={x, y};
96  pixels.push_back(pt);
97  }
98  // NOTE: this assumes roi->pixel_step == 1
99  ++buffer;
100  }
101  line_start += roi->line_step;
102  buffer = line_start;
103  }
104 
105  // Then perform the RHT algorithm
106  upoint_t p;
107  float r, phi; // used for line representation
108  vector< upoint_t >::iterator pos;
109  if (pixels.size() == 0) {
110  // No edge pixels found => no lines
111  return 0;
112  }
113 
114 
115  while (pixels.size() > 0) {
116  p = pixels.back();
117  pixels.pop_back();
118 
119  for (unsigned int i = 0; i < RHT_NR_CANDIDATES; ++i) {
120  phi = RHT_ANGLE_FROM + i * RHT_ANGLE_INCREMENT;
121  r = p.x * cos( phi ) + p.y * sin( phi );
122 
123  int angle = (int)round(fawkes::rad2deg( phi ));
124 
125  accumulator.accumulate( (int)round(r / RHT_R_SCALE),
126  angle,
127  0 );
128  }
129  }
130 
131 
132  // Find the most dense region, and decide on the lines
133  int max, r_max, phi_max, any_max;
134  max = accumulator.getMax(r_max, phi_max, any_max);
135 
136  roi_width = roi->width;
137  roi_height = roi->height;
138 
139  LineShape l(roi->width, roi->height);
140  l.r = r_max * RHT_R_SCALE;
141  l.phi = phi_max;
142  l.count = max;
143  m_Lines.push_back( l );
144 
145  return 1;
146 }
147 
148 
149 int
150 HtLinesModel::getShapeCount(void) const
151 {
152  return m_Lines.size();
153 }
154 
155 LineShape *
156 HtLinesModel::getShape(int id) const
157 {
158  if (id < 0 || (unsigned int)id >= m_Lines.size()) {
159  return NULL;
160  } else {
161  return const_cast<LineShape*>(&m_Lines[id]); // or use const Shape* def?!...
162  }
163 }
164 
165 
166 LineShape *
167 HtLinesModel::getMostLikelyShape(void) const
168 {
169  if (m_Lines.size() == 0) {
170  return NULL;
171  } else if (m_Lines.size() == 1) {
172  return const_cast<LineShape*>(&m_Lines[0]); // or use const Shape* def?!...
173  } else {
174  int cur=0;
175  for (unsigned int i=1; i < m_Lines.size(); ++i) {
176  if (m_Lines[i].count > m_Lines[cur].count) {
177  cur = i;
178  }
179  }
180  return const_cast<LineShape*>(&m_Lines[cur]); // or use const Shape* definition?!...
181  }
182 }
183 
184 
185 /** Get all lines found.
186  * @return vector with all line shapes.
187  */
188 vector< LineShape > *
189 HtLinesModel::getShapes()
190 {
191  int votes = (int)(accumulator.getNumVotes() * (float)RHT_MIN_VOTES_RATIO);
192 
193  if ( RHT_MIN_VOTES > votes ) {
194  votes = RHT_MIN_VOTES;
195  }
196 
197  vector< LineShape > * rv = new vector< LineShape >();
198 
199  vector< vector< int > > *rht_nodes = accumulator.getNodes( votes );
200  vector< vector< int > >::iterator node_it;
201 
202  LineShape l(roi_width, roi_height);
203 
204  for (node_it = rht_nodes->begin(); node_it != rht_nodes->end(); ++node_it) {
205  l.r = node_it->at(0) * RHT_R_SCALE;
206  l.phi = node_it->at(1);
207  // we do not use val 2 here!
208  l.count = node_it->at(3);
209  l.calcPoints();
210  rv->push_back( l );
211  }
212 
213  return rv;
214 }
215 
216 } // end namespace firevision
Fawkes library namespace.
unsigned int y
y coordinate
Definition: types.h:36
STL namespace.
unsigned int x
x coordinate
Definition: types.h:35
unsigned int width
ROI width.
Definition: roi.h:121
Region of interest.
Definition: roi.h:58
void calcPoints()
Calc points for line.
Definition: line.cpp:104
unsigned char * get_roi_buffer_start(unsigned char *buffer) const
Get ROI buffer start.
Definition: roi.cpp:556
Line shape.
Definition: line.h:40
Point with cartesian coordinates as unsigned integers.
Definition: types.h:34
float rad2deg(float rad)
Convert an angle given in radians to degrees.
Definition: angle.h:48
unsigned int height
ROI height.
Definition: roi.h:123
unsigned int line_step
line step
Definition: roi.h:129