distrans.cpp 5.1 KB

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