edge.h
説明を見る。
1 //
2 // Copyright (c) 2003-2011, MIST Project, Nagoya University
3 // All rights reserved.
4 //
5 // Redistribution and use in source and binary forms, with or without modification,
6 // are permitted provided that the following conditions are met:
7 //
8 // 1. Redistributions of source code must retain the above copyright notice,
9 // this list of conditions and the following disclaimer.
10 //
11 // 2. Redistributions in binary form must reproduce the above copyright notice,
12 // this list of conditions and the following disclaimer in the documentation
13 // and/or other materials provided with the distribution.
14 //
15 // 3. Neither the name of the Nagoya University nor the names of its contributors
16 // may be used to endorse or promote products derived from this software
17 // without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
20 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21 // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
22 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25 // IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
26 // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 //
28 
33 
34 #ifndef __INCLUDE_MIST_EDGE__
35 #define __INCLUDE_MIST_EDGE__
36 
37 
38 #ifndef __INCLUDE_MIST_H__
39 #include "../mist.h"
40 #endif
41 
42 #ifndef __INCLUDE_MIST_VECTOR__
43 #include "../vector.h"
44 #endif
45 
46 #ifndef __INCLUDE_MIST_LIMITS__
47 #include "../limits.h"
48 #endif
49 
50 #ifndef __INCLUDE_MIST_VECTOR__
51 #include "../vector.h"
52 #endif
53 
54 #ifndef __INCLUDE_CONVERTER__
55 #include "../converter.h"
56 #endif
57 
58 #ifndef __INCLUDE_MIST_THREAD__
59 #include "../thread.h"
60 #endif
61 
62 #ifndef __INCLUDE_FILTER_LINEAR_FILTER_H__
63 #include "linear.h"
64 #endif
65 
66 #include <vector>
67 #include <cmath>
68 
69 
70 // mist名前空間の始まり
72 
73 
74 
82 
83 
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 )
103 {
104  typedef typename array2< T1, Allocator1 >::size_type size_type;
105  typedef typename array2< T1, Allocator1 >::difference_type difference_type;
106  if( in.empty( ) )
107  {
108  return( false );
109  }
110 
111  // 値が入れ替わっている場合への対処
112  if( lower > upper )
113  {
114  double ttt = lower;
115  lower = upper;
116  upper = ttt;
117  }
118 
119  typedef array2< double > image_type;
120  typedef array2< unsigned char > mask_type;
121 
122  image_type tmp, k1( 3, 3 ), k2( 3, 3 ), gx, gy;
123 
124  convert( in, tmp );
125 
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;
129 
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;
133 
134  linear_filter( tmp, gx, k1, thread_num );
135  linear_filter( tmp, gy, k2, thread_num );
136 
137  if( useL2gradient )
138  {
139 #ifdef _OPENMP
140  #pragma omp parallel for
141 #endif
142  for( int i = 0 ; i < static_cast< int >( tmp.size( ) ) ; i++ )
143  {
144  tmp[ i ] = std::sqrt( gx[ i ] * gx[ i ] + gy[ i ] * gy[ i ] );
145  }
146  }
147  else
148  {
149 #ifdef _OPENMP
150  #pragma omp parallel for
151 #endif
152  for( int i = 0 ; i < static_cast< int >( tmp.size( ) ) ; i++ )
153  {
154  tmp[ i ] = std::abs( gx[ i ] ) + std::abs( gy[ i ] );
155  }
156  }
157 
158  mask_type mask( in.width( ), in.height( ) );
159 
160 #ifdef _OPENMP
161  #pragma omp parallel for schedule( guided )
162 #endif
163  for( int j = 1 ; j < static_cast< int >( tmp.height( ) - 1 ) ; j++ )
164  {
165  for( size_type i = 1 ; i < tmp.width( ) - 1 ; i++ )
166  {
167  double dx = gx( i, j );
168  double dy = gy( i, j );
169  double sign = dx * dy < 0 ? -1 : +1;
170 
171  dx = std::abs( dx );
172  dy = std::abs( dy );
173 
174  double val = tmp( i, j );
175 
176  if( val > lower )
177  {
178  // dy / dx < tan( 22.5 / 180.0 / 3.1415926535897932384626433832795 )
179  if( dy < dx * 0.4142135623730950488016887242097 )
180  {
181  // 0度
182  if( val > tmp( i - 1, j ) && val >= tmp( i + 1, j ) )
183  {
184  if( val > upper )
185  {
186  mask( i, j ) = 2;
187  }
188  else
189  {
190  mask( i, j ) = 1;
191  }
192  }
193  }
194  // dy / dx < tan( ( 22.5 + 45.0 ) / 180.0 / 3.1415926535897932384626433832795 )
195  else if( dy > dx * 2.4142135623730950488016887242097 )
196  {
197  // 90度
198  if( val > tmp( i, j - 1 ) && val >= tmp( i, j + 1 ) )
199  {
200  if( val > upper )
201  {
202  mask( i, j ) = 2;
203  }
204  else
205  {
206  mask( i, j ) = 1;
207  }
208  }
209  }
210  else
211  {
212  if( sign < 0 )
213  {
214  // 45度
215  if( val > tmp( i - 1, j + 1 ) && val > tmp( i + 1, j - 1 ) )
216  {
217  if( val > upper )
218  {
219  mask( i, j ) = 2;
220  }
221  else
222  {
223  mask( i, j ) = 1;
224  }
225  }
226  }
227  else
228  {
229  // 135度
230  if( val > tmp( i - 1, j - 1 ) && val > tmp( i + 1, j + 1 ) )
231  {
232  if( val > upper )
233  {
234  mask( i, j ) = 2;
235  }
236  else
237  {
238  mask( i, j ) = 1;
239  }
240  }
241  }
242  }
243  }
244  }
245  }
246 
247  typedef vector2< size_type > vector_type;
248  typedef std::list< vector_type > point_list_type;
249  point_list_type point_list;
250 
251  for( size_type j = 1 ; j < tmp.height( ) - 1 ; j++ )
252  {
253  for( size_type i = 1 ; i < tmp.width( ) - 1 ; i++ )
254  {
255  if( mask( i, j ) == 1 )
256  {
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 )
260  {
261  mask( i, j ) = 2;
262  point_list.push_back( vector_type( i, j ) );
263  }
264  }
265  }
266  }
267 
268  while( !point_list.empty( ) )
269  {
270  vector_type v = point_list.front( );
271  point_list.pop_front( );
272  size_type i = v.x;
273  size_type j = v.y;
274 
275  if( mask( i - 1, j - 1 ) == 1 )
276  {
277  mask( i - 1, j - 1 ) = 2;
278  point_list.push_back( vector_type( i - 1, j - 1 ) );
279  }
280  if( mask( i, j - 1 ) == 1 )
281  {
282  mask( i, j - 1 ) = 2;
283  point_list.push_back( vector_type( i, j - 1 ) );
284  }
285  if( mask( i + 1, j - 1 ) == 1 )
286  {
287  mask( i + 1, j - 1 ) = 2;
288  point_list.push_back( vector_type( i + 1, j - 1 ) );
289  }
290  if( mask( i - 1, j ) == 1 )
291  {
292  mask( i - 1, j ) = 2;
293  point_list.push_back( vector_type( i - 1, j ) );
294  }
295  if( mask( i + 1, j ) == 1 )
296  {
297  mask( i + 1, j ) = 2;
298  point_list.push_back( vector_type( i + 1, j ) );
299  }
300  if( mask( i - 1, j + 1 ) == 1 )
301  {
302  mask( i - 1, j + 1 ) = 2;
303  point_list.push_back( vector_type( i - 1, j + 1 ) );
304  }
305  if( mask( i, j + 1 ) == 1 )
306  {
307  mask( i, j + 1 ) = 2;
308  point_list.push_back( vector_type( i, j + 1 ) );
309  }
310  if( mask( i + 1, j + 1 ) == 1 )
311  {
312  mask( i + 1, j + 1 ) = 2;
313  point_list.push_back( vector_type( i + 1, j + 1 ) );
314  }
315  }
316 
317  out.resize( in.width( ), in.height( ) );
318  out.reso( in.reso1( ), in.reso2( ) );
319 
320 #ifdef _OPENMP
321  #pragma omp parallel for
322 #endif
323  for( int i = 0 ; i < static_cast< int >( out.size( ) ) ; i++ )
324  {
325  out[ i ] = mask[ i ] == 2 ? fgval : bgval;
326  }
327 
328  return( true );
329 }
330 
331 
332 
334 // エッジ検出フィルタグループの終わり
335 
336 
337 // mist名前空間の終わり
338 _MIST_END
339 
340 
341 #endif // __INCLUDE_MIST_EDGE__
342 

Generated on Wed Nov 12 2014 19:44:14 for MIST by doxygen 1.8.1.2