Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "opencv2/imgproc.hpp"
- #include "opencv2/imgcodecs.hpp"
- #include "opencv2/highgui.hpp"
- #include <iostream>
- using namespace cv;
- using namespace std;
- double angle(cv::Point pt1, cv::Point pt2, cv::Point pt0) {
- double dx1 = pt1.x - pt0.x;
- double dy1 = pt1.y - pt0.y;
- double dx2 = pt2.x - pt0.x;
- double dy2 = pt2.y - pt0.y;
- return (dx1*dx2 + dy1*dy2) / sqrt((dx1*dx1 + dy1*dy1)*(dx2*dx2 + dy2*dy2) + 1e-10);
- }
- void find_squares(Mat& image, vector<vector<Point> >& squares)
- {
- // blur will enhance edge detection
- Mat blurred(image);
- Mat dst;
- medianBlur(image, dst, 9);
- Mat gray0(dst.size(), CV_8U), gray;
- vector<vector<Point> > contours;
- // find squares in every color plane of the image
- for (int c = 0; c < 3; c++)
- {
- int ch[] = { c, 0 };
- mixChannels(&dst, 1, &gray0, 1, ch, 1);
- // try several threshold levels
- const int threshold_level = 2;
- for (int l = 0; l < threshold_level; l++)
- {
- // Use Canny instead of zero threshold level!
- // Canny helps to catch squares with gradient shading
- if (l == 0)
- {
- Canny(gray0, gray, 10, 20, 3); //
- // Dilate helps to remove potential holes between edge segments
- dilate(gray, gray, Mat(), Point(-1, -1));
- }
- else
- {
- gray = gray0 >= (l + 1) * 255 / threshold_level;
- }
- // Find contours and store them in a list
- findContours(gray, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);
- // Test contours
- vector<Point> approx;
- for (size_t i = 0; i < contours.size(); i++)
- {
- // approximate contour with accuracy proportional
- // to the contour perimeter
- approxPolyDP(Mat(contours[i]), approx, arcLength(Mat(contours[i]), true)*0.02, true);
- // Note: absolute value of an area is used because
- // area may be positive or negative - in accordance with the
- // contour orientation
- if (approx.size() == 4 &&
- fabs(contourArea(Mat(approx))) > 1000 &&
- isContourConvex(Mat(approx)))
- {
- double maxCosine = 0;
- for (int j = 2; j < 5; j++)
- {
- double cosine = fabs(angle(approx[j % 4], approx[j - 2], approx[j - 1]));
- maxCosine = MAX(maxCosine, cosine);
- }
- if (maxCosine < 0.3)
- squares.push_back(approx);
- }
- }
- }
- }
- }
- cv::Mat debugSquares(std::vector<std::vector<cv::Point> > squares, cv::Mat image)
- {
- for (int i = 0; i< squares.size(); i++) {
- // draw contour
- cv::drawContours(image, squares, i, cv::Scalar(255, 0, 0), 1, 8, std::vector<cv::Vec4i>(), 0, cv::Point());
- // draw bounding rect
- cv::Rect rect = boundingRect(cv::Mat(squares[i]));
- cv::rectangle(image, rect.tl(), rect.br(), cv::Scalar(0, 255, 0), 2, 8, 0);
- // draw rotated rect
- cv::RotatedRect minRect = minAreaRect(cv::Mat(squares[i]));
- cv::Point2f rect_points[4];
- minRect.points(rect_points);
- for (int j = 0; j < 4; j++) {
- cv::line(image, rect_points[j], rect_points[(j + 1) % 4], cv::Scalar(0, 0, 255), 1, 8); // blue
- }
- }
- return image;
- }
- int main(int, char**)
- {
- int largest_area = 0;
- int largest_contour_index = 0;
- cv::Rect bounding_rect;
- Mat src = imread("15016889798859437.jpg");
- Mat greyMat = imread("15016889798859437.jpg", CV_LOAD_IMAGE_GRAYSCALE);
- //2-convert image from gray scale to black and white using adaptive thresholding
- Mat blackAndWhiteMat;
- adaptiveThreshold(greyMat, blackAndWhiteMat, 255, CV_ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY_INV, 13, 1);
- Mat dst(src.rows, src.cols, CV_8UC1, Scalar::all(0));
- vector<Vec4i> hierarchy;
- vector<vector<cv::Point>> contours; // Vector for storing contour
- find_squares(src, contours);
- for (int i = 0; i< contours.size(); i++) // iterate through each contour.
- {
- double a = contourArea(contours[i], false); // Find the area of contour
- if (a>largest_area) {
- largest_area = a;
- largest_contour_index = i; //Store the index of largest contour
- bounding_rect = boundingRect(contours[i]); // Find the bounding rectangle for biggest contour
- }
- }
- Scalar color(255, 255, 255);
- drawContours(dst, contours, largest_contour_index, color, CV_FILLED, 8, hierarchy); // Draw the largest contour using previously stored index.
- rectangle(src, bounding_rect, Scalar(0, 255, 0), 1, 8, 0);
- Mat quad(src.size(), CV_8UC1); // should be improved
- Mat results(src.size(), CV_8UC3);
- vector<Point2f> corners;
- vector<Point2f> quad_pts;
- quad_pts.push_back(cv::Point2f(0, 0));
- quad_pts.push_back(cv::Point2f(quad.cols, 0));
- quad_pts.push_back(cv::Point2f(quad.cols, quad.rows));
- quad_pts.push_back(cv::Point2f(0, quad.rows));
- for (size_t i = 0; i< contours.size(); i++)
- {
- RotatedRect minRect = minAreaRect(Mat(contours[i]));
- // rotated rectangle
- Point2f rect_points[4];
- minRect.points(rect_points);
- if (Rect(minRect.boundingRect()).width > src.cols / 2) // should be improved
- for (int j = 0; j < 4; j++)
- {
- Point2f pt = quad_pts[j];
- Point2f nearest_pt = rect_points[0];
- float dist = norm(pt - nearest_pt);
- for (int k = 1; k < 4; k++)
- {
- if (norm(pt - rect_points[k]) < dist)
- {
- dist = norm(pt - rect_points[k]);
- nearest_pt = rect_points[k];
- }
- }
- corners.push_back(nearest_pt);
- }
- }
- Mat transmtx = getPerspectiveTransform(corners, quad_pts);
- warpPerspective(src, results, transmtx, src.size()); // Create a Mat To Show results
- imshow("results", results);
- cv::Mat result; // segmentation result (4 possible values)
- cv::Mat bgModel, fgModel; // the models (internally used)
- // GrabCut segmentation
- cv::grabCut(src, // input image
- result, // segmentation result
- bounding_rect,// rectangle containing foreground
- bgModel, fgModel, // models
- 1, // number of iterations
- cv::GC_INIT_WITH_RECT); // use rectangle
- // Get the pixels marked as likely foreground
- cv::compare(result, cv::GC_PR_FGD, result, cv::CMP_EQ);
- // Generate output image
- cv::Mat foreground(src.size(), CV_8UC3, cv::Scalar(255, 255, 255));
- src.copyTo(foreground, result); // bg pixels not copied
- // draw rectangle on original image
- cv::rectangle(src, bounding_rect, cv::Scalar(255, 255, 255), 1);
- resize(src, src, Size(), 0.5, 0.5);
- cv::namedWindow("Image");
- cv::imshow("Image", src);
- // display result
- cv::namedWindow("Segmented Image");
- resize(foreground, foreground, Size(), 0.5, 0.5);
- cv::imshow("Segmented Image", foreground);
- waitKey();
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement