凸包的定义:
包含点集 S 所有点的最小凸多边形称为凸包。
凸包绘制原理:Graham 扫描法
- 首先选择 y 方向上最低的点作为起始点 p0。
- 然后以 p0 为原点,建立极坐标系,做逆时针极坐标扫描,依次添加凸包点 p1,p2 ...pn(排序顺序根据极坐标角度大小)
- 若当前扫描点与下一个点构成的直线为逆时针转向,且转角 > 180°,则将该点添加到凸包点集合,否则忽略。
寻找凸包:convexHull 函数
void convexHull(InputArray points, OutputArray hull, bool clockwise = false, bool returnPoints = true);
- points,输入的二维点集,可以填 Mat 类型或者 vector。
- hull,输出参数,函数调用后找到的凸包。
- clockwise,操作方向标识符。当此标识符为 true 时,输出凸包为顺时针方向,否则为逆时针方向,默认为 false。并且假设坐标系的 x 轴指右,y 轴指上。
- returnPoints,当标志为真时,函数返回各凸包的各个点。否则返回凸包各点的指数。
代码示例:
#include<opencv.hpp>
#include<iostream>
using namespace cv;
using namespace std;
int main(){
Mat src = imread("C:/Users/齐明洋/Desktop/1.jpg");
imshow("src", src);
Mat gray, bin_img;
cvtColor(src, gray, COLOR_BGR2GRAY);
medianBlur(gray, gray, 3);//中值滤波,去除椒盐噪声
imshow("gray", gray);
//获得二值图像,canny 和 threshold 两种方法都可以
//Canny(gray, bin_img, 20, 40, 3);
threshold(gray, bin_img, 80, 255, THRESH_BINARY);
imshow("bin_img", bin_img);
//获取轮廓
vector<vector<Point> >contours;
findContours(bin_img, contours, RETR_TREE, CHAIN_APPROX_NONE);
//获取凸包
vector<vector<Point> >hull(contours.size());
Mat dst = Mat(src.size(), src.type());
for (int i = 0; i < contours.size(); i++) {
convexHull(contours[i], hull[i]);
drawContours(dst, hull, i, Scalar(0, 0, 255), 1);
}
imshow("dst", dst);
waitKey(0);
}
效果演示:
借鉴博客:https://blog.csdn.net/just_tree/article/details/89296985