34 #ifndef __INCLUDE_MIST_EDGE__
35 #define __INCLUDE_MIST_EDGE__
38 #ifndef __INCLUDE_MIST_H__
42 #ifndef __INCLUDE_MIST_VECTOR__
43 #include "../vector.h"
46 #ifndef __INCLUDE_MIST_LIMITS__
47 #include "../limits.h"
50 #ifndef __INCLUDE_MIST_VECTOR__
51 #include "../vector.h"
54 #ifndef __INCLUDE_CONVERTER__
55 #include "../converter.h"
58 #ifndef __INCLUDE_MIST_THREAD__
59 #include "../thread.h"
62 #ifndef __INCLUDE_FILTER_LINEAR_FILTER_H__
101 template <
class T1,
class T2,
class Allocator1,
class Allocator2 >
102 inline bool canny(
const array2< T1, Allocator1 > &in,
array2< T2, Allocator2 > &out,
double lower,
double upper,
bool useL2gradient =
false,
const typename array2< T2, Allocator2 >::value_type &fgval =
typename array2< T2, Allocator2 >::value_type( 255 ),
const typename array2< T2, Allocator2 >::value_type &bgval =
typename array2< T2, Allocator2 >::value_type( 0 ),
typename array2< T2, Allocator2 >::size_type thread_num = 0 )
122 image_type tmp, k1( 3, 3 ), k2( 3, 3 ), gx, gy;
126 k1( 0, 0 ) = -1; k1( 1, 0 ) = 0; k1( 2, 0 ) = 1;
127 k1( 0, 1 ) = -2; k1( 1, 1 ) = 0; k1( 2, 1 ) = 2;
128 k1( 0, 2 ) = -1; k1( 1, 2 ) = 0; k1( 2, 2 ) = 1;
130 k2( 0, 0 ) = -1; k2( 1, 0 ) = -2; k2( 2, 0 ) = -1;
131 k2( 0, 1 ) = 0; k2( 1, 1 ) = 0; k2( 2, 1 ) = 0;
132 k2( 0, 2 ) = +1; k2( 1, 2 ) = +2; k2( 2, 2 ) = +1;
134 linear_filter( tmp, gx, k1, thread_num );
135 linear_filter( tmp, gy, k2, thread_num );
140 #pragma omp parallel for
142 for(
int i = 0 ; i < static_cast< int >( tmp.size( ) ) ; i++ )
144 tmp[ i ] = std::sqrt( gx[ i ] * gx[ i ] + gy[ i ] * gy[ i ] );
150 #pragma omp parallel for
152 for(
int i = 0 ; i < static_cast< int >( tmp.size( ) ) ; i++ )
154 tmp[ i ] = std::abs( gx[ i ] ) + std::abs( gy[ i ] );
161 #pragma omp parallel for schedule( guided )
163 for(
int j = 1 ; j < static_cast< int >( tmp.height( ) - 1 ) ; j++ )
165 for( size_type i = 1 ; i < tmp.width( ) - 1 ; i++ )
167 double dx = gx( i, j );
168 double dy = gy( i, j );
169 double sign = dx * dy < 0 ? -1 : +1;
174 double val = tmp( i, j );
179 if( dy < dx * 0.4142135623730950488016887242097 )
182 if( val > tmp( i - 1, j ) && val >= tmp( i + 1, j ) )
195 else if( dy > dx * 2.4142135623730950488016887242097 )
198 if( val > tmp( i, j - 1 ) && val >= tmp( i, j + 1 ) )
215 if( val > tmp( i - 1, j + 1 ) && val > tmp( i + 1, j - 1 ) )
230 if( val > tmp( i - 1, j - 1 ) && val > tmp( i + 1, j + 1 ) )
248 typedef std::list< vector_type > point_list_type;
249 point_list_type point_list;
251 for( size_type j = 1 ; j < tmp.height( ) - 1 ; j++ )
253 for( size_type i = 1 ; i < tmp.width( ) - 1 ; i++ )
255 if( mask( i, j ) == 1 )
257 if( mask( i - 1, j - 1 ) == 2 || mask( i, j - 1 ) == 2 || mask( i + 1, j - 1 ) == 2 ||
258 mask( i - 1, j ) == 2 || mask( i + 1, j ) == 2 ||
259 mask( i - 1, j + 1 ) == 2 || mask( i, j + 1 ) == 2 || mask( i + 1, j + 1 ) == 2 )
262 point_list.push_back( vector_type( i, j ) );
268 while( !point_list.empty( ) )
270 vector_type v = point_list.front( );
271 point_list.pop_front( );
275 if( mask( i - 1, j - 1 ) == 1 )
277 mask( i - 1, j - 1 ) = 2;
278 point_list.push_back( vector_type( i - 1, j - 1 ) );
280 if( mask( i, j - 1 ) == 1 )
282 mask( i, j - 1 ) = 2;
283 point_list.push_back( vector_type( i, j - 1 ) );
285 if( mask( i + 1, j - 1 ) == 1 )
287 mask( i + 1, j - 1 ) = 2;
288 point_list.push_back( vector_type( i + 1, j - 1 ) );
290 if( mask( i - 1, j ) == 1 )
292 mask( i - 1, j ) = 2;
293 point_list.push_back( vector_type( i - 1, j ) );
295 if( mask( i + 1, j ) == 1 )
297 mask( i + 1, j ) = 2;
298 point_list.push_back( vector_type( i + 1, j ) );
300 if( mask( i - 1, j + 1 ) == 1 )
302 mask( i - 1, j + 1 ) = 2;
303 point_list.push_back( vector_type( i - 1, j + 1 ) );
305 if( mask( i, j + 1 ) == 1 )
307 mask( i, j + 1 ) = 2;
308 point_list.push_back( vector_type( i, j + 1 ) );
310 if( mask( i + 1, j + 1 ) == 1 )
312 mask( i + 1, j + 1 ) = 2;
313 point_list.push_back( vector_type( i + 1, j + 1 ) );
321 #pragma omp parallel for
323 for(
int i = 0 ; i < static_cast< int >( out.
size( ) ) ; i++ )
325 out[ i ] = mask[ i ] == 2 ? fgval : bgval;
341 #endif // __INCLUDE_MIST_EDGE__