34 #ifndef __INCLUDE_MIST_HOUGH__
35 #define __INCLUDE_MIST_HOUGH__
37 #ifndef __INCLUDE_MIST_H__
50 namespace __hough_detail__
52 typedef std::multimap< size_t, std::complex< int >, std::greater< size_t > > hough_counter;
55 class trigonometric_table
58 typedef size_t size_type;
62 array< double > cos_table_;
63 array< double > sin_table_;
66 double sin( size_type angle )
const {
return( sin_table_[ angle ] ); }
67 double cos( size_type angle )
const {
return( cos_table_[ angle ] ); }
68 size_type size( )
const {
return( size_ ); }
71 trigonometric_table(
double rho_resolution,
double theta_resolution )
72 : size_( static_cast< size_type >( std::fabs( 3.1415926535897932384626433832795 / theta_resolution ) + 0.5 ) ), cos_table_( size_ ), sin_table_( size_ )
74 const double rho_inverse = 1.0 / rho_resolution;
77 for( size_type i = 0 ; i < size_ ; angle += theta_resolution, i++ )
79 sin_table_[ i ] = std::sin( angle ) * rho_inverse;
80 cos_table_[ i ] = std::cos( angle ) * rho_inverse;
84 ~trigonometric_table( )
92 typedef array2< size_t > data_type;
93 typedef data_type::size_type size_type;
94 typedef data_type::difference_type difference_type;
100 accumulator( size_type rho_size, size_type angle_size ) : data_( angle_size + 2, rho_size + 2 )
108 void count_up( difference_type rho, size_type angle )
110 this->operator ()( static_cast< difference_type >( rho + ( get_rho_size( ) - 1 ) / 2 ), angle ) ++;
113 void convert_to_counter( hough_counter &c, size_type
threshold )
const
115 int rho_size =
static_cast< int >( get_rho_size( ) );
116 size_type angle_size = get_angle_size( );
119 #pragma omp parallel for schedule( guided )
121 for(
int rho = 0 ; rho < rho_size ; ++rho )
123 for( size_type angle = 0 ; angle < angle_size ; ++angle )
125 size_type count = at( rho, angle );
127 if( ( count > threshold ) && is_peak_cell( rho, angle ) )
133 c.insert( std::make_pair( count, std::complex< int >( rho - ( rho_size - 1 ) / 2, angle ) ) );
141 size_type & operator ()( size_type rho, size_type angle )
143 return( data_( angle + 1, rho + 1 ) );
146 size_type operator ()( size_type rho, size_type angle )
const
148 return( data_( angle + 1, rho + 1 ) );
151 size_type & at( size_type rho, size_type angle )
153 return( this->
operator ()( rho, angle ) );
156 size_type at( size_type rho, size_type angle )
const
158 return( this->
operator ()( rho, angle ) );
161 size_type get_rho_size( )
const
163 return( data_.size2( ) - 2 );
166 size_type get_angle_size( )
const
168 return( data_.size1( ) - 2 );
171 bool is_peak_cell( size_type rho, size_type angle )
const
173 size_type level = at( rho, angle );
175 return( level > at( rho - 1, angle ) &&
176 level >= at( rho + 1, angle ) &&
177 level > at( rho, angle - 1 ) &&
178 level >= at( rho, angle + 1 ) );
182 template <
class T,
class Allocator,
class FUNCTOR >
183 accumulator hough_transform(
const array2< T, Allocator >& input,
double rho_resolution,
const trigonometric_table & table, FUNCTOR f )
185 typedef typename array2< T, Allocator >::size_type size_type;
186 typedef typename array2< T, Allocator >::difference_type difference_type;
187 typedef typename array2< T, Allocator >::value_type value_type;
189 const size_type angle_size = table.size( );
190 const size_type rho_size =
static_cast< size_type
>( ( ( input.width( ) + input.height( ) ) * 2 + 1 ) / rho_resolution );
192 accumulator accumulator( rho_size, angle_size );
194 int height =
static_cast< int >( input.height( ) );
197 #pragma omp parallel for schedule( guided )
199 for(
int j = 0 ; j < height ; j++ )
201 for( size_type i = 0 ; i < input.width( ) ; i++ )
203 if( f( input( i, j ) ) )
208 for( size_type angle = 0 ; angle < angle_size ; ++angle )
210 difference_type rho =
static_cast< difference_type
>( i * table.cos( angle ) + j * table.sin( angle ) + 0.5 );
211 accumulator.count_up( rho, angle );
217 return( accumulator );
220 template <
template <
typename,
typename >
class LINES,
class TT,
class AAllocator >
221 void hough_inverse(
const hough_counter & counter, LINES< TT, AAllocator > &lines,
double rho_resolution,
double theta_resolution,
size_t max_lines )
223 typedef typename LINES< TT, AAllocator >::value_type value_type;
227 for( hough_counter::const_iterator ite = counter.begin( ) ; ite != counter.end( ) && lines.size( ) < max_lines ; ++ite )
229 double rho = ite->second.real( ) * rho_resolution;
230 double theta = ite->second.imag( ) * theta_resolution;
231 lines.push_back( value_type( rho, theta ) );
235 class foreground_evaluator
239 bool operator ()(
const T &val )
const
241 return( val != T( ) );
245 class background_evaluator
249 bool operator ()(
const T &val )
const
251 return( val == T( ) );
282 template <
class T,
class Allocator,
template <
typename,
typename >
class LINES,
class TT,
class AAllocator,
class FUNCTOR >
283 bool hough_transform(
const array2< T, Allocator >& input, LINES< TT, AAllocator > &lines, std::size_t max_lines,
double rho_resolution,
double theta_resolution,
size_t threshold, FUNCTOR value_functor )
286 __hough_detail__::trigonometric_table table = __hough_detail__::trigonometric_table( rho_resolution, theta_resolution );
292 __hough_detail__::hough_counter counter;
293 accumulator.convert_to_counter( counter, threshold );
296 __hough_detail__::hough_inverse( counter, lines, rho_resolution, theta_resolution, max_lines );
298 return( !lines.empty( ) );
313 template <
class T,
class Allocator,
template <
typename,
typename >
class LINES,
class TT,
class AAllocator >
314 bool hough_transform(
const array2< T, Allocator >& input, LINES< TT, AAllocator > &lines, std::size_t max_lines,
double rho_resolution = 1.0,
double theta_resolution = 3.1415926535897932384626433832795 / 360.0,
size_t threshold = 100 )
316 return(
hough_transform( input, lines, max_lines, rho_resolution, theta_resolution, threshold, __hough_detail__::foreground_evaluator( ) ) );
326 #endif // __INCLUDE_MIST_HOUGH__