Merge remote-tracking branch 'origin/2.4' into merge-2.4
[profile/ivi/opencv.git] / samples / cpp / distrans.cpp
1 #include <opencv2/core/utility.hpp>
2 #include "opencv2/imgproc.hpp"
3 #include "opencv2/highgui.hpp"
4
5 #include <stdio.h>
6
7 using namespace std;
8 using namespace cv;
9
10 int maskSize0 = DIST_MASK_5;
11 int voronoiType = -1;
12 int edgeThresh = 100;
13 int distType0 = DIST_L1;
14
15 // The output and temporary images
16 Mat gray;
17
18 // threshold trackbar callback
19 static void onTrackbar( int, void* )
20 {
21     static const Scalar colors[] =
22     {
23         Scalar(0,0,0),
24         Scalar(255,0,0),
25         Scalar(255,128,0),
26         Scalar(255,255,0),
27         Scalar(0,255,0),
28         Scalar(0,128,255),
29         Scalar(0,255,255),
30         Scalar(0,0,255),
31         Scalar(255,0,255)
32     };
33
34     int maskSize = voronoiType >= 0 ? DIST_MASK_5 : maskSize0;
35     int distType = voronoiType >= 0 ? DIST_L2 : distType0;
36
37     Mat edge = gray >= edgeThresh, dist, labels, dist8u;
38
39     if( voronoiType < 0 )
40         distanceTransform( edge, dist, distType, maskSize );
41     else
42         distanceTransform( edge, dist, labels, distType, maskSize, voronoiType );
43
44     if( voronoiType < 0 )
45     {
46         // begin "painting" the distance transform result
47         dist *= 5000;
48         pow(dist, 0.5, dist);
49
50         Mat dist32s, dist8u1, dist8u2;
51
52         dist.convertTo(dist32s, CV_32S, 1, 0.5);
53         dist32s &= Scalar::all(255);
54
55         dist32s.convertTo(dist8u1, CV_8U, 1, 0);
56         dist32s *= -1;
57
58         dist32s += Scalar::all(255);
59         dist32s.convertTo(dist8u2, CV_8U);
60
61         Mat planes[] = {dist8u1, dist8u2, dist8u2};
62         merge(planes, 3, dist8u);
63     }
64     else
65     {
66         dist8u.create(labels.size(), CV_8UC3);
67         for( int i = 0; i < labels.rows; i++ )
68         {
69             const int* ll = (const int*)labels.ptr(i);
70             const float* dd = (const float*)dist.ptr(i);
71             uchar* d = (uchar*)dist8u.ptr(i);
72             for( int j = 0; j < labels.cols; j++ )
73             {
74                 int idx = ll[j] == 0 || dd[j] == 0 ? 0 : (ll[j]-1)%8 + 1;
75                 float scale = 1.f/(1 + dd[j]*dd[j]*0.0004f);
76                 int b = cvRound(colors[idx][0]*scale);
77                 int g = cvRound(colors[idx][1]*scale);
78                 int r = cvRound(colors[idx][2]*scale);
79                 d[j*3] = (uchar)b;
80                 d[j*3+1] = (uchar)g;
81                 d[j*3+2] = (uchar)r;
82             }
83         }
84     }
85
86     imshow("Distance Map", dist8u );
87 }
88
89 static void help()
90 {
91     printf("\nProgram to demonstrate the use of the distance transform function between edge images.\n"
92             "Usage:\n"
93             "./distrans [image_name -- default image is stuff.jpg]\n"
94             "\nHot keys: \n"
95             "\tESC - quit the program\n"
96             "\tC - use C/Inf metric\n"
97             "\tL1 - use L1 metric\n"
98             "\tL2 - use L2 metric\n"
99             "\t3 - use 3x3 mask\n"
100             "\t5 - use 5x5 mask\n"
101             "\t0 - use precise distance transform\n"
102             "\tv - switch to Voronoi diagram mode\n"
103             "\tp - switch to pixel-based Voronoi diagram mode\n"
104             "\tSPACE - loop through all the modes\n\n");
105 }
106
107 const char* keys =
108 {
109     "{@image |stuff.jpg|input image file}"
110 };
111
112 int main( int argc, const char** argv )
113 {
114     help();
115     CommandLineParser parser(argc, argv, keys);
116     string filename = parser.get<string>(0);
117     gray = imread(filename.c_str(), 0);
118     if(gray.empty())
119     {
120         printf("Cannot read image file: %s\n", filename.c_str());
121         help();
122         return -1;
123     }
124
125     namedWindow("Distance Map", 1);
126     createTrackbar("Brightness Threshold", "Distance Map", &edgeThresh, 255, onTrackbar, 0);
127
128     for(;;)
129     {
130         // Call to update the view
131         onTrackbar(0, 0);
132
133         int c = waitKey(0) & 255;
134
135         if( c == 27 )
136             break;
137
138         if( c == 'c' || c == 'C' || c == '1' || c == '2' ||
139             c == '3' || c == '5' || c == '0' )
140             voronoiType = -1;
141
142         if( c == 'c' || c == 'C' )
143             distType0 = DIST_C;
144         else if( c == '1' )
145             distType0 = DIST_L1;
146         else if( c == '2' )
147             distType0 = DIST_L2;
148         else if( c == '3' )
149             maskSize0 = DIST_MASK_3;
150         else if( c == '5' )
151             maskSize0 = DIST_MASK_5;
152         else if( c == '0' )
153             maskSize0 = DIST_MASK_PRECISE;
154         else if( c == 'v' )
155             voronoiType = 0;
156         else if( c == 'p' )
157             voronoiType = 1;
158         else if( c == ' ' )
159         {
160             if( voronoiType == 0 )
161                 voronoiType = 1;
162             else if( voronoiType == 1 )
163             {
164                 voronoiType = -1;
165                 maskSize0 = DIST_MASK_3;
166                 distType0 = DIST_C;
167             }
168             else if( distType0 == DIST_C )
169                 distType0 = DIST_L1;
170             else if( distType0 == DIST_L1 )
171                 distType0 = DIST_L2;
172             else if( maskSize0 == DIST_MASK_3 )
173                 maskSize0 = DIST_MASK_5;
174             else if( maskSize0 == DIST_MASK_5 )
175                 maskSize0 = DIST_MASK_PRECISE;
176             else if( maskSize0 == DIST_MASK_PRECISE )
177                 voronoiType = 0;
178         }
179     }
180
181     return 0;
182 }