凸包:一组平面上的点,求一个包含所有点的最小的 凸多边形,这就是凸包问题。这可以形象地想成这样:在地上放置一些不可移动的木桩,用一根绳子把他们尽量紧地圈起来,并且为凸边形,这就是凸包了。
Graham扫描法:
步骤:
1、bgr转灰度;
2、canny边缘检测;
3、寻找轮廓;
4、轮廓转凸包;
5、画出轮廓和凸包。
#include<opencv2/opencv.hpp>
using namespace cv;
using namespace std;
void callback(int, void*);
Mat src, dst1,dst2, canny_img;;
int value = 80;
RNG rng(1);
int main(int arc, char** argv)
{
src = imread("1.jpg");
namedWindow("src",CV_WINDOW_AUTOSIZE);
imshow("src", src);
cvtColor(src, src, CV_BGR2GRAY);
blur(src, src, Size(3, 3));
namedWindow("output", CV_WINDOW_AUTOSIZE);
createTrackbar("threshold", "output", &value,255, callback);
callback(0, 0);
waitKey(0);
return 0;
}
void callback(int, void*){
//canny边缘检测
Canny(src, canny_img, value, 2 * value);
//寻找轮廓
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
findContours(canny_img, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE,Point(0,0));
//将轮廓转化为凸包
vector<vector<Point>> convexs(contours.size());
for (int i = 0; i < contours.size(); i++) {
convexHull(contours[i], convexs[i], false, true);
}
//画轮廓和凸包
dst1 = Mat::zeros(src.size(), CV_8UC3);
dst2 = Mat::zeros(src.size(), CV_8UC3);
for (int j = 0; j < contours.size(); j++) {
Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
drawContours(dst1, contours, j, color, 2);
drawContours(dst2, convexs, j, color, 2);
}
imshow("output",canny_img);
imshow("contours", dst1);
imshow("convexs", dst2);
}
运行结果如下: