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