- メインページ
- モジュール
- ネームスペース
- データ構造
- ファイル

- ファイル一覧
- グローバル

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名前空間の始まり
71 _MIST_BEGIN
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