lines.cpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. #include<cmath>
  2. #include<algorithm>
  3. #ifdef HAS_OPENCV3
  4. #include <opencv2/core.hpp> //Any OPENCV3 code
  5. #else
  6. #include <opencv2/core/core.hpp> //Any Opencv2 code
  7. #endif
  8. #include"lines.h"
  9. #include "geometry.h"
  10. #include "cvutils.h"
  11. using namespace cv;
  12. #define likely(x) __builtin_expect(!!(x), 1)
  13. #define unlikely(x) __builtin_expect(!!(x), 0)
  14. // all those colors are still visible on b/w (the first component is not so low)
  15. auto WHITE = cv::Scalar(255,255,255);
  16. auto BLUE = cv::Scalar(200,50,50);
  17. auto MAGENTA = cv::Scalar(110,10,200);
  18. auto BROWN = cv::Scalar(90,100,60);
  19. int main(int argc, char *argv[])
  20. {
  21. char const *fname = "files/masckera.png";
  22. if( 1<argc )
  23. fname = argv[1];
  24. if( 2<argc) {
  25. std::cerr << "Too many arguments" << std::endl;
  26. return EXIT_FAILURE;
  27. }
  28. cv::Mat img;
  29. img=cv::imread(fname,CV_LOAD_IMAGE_GRAYSCALE);
  30. if( img.empty() ) {
  31. std::cerr << "Error opening image, aborting" << std::endl;
  32. return EXIT_FAILURE;
  33. }
  34. std::vector< std::vector<cv::Point> > contours;
  35. std::vector<cv::Vec4i> hierarchy;
  36. cv::findContours(img,contours,hierarchy,CV_RETR_EXTERNAL,CV_CHAIN_APPROX_SIMPLE);
  37. unsigned short dotwidth = img.cols >> 6; // divide by 64, so efficient
  38. //img = cv::imread(fname,CV_LOAD_IMAGE_COLOR); // uncomment to this to display image with colors
  39. cv::drawContours(img,contours,-1,BROWN,dotwidth>>4);
  40. if( 0==contours.size() ) {
  41. std::cerr << "No contours found" << std::endl;
  42. return EXIT_FAILURE;
  43. }
  44. auto contour = contours[0];
  45. if( 1!=contours.size() )
  46. {
  47. // choosing the biggest contour in the image
  48. // you can test it with files/2contours.png
  49. for(auto cont: contours) {
  50. if(cont.size() > contour.size())
  51. contour = cont;
  52. }
  53. }
  54. std::vector<cv::Point> hull;
  55. cv::convexHull(cv::Mat(contour),hull,false);
  56. //these are the "horizontal" lines
  57. unsigned *maxdistances = max2_distance(hull);
  58. cv::Point corn_1, corn_2, corn_3, corn_4;
  59. corn_1 = hull[maxdistances[0]];
  60. corn_2 = hull[(maxdistances[0]+1)%hull.size()];
  61. corn_3 = hull[maxdistances[1]];
  62. corn_4 = hull[(maxdistances[1]+1)%hull.size()];
  63. #ifdef _DEBUG
  64. img = cv::imread(fname,CV_LOAD_IMAGE_COLOR); // uncomment to this to display image with colors
  65. std::cout << "Maxdist1:" << maxdistances[0] << " " << corn_1 << corn_2 << std::endl;
  66. std::cout << "Maxdist2:" << maxdistances[1] << " " << corn_3 << corn_4 << std::endl;
  67. cv::circle(img,corn_1,dotwidth>>1,MAGENTA,2);
  68. cv::circle(img,corn_2,dotwidth>>2,MAGENTA,2);
  69. cv::circle(img,corn_3,dotwidth>>2,BROWN,2);
  70. cv::circle(img,corn_4,dotwidth>>2,BROWN,2);
  71. cv::namedWindow("win", CV_GUI_NORMAL);
  72. // cv::imshow("4 corners",img);
  73. // cv::waitKey(0);
  74. #endif
  75. std::vector<std::vector<cv::Point>> verticals;
  76. verticals.push_back(find_longest_line(hull, (maxdistances[0]+1)%hull.size(), maxdistances[1]));
  77. std::cout << maxdistances[1] << std::endl;
  78. std::cout << maxdistances[1]+1 << std::endl;
  79. std::cout << (maxdistances[1]+1)%hull.size() << std::endl;
  80. verticals.push_back(find_longest_line(hull, (maxdistances[1]+1)%hull.size(), maxdistances[0]));
  81. free(maxdistances);
  82. #ifdef _DEBUG
  83. //img = cv::imread(fname,CV_LOAD_IMAGE_COLOR); // uncomment to this to display image with colors
  84. auto color = MAGENTA;
  85. for( auto line: verticals )
  86. {
  87. color = (color==BLUE) ? MAGENTA : BLUE; //flip color for the two lines
  88. cv::Point p1 = line[0];
  89. cv::Point p2 = line[line.size()-1];
  90. cv::line(img, p1, p2, color, dotwidth>>4);
  91. std::cout << "vertical: " << line[0] << line[line.size()-1] << std::endl;
  92. for(cv::Point p: line)
  93. {
  94. cv::circle(img,p,dotwidth>>3,color,-1);
  95. }
  96. }
  97. cv::imshow("win",img);
  98. while(1)
  99. {
  100. if( cv::waitKey(0) == 113 )
  101. break;
  102. }
  103. img.release();
  104. #endif
  105. // theta is the angle of the line connecting point 1 and 2; it will be the
  106. // rotation of our new coordinate system
  107. double theta = atan(((double)corn_1.y - corn_2.y)/(corn_1.x - corn_2.x));
  108. std::cout << "Theta = " << theta << std::endl;
  109. assert(map_point(theta, corn_1, corn_1).x == 0);
  110. assert(map_point(theta, corn_1, corn_1).y == 0);
  111. assert(map_point(theta, corn_1, corn_2).y == 0);
  112. return EXIT_SUCCESS;
  113. }
  114. // vim: set noet ts=4 sw=4: