Update the trunk to the OpenCV's CVS (2008-07-14)
[opencv] / samples / c / distrans.c
1 #ifdef _CH_
2 #pragma package <opencv>
3 #endif
4
5 #include "cv.h"
6 #include "highgui.h"
7 #include <stdio.h>
8
9 char wndname[] = "Distance transform";
10 char tbarname[] = "Threshold";
11 int mask_size = CV_DIST_MASK_5;
12 int build_voronoi = 0;
13 int edge_thresh = 100;
14 int dist_type = CV_DIST_L1;
15
16 // The output and temporary images
17 IplImage* dist = 0;
18 IplImage* dist8u1 = 0;
19 IplImage* dist8u2 = 0;
20 IplImage* dist8u = 0;
21 IplImage* dist32s = 0;
22
23 IplImage* gray = 0;
24 IplImage* edge = 0;
25 IplImage* labels = 0;
26
27 // threshold trackbar callback
28 void on_trackbar( int dummy )
29 {
30     static const uchar colors[][3] = 
31     {
32         {0,0,0},
33         {255,0,0},
34         {255,128,0},
35         {255,255,0},
36         {0,255,0},
37         {0,128,255},
38         {0,255,255},
39         {0,0,255},
40         {255,0,255}
41     };
42     
43     int msize = mask_size;
44     int _dist_type = build_voronoi ? CV_DIST_L2 : dist_type;
45
46     cvThreshold( gray, edge, (float)edge_thresh, (float)edge_thresh, CV_THRESH_BINARY );
47
48     if( build_voronoi )
49         msize = CV_DIST_MASK_5;
50
51     if( _dist_type == CV_DIST_L1 )
52     {
53         cvDistTransform( edge, edge, _dist_type, msize, NULL, NULL );
54         cvConvert( edge, dist );
55     }
56     else
57         cvDistTransform( edge, dist, _dist_type, msize, NULL, build_voronoi ? labels : NULL );
58
59     if( !build_voronoi )
60     {
61         // begin "painting" the distance transform result
62         cvConvertScale( dist, dist, 5000.0, 0 );
63         cvPow( dist, dist, 0.5 );
64     
65         cvConvertScale( dist, dist32s, 1.0, 0.5 );
66         cvAndS( dist32s, cvScalarAll(255), dist32s, 0 );
67         cvConvertScale( dist32s, dist8u1, 1, 0 );
68         cvConvertScale( dist32s, dist32s, -1, 0 );
69         cvAddS( dist32s, cvScalarAll(255), dist32s, 0 );
70         cvConvertScale( dist32s, dist8u2, 1, 0 );
71         cvMerge( dist8u1, dist8u2, dist8u2, 0, dist8u );
72         // end "painting" the distance transform result
73     }
74     else
75     {
76         int i, j;
77         for( i = 0; i < labels->height; i++ )
78         {
79             int* ll = (int*)(labels->imageData + i*labels->widthStep);
80             float* dd = (float*)(dist->imageData + i*dist->widthStep);
81             uchar* d = (uchar*)(dist8u->imageData + i*dist8u->widthStep);
82             for( j = 0; j < labels->width; j++ )
83             {
84                 int idx = ll[j] == 0 || dd[j] == 0 ? 0 : (ll[j]-1)%8 + 1;
85                 int b = cvRound(colors[idx][0]);
86                 int g = cvRound(colors[idx][1]);
87                 int r = cvRound(colors[idx][2]);
88                 d[j*3] = (uchar)b;
89                 d[j*3+1] = (uchar)g;
90                 d[j*3+2] = (uchar)r;
91             }
92         }
93     }
94     
95     cvShowImage( wndname, dist8u );
96 }
97
98 int main( int argc, char** argv )
99 {
100     char* filename = argc == 2 ? argv[1] : (char*)"stuff.jpg";
101
102     if( (gray = cvLoadImage( filename, 0 )) == 0 )
103         return -1;
104
105     printf( "Hot keys: \n"
106         "\tESC - quit the program\n"
107         "\tC - use C/Inf metric\n"
108         "\tL1 - use L1 metric\n"
109         "\tL2 - use L2 metric\n"
110         "\t3 - use 3x3 mask\n"
111         "\t5 - use 5x5 mask\n"
112         "\t0 - use precise distance transform\n"
113         "\tv - switch Voronoi diagram mode on/off\n"
114         "\tENTER - loop through all the modes\n" );
115
116     dist = cvCreateImage( cvGetSize(gray), IPL_DEPTH_32F, 1 );
117     dist8u1 = cvCloneImage( gray );
118     dist8u2 = cvCloneImage( gray );
119     dist8u = cvCreateImage( cvGetSize(gray), IPL_DEPTH_8U, 3 );
120     dist32s = cvCreateImage( cvGetSize(gray), IPL_DEPTH_32S, 1 );
121     edge = cvCloneImage( gray );
122     labels = cvCreateImage( cvGetSize(gray), IPL_DEPTH_32S, 1 );
123
124     cvNamedWindow( wndname, 1 );
125
126     cvCreateTrackbar( tbarname, wndname, &edge_thresh, 255, on_trackbar );
127
128     for(;;)
129     {
130         int c;
131         
132         // Call to update the view
133         on_trackbar(0);
134
135         c = cvWaitKey(0);
136
137         if( (char)c == 27 )
138             break;
139
140         if( (char)c == 'c' || (char)c == 'C' )
141             dist_type = CV_DIST_C;
142         else if( (char)c == '1' )
143             dist_type = CV_DIST_L1;
144         else if( (char)c == '2' )
145             dist_type = CV_DIST_L2;
146         else if( (char)c == '3' )
147             mask_size = CV_DIST_MASK_3;
148         else if( (char)c == '5' )
149             mask_size = CV_DIST_MASK_5;
150         else if( (char)c == '0' )
151             mask_size = CV_DIST_MASK_PRECISE;
152         else if( (char)c == 'v' )
153             build_voronoi ^= 1;
154         else if( (char)c == '\n' || (char)c == '\r' )
155         {
156             if( build_voronoi )
157             {
158                 build_voronoi = 0;
159                 mask_size = CV_DIST_MASK_3;
160                 dist_type = CV_DIST_C;
161             }
162             else if( dist_type == CV_DIST_C )
163                 dist_type = CV_DIST_L1;
164             else if( dist_type == CV_DIST_L1 )
165                 dist_type = CV_DIST_L2;
166             else if( mask_size == CV_DIST_MASK_3 )
167                 mask_size = CV_DIST_MASK_5;
168             else if( mask_size == CV_DIST_MASK_5 )
169                 mask_size = CV_DIST_MASK_PRECISE;
170             else if( mask_size == CV_DIST_MASK_PRECISE )
171                 build_voronoi = 1;
172         }
173     }
174
175     cvReleaseImage( &gray );
176     cvReleaseImage( &edge );
177     cvReleaseImage( &dist );
178     cvReleaseImage( &dist8u );
179     cvReleaseImage( &dist8u1 );
180     cvReleaseImage( &dist8u2 );
181     cvReleaseImage( &dist32s );
182     cvReleaseImage( &labels );
183     
184     cvDestroyWindow( wndname );
185     
186     return 0;
187 }