SHARE
TWEET

Untitled

a guest Aug 3rd, 2017 263 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  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. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top