Advertisement
Guest User

Untitled

a guest
Aug 3rd, 2017
714
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.42 KB | None | 0 0
  1. #include "opencv2/imgproc.hpp"
  2. #include "opencv2/imgcodecs.hpp"
  3. #include "opencv2/highgui.hpp"
  4. #include <iostream>
  5.  
  6. using namespace cv;
  7. using namespace std;
  8. double angle(cv::Point pt1, cv::Point pt2, cv::Point pt0) {
  9. double dx1 = pt1.x - pt0.x;
  10. double dy1 = pt1.y - pt0.y;
  11. double dx2 = pt2.x - pt0.x;
  12. double dy2 = pt2.y - pt0.y;
  13. return (dx1*dx2 + dy1*dy2) / sqrt((dx1*dx1 + dy1*dy1)*(dx2*dx2 + dy2*dy2) + 1e-10);
  14. }
  15.  
  16. void find_squares(Mat& image, vector<vector<Point> >& squares)
  17. {
  18. // blur will enhance edge detection
  19. Mat blurred(image);
  20. Mat dst;
  21. medianBlur(image, dst, 9);
  22.  
  23. Mat gray0(dst.size(), CV_8U), gray;
  24. vector<vector<Point> > contours;
  25.  
  26. // find squares in every color plane of the image
  27. for (int c = 0; c < 3; c++)
  28. {
  29. int ch[] = { c, 0 };
  30. mixChannels(&dst, 1, &gray0, 1, ch, 1);
  31.  
  32. // try several threshold levels
  33. const int threshold_level = 2;
  34. for (int l = 0; l < threshold_level; l++)
  35. {
  36. // Use Canny instead of zero threshold level!
  37. // Canny helps to catch squares with gradient shading
  38. if (l == 0)
  39. {
  40. Canny(gray0, gray, 10, 20, 3); //
  41.  
  42. // Dilate helps to remove potential holes between edge segments
  43. dilate(gray, gray, Mat(), Point(-1, -1));
  44. }
  45. else
  46. {
  47. gray = gray0 >= (l + 1) * 255 / threshold_level;
  48. }
  49.  
  50. // Find contours and store them in a list
  51. findContours(gray, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);
  52.  
  53. // Test contours
  54. vector<Point> approx;
  55. for (size_t i = 0; i < contours.size(); i++)
  56. {
  57. // approximate contour with accuracy proportional
  58. // to the contour perimeter
  59. approxPolyDP(Mat(contours[i]), approx, arcLength(Mat(contours[i]), true)*0.02, true);
  60.  
  61. // Note: absolute value of an area is used because
  62. // area may be positive or negative - in accordance with the
  63. // contour orientation
  64. if (approx.size() == 4 &&
  65. fabs(contourArea(Mat(approx))) > 1000 &&
  66. isContourConvex(Mat(approx)))
  67. {
  68. double maxCosine = 0;
  69.  
  70. for (int j = 2; j < 5; j++)
  71. {
  72. double cosine = fabs(angle(approx[j % 4], approx[j - 2], approx[j - 1]));
  73. maxCosine = MAX(maxCosine, cosine);
  74. }
  75.  
  76. if (maxCosine < 0.3)
  77. squares.push_back(approx);
  78. }
  79. }
  80. }
  81. }
  82. }
  83.  
  84.  
  85. cv::Mat debugSquares(std::vector<std::vector<cv::Point> > squares, cv::Mat image)
  86. {
  87. for (int i = 0; i< squares.size(); i++) {
  88. // draw contour
  89. cv::drawContours(image, squares, i, cv::Scalar(255, 0, 0), 1, 8, std::vector<cv::Vec4i>(), 0, cv::Point());
  90.  
  91. // draw bounding rect
  92. cv::Rect rect = boundingRect(cv::Mat(squares[i]));
  93. cv::rectangle(image, rect.tl(), rect.br(), cv::Scalar(0, 255, 0), 2, 8, 0);
  94.  
  95. // draw rotated rect
  96. cv::RotatedRect minRect = minAreaRect(cv::Mat(squares[i]));
  97. cv::Point2f rect_points[4];
  98. minRect.points(rect_points);
  99. for (int j = 0; j < 4; j++) {
  100. cv::line(image, rect_points[j], rect_points[(j + 1) % 4], cv::Scalar(0, 0, 255), 1, 8); // blue
  101. }
  102. }
  103.  
  104. return image;
  105. }
  106.  
  107. int main(int, char**)
  108. {
  109. int largest_area = 0;
  110. int largest_contour_index = 0;
  111. cv::Rect bounding_rect;
  112. Mat src = imread("15016889798859437.jpg");
  113. Mat greyMat = imread("15016889798859437.jpg", CV_LOAD_IMAGE_GRAYSCALE);
  114.  
  115. //2-convert image from gray scale to black and white using adaptive thresholding
  116. Mat blackAndWhiteMat;
  117. adaptiveThreshold(greyMat, blackAndWhiteMat, 255, CV_ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY_INV, 13, 1);
  118.  
  119.  
  120. Mat dst(src.rows, src.cols, CV_8UC1, Scalar::all(0));
  121. vector<Vec4i> hierarchy;
  122.  
  123. vector<vector<cv::Point>> contours; // Vector for storing contour
  124. find_squares(src, contours);
  125.  
  126.  
  127. for (int i = 0; i< contours.size(); i++) // iterate through each contour.
  128. {
  129. double a = contourArea(contours[i], false); // Find the area of contour
  130. if (a>largest_area) {
  131. largest_area = a;
  132. largest_contour_index = i; //Store the index of largest contour
  133. bounding_rect = boundingRect(contours[i]); // Find the bounding rectangle for biggest contour
  134. }
  135.  
  136. }
  137.  
  138. Scalar color(255, 255, 255);
  139. drawContours(dst, contours, largest_contour_index, color, CV_FILLED, 8, hierarchy); // Draw the largest contour using previously stored index.
  140. rectangle(src, bounding_rect, Scalar(0, 255, 0), 1, 8, 0);
  141.  
  142.  
  143.  
  144. Mat quad(src.size(), CV_8UC1); // should be improved
  145. Mat results(src.size(), CV_8UC3);
  146.  
  147. vector<Point2f> corners;
  148. vector<Point2f> quad_pts;
  149. quad_pts.push_back(cv::Point2f(0, 0));
  150. quad_pts.push_back(cv::Point2f(quad.cols, 0));
  151. quad_pts.push_back(cv::Point2f(quad.cols, quad.rows));
  152. quad_pts.push_back(cv::Point2f(0, quad.rows));
  153.  
  154.  
  155. for (size_t i = 0; i< contours.size(); i++)
  156. {
  157. RotatedRect minRect = minAreaRect(Mat(contours[i]));
  158.  
  159. // rotated rectangle
  160. Point2f rect_points[4];
  161. minRect.points(rect_points);
  162.  
  163. if (Rect(minRect.boundingRect()).width > src.cols / 2) // should be improved
  164. for (int j = 0; j < 4; j++)
  165. {
  166. Point2f pt = quad_pts[j];
  167. Point2f nearest_pt = rect_points[0];
  168. float dist = norm(pt - nearest_pt);
  169. for (int k = 1; k < 4; k++)
  170. {
  171. if (norm(pt - rect_points[k]) < dist)
  172. {
  173. dist = norm(pt - rect_points[k]);
  174. nearest_pt = rect_points[k];
  175. }
  176. }
  177. corners.push_back(nearest_pt);
  178. }
  179. }
  180.  
  181. Mat transmtx = getPerspectiveTransform(corners, quad_pts);
  182. warpPerspective(src, results, transmtx, src.size()); // Create a Mat To Show results
  183.  
  184. imshow("results", results);
  185.  
  186. cv::Mat result; // segmentation result (4 possible values)
  187. cv::Mat bgModel, fgModel; // the models (internally used)
  188.  
  189. // GrabCut segmentation
  190. cv::grabCut(src, // input image
  191. result, // segmentation result
  192. bounding_rect,// rectangle containing foreground
  193. bgModel, fgModel, // models
  194. 1, // number of iterations
  195. cv::GC_INIT_WITH_RECT); // use rectangle
  196. // Get the pixels marked as likely foreground
  197. cv::compare(result, cv::GC_PR_FGD, result, cv::CMP_EQ);
  198. // Generate output image
  199. cv::Mat foreground(src.size(), CV_8UC3, cv::Scalar(255, 255, 255));
  200. src.copyTo(foreground, result); // bg pixels not copied
  201.  
  202. // draw rectangle on original image
  203. cv::rectangle(src, bounding_rect, cv::Scalar(255, 255, 255), 1);
  204. resize(src, src, Size(), 0.5, 0.5);
  205.  
  206. cv::namedWindow("Image");
  207. cv::imshow("Image", src);
  208.  
  209. // display result
  210. cv::namedWindow("Segmented Image");
  211. resize(foreground, foreground, Size(), 0.5, 0.5);
  212. cv::imshow("Segmented Image", foreground);
  213.  
  214.  
  215. waitKey();
  216.  
  217.  
  218. return 0;
  219. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement