1 #include <opencv2/opencv.hpp>
  2 #include <iostream>
  3 
  4 using namespace std;
  5 using namespace cv;
  6 
  7 Mat searchConcaveRegion(vector<vector<Point> >hull, Mat &src);
  8 vector<Point2f> searchConcavePoint(Mat &src);
  9 
 10 void main()
 11 {
 12     Mat img = imread("C:\\4.jpg",1);
 13     Mat gray, gray_back;
 14 
 15     cvtColor(img, gray, CV_BGR2GRAY);
 16     
 17     threshold(gray, gray, 0, 255, CV_THRESH_OTSU);
 18     gray_back = gray.clone();
 19 
 20     //提取轮廓
 21     vector<vector<Point>>contours;
 22     findContours(gray, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
 23     drawContours(img, contours, -1, Scalar(0, 0, 255), 2);
 24 
 25     Mat aotu = searchConcaveRegion(contours, gray_back);
 26     vector<Point2f> pt;
 27     pt = searchConcavePoint(aotu);
 28 
 29     line(img, pt[pt.size() - 2], pt[pt.size() - 1], Scalar(255, 0, 0), 2, 8, 0);
 30 
 31     imshow("切割线", img);
 32     waitKey(0);
 33 }
 34 
 35 /**
 36 * @brief searchConcaveRegion 寻找凹区域
 37 * @param hull  凸包点集
 38 * @param src  原图像(二值图)
 39 * @return 返回 图像凹区域
 40 */
 41 Mat searchConcaveRegion(vector<vector<Point> >contours, Mat &src)
 42 {
 43     if (src.empty())
 44         return Mat();
 45 
 46     //遍历每个轮廓,寻找其凸包
 47     vector<vector<Point>>hull(contours.size());
 48     for (unsigned int i = 0; i<contours.size(); ++i)
 49     {
 50         convexHull(Mat(contours[i]), hull[i], false);
 51     }
 52 
 53     //绘制轮廓及其凸包
 54     Mat drawing = Mat::zeros(src.rows, src.cols, CV_8UC1);
 55     for (unsigned int i = 0; i < contours.size(); ++i)
 56     {
 57         drawContours(drawing, hull, i, Scalar(255), -1, 8, vector<Vec4i>(), 0, Point());
 58         drawContours(drawing, contours, i, Scalar(0), -1, 8, vector<Vec4i>(), 0, Point());
 59     }
 60 
 61     medianBlur(drawing, drawing, 3);
 62 
 63     imshow("凹区域", drawing);
 64 
 65     return drawing;
 66 }
 67 
 68 /**
 69 * @brief searchConcavePoint
 70 * @param src 凹区域图像
 71 * @return 返回匹配好的凹点对(2个)
 72 */
 73 vector<Point2f> searchConcavePoint(Mat &src)
 74 {
 75     vector<Point2f> ConcavePoint;
 76     //轮廓寻找  
 77     vector<vector<Point> > contour;//用来存储轮廓  
 78     vector<Vec4i> hierarchys;
 79     findContours(src, contour, hierarchys,
 80         CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));  //寻找轮廓  
 81 
 82     //凹区域少于2要退出  
 83     if (contour.size()<2)
 84         return ConcavePoint;
 85 
 86     //按照轮廓面积大小排序  
 87     sort(contour.begin(), contour.end(), [](const vector<Point> &s1,
 88         const vector<Point> &s2){
 89         double a1 = contourArea(s1);
 90         double a2 = contourArea(s2);
 91         return a1>a2;
 92     });
 93 
 94     int minDistance = 100000000;//最短距离  
 95     for (int i = 0; i<contour[0].size(); ++i)
 96     for (int j = 0; j<contour[1].size(); ++j)
 97     {
 98         //欧氏距离  
 99         int d = sqrt(pow((contour[0][i].x - contour[1][j].x), 2) +
100             pow((contour[0][i].y - contour[1][j].y), 2));
101         if (minDistance>d)
102         {
103             minDistance = d;
104             ConcavePoint.push_back(contour[0][i]);
105             ConcavePoint.push_back(contour[1][j]);
106         }
107     }
108     cout << "ConcavePoint0:" << ConcavePoint[ConcavePoint.size() - 2].x << "," << ConcavePoint[ConcavePoint.size() - 2].y << endl;
109     cout << "ConcavePoint1:" << ConcavePoint[ConcavePoint.size() - 1].x << "," << ConcavePoint[ConcavePoint.size() - 1].y << endl;
110 
111     return ConcavePoint;
112 }