文章目录

  • 凸包介绍
    • 什么是凸包?
    • 正式定义:
    • 凸包查找——Graham扫描算法
      • Graham算法例题
  • 相关API
    • convexHull
  • 找到凸包步骤
  • 代码示例

凸包介绍

什么是凸包?

什么是凸包(Convex Hull),在一个多变形边缘或者内部任意两个点的连线都包含在多边形边界或者内部。

例如下图左侧为凸包,右侧因为有两个点的连线不包含在多边形边界或者内部,所以不是凸包

正式定义:

包含点集合S中所有点的最小凸多边形称为凸包

凸包查找——Graham扫描算法

  1. 首先选择Y方向最低的点作为起始点p0
  2. 从p0开始极坐标扫描,依次添加p1….pn(排序顺序是根据极坐标的角度大小,逆时针方向),添加的思想是:先找到凸包上的一个点,然后从那个点开始按逆时针方向逐个找凸包上的点,实际上就是进行极角排序,然后对其查询使用。
  3. 对每个点pi来说,如果添加pi点到凸包中导致一个左转向(逆时针方法)则添加该点到凸包, 反之如果导致一个右转向(顺时针方向)删除该点从凸包中

Graham算法例题

例如下图:下面点找到凸包

步骤:

1.把所有点放在二维坐标系中,则纵坐标最小的点一定是凸包上的点,如图中的P0。

2.把所有点的坐标平移一下,使 P0 作为原点,如下图。

3.计算各个点相对于 P0 的幅角 α ,按从小到大的顺序对各个点排序。当 α 相同时,距离 P0 比较近的排在前面。例如上图得到的结果为 P1,P2,P3,P4,P5,P6,P7,P8。我们由几何知识可以知道,结果中第一个点 P1 和最后一个点 P8 一定是凸包上的点。

(以上是准备步骤:找点,排号,以下开始求凸包)
以上,我们已经知道了凸包上的第一个点 P0 和第二个点 P1,我们把它们放在栈里面。现在从步骤3求得的那个结果里,把 P1 后面的那个点拿出来做当前点,即 P2 。接下来开始找第三个点:

4.连接P0和栈顶的那个点,得到直线 L 。看当前点是在直线 L 的右边还是左边。如果在直线的右边就执行步骤5;如果在直线上,或者在直线的左边就执行步骤6。

5.如果在右边,则栈顶的那个元素不是凸包上的点,把栈顶元素出栈。执行步骤4。

6.当前点是凸包上的点,把它压入栈,执行步骤7。

7.检查当前的点 P2 是不是步骤3那个结果的最后一个元素。是最后一个元素的话就结束。如果不是的话就把 P2 后面那个点做当前点,返回步骤4。

最后,栈中的元素就是凸包上的点了。

以下为用Graham扫描法动态求解的过程:

下面静态求解过程






当然,这么负责不要担心,我们只是需要了解,OpenCV已经实现了凸包发现算法和API提供我们使用。

相关API

convexHull

函数作用:

  • opencv提供了convexHull()函数来查找图像中物体的凸包

函数原型:

void cv::convexHull (  InputArray  points,OutputArray     hull,bool    clockwise = false,bool    returnPoints = true
)

函数参数:

  • points:输入的二维点集,Mat类型数据即可
  • hull:输出参数,用于输出函数调用后找到的凸包
  • clockwise:操作方向,当标识符为真时,输出凸包为顺时针方向,否则为逆时针方向。
  • returnPoints:操作标识符,默认值为true,此时返回各凸包的各个点,否则返回凸包各点的指数,当输出数组时std::vector时,此标识被忽略。

找到凸包步骤

  • 首先把图像从RGB转为灰度
  • 然后再转为二值图像
  • 在通过发现轮廓得到候选点
  • 凸包API调用
  • 绘制显示。

代码示例

#include <iostream>
#include <math.h>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/highgui/highgui_c.h> using namespace std;
using namespace cv;
Mat src, src_gray, dst;
int threshold_value = 100;
int threshold_max = 255;
const char* output_win = "convex hull demo";
void Threshold_Callback(int, void*);
RNG rng(12345);int main(int argc, char** argv)
{src = imread("./test2.jpg");if (!src.data) {printf("could not load image...\n");return -1;}const char* input_win = "input image";namedWindow(input_win, CV_WINDOW_AUTOSIZE);namedWindow(output_win, CV_WINDOW_NORMAL);const char* trackbar_label = "Threshold : ";cvtColor(src, src_gray, CV_BGR2GRAY);blur(src_gray, src_gray, Size(3, 3), Point(-1, -1), BORDER_DEFAULT);imshow(input_win, src_gray);createTrackbar(trackbar_label, output_win, &threshold_value, threshold_max, Threshold_Callback);Threshold_Callback(0, 0);waitKey(0);return 0;
}void Threshold_Callback(int, void*) {Mat bin_output;vector<vector<Point>> contours;vector<Vec4i> hierachy;// 设定灰度阈值threshold(src_gray, bin_output, threshold_value, threshold_max, THRESH_BINARY);findContours(bin_output, contours, hierachy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));vector<vector<Point>> convexs(contours.size());for (size_t i = 0; i < contours.size(); i++) {convexHull(contours[i], convexs[i], false, true);}// 绘制凸包dst = Mat::zeros(src.size(), CV_8UC3);vector<Vec4i> empty(0);for (size_t k = 0; k < contours.size(); k++) {Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));drawContours(dst, contours, k, color, 2, LINE_8, hierachy, 0, Point(0, 0));drawContours(dst, convexs, k, color, 2, LINE_8, empty, 0, Point(0, 0));}imshow(output_win, dst);return;
}

OpenCV 凸包查找,Graham详解相关推荐

  1. c++ opencv函数putText用法详解

    c++ opencv函数putText用法详解 #include <stdio.h> #include <iostream> #include <opencv2/open ...

  2. linux find 命令通配符,linux find命令查找文件详解

    首页 > Linux教程 > 常用命令 > find 查找文件 linux find命令查找文件详解 linux中find命令用来在指定目录下查找文件,如果使用该命令时,不设置任何参 ...

  3. 二分查找算法详解(附代码)

    二分查找算法详解(附代码) 注: 现有一个升序 不重复的数组 查询target是否在此数组中并返回序号 使用条件 使用二分算法的两个条件: 有序 不重复 混淆处 二分算法两种方式容易弄混淆的地方:就是 ...

  4. python实现二分查找代码+详解

    python实现二分查找代码+详解 一.规定函数值 函数输入值 li=[1,2,3,4,5,6,7,8,9]#输入的集合 val=4#要查找的值 函数内部值 left=0#代表集合中第一个值的位置 r ...

  5. Linux下文件查找使用详解-羽飞作品

    Linux下文件查找使用详解 (1/3) http://www.boobooke.com/v/bbk1579 Linux下文件查找使用详解 (2/3) http://www.boobooke.com/ ...

  6. OpenCV SIFT源码详解——总体概览

    OpenCV SIFT源码详解--总体概览 一.版本 二.章节系列 此系列文章源自本人硕士毕业论文,主要讲源码,对于SIFT理论知识默认大家有过了解.若文章中有不对之处还请读者指出. 一.版本 本系列 ...

  7. java斐波那契查找_详解Java Fibonacci Search斐波那契搜索算法代码实现

    一, 斐波那契搜索算法简述 斐波那契搜索(Fibonacci search) ,又称斐波那契查找,是区间中单峰函数的搜索技术. 斐波那契搜索采用分而治之的方法,其中我们按照斐波那契数列对元素进行不均等 ...

  8. opencv的逻辑运算bitwise详解

    官网介绍 http://docs.opencv.org/2.4/modules/core/doc/operations_on_arrays.html# 代码 #include <windows. ...

  9. 【OpenCV实战】OpenCV实现人脸检测详解(含代码)

    OpenCV中有许多可以进行人脸.人眼检测的特征文件,今天我们利用OpenCV中自带的特征文件haarcascade_frontalface_default.xml来进行人脸检测. [OpenCV实战 ...

最新文章

  1. geohash java github_GitHub - GongDexing/Geohash: GeoHash是目前比较主流实现位置服务的技术,用最简洁的Java实现GeoHash算法...
  2. oracle创建索引---如何创建所以
  3. 虚拟机配置网络eth1
  4. sql语句中嵌套2层循环
  5. python读excel两列为字典_用python读取Excel并保存字典?一两行代码完成骚操作
  6. Integer对象范围(-128-127)之间(Integer. valueOf()方法)
  7. jq之slideup()
  8. [转载] Python中定义函数,循环语句,条件语句
  9. access百度翻译 get_Asp.NET调用百度翻译
  10. SVN-您的主机中的软件中止了一个已建立的连接
  11. 【Java】java测试--词频统计 ----IO流操作
  12. JAVA排序:快速排序算法
  13. java爬虫-2018国家统计局区划和城乡划分代码以及数据库、json文件
  14. 武汉理工大学计算机考研专业代码,武汉理工大学代码及专业代码
  15. 反向题在测试问卷信效度_关于调查问卷的信度和效度检验
  16. Mac安装 nginx (极简)
  17. 读《我怎样设计飞机》
  18. D社创始人 苟方韬:当二次元恋上区块链,如何引爆流量
  19. 树莓派+SAKS扩展板实现数码管时钟
  20. python 柱状图 内部颜色_Matplotlib/seaborn柱状图使用不同的颜色分组存储箱

热门文章

  1. 自定义邮箱和手机号码的校验规则
  2. Inno Setup选择语言并写入配置文件、翻译提示信息
  3. adaboost.M1与adaboost.M2差别比较
  4. 企业抖音蓝V怎么认证?申请流程是怎样的?需要具备哪些条件?
  5. css寸照的自适应比例设置
  6. js弹幕脚本(基于油猴)
  7. tkinter-canvas详解
  8. 元宇宙NFT最近最火的项目,该如何选择平台呢
  9. 2023年全国最新二级建造师精选真题及答案27
  10. Android-进阶教程-权限-特殊权限-AppOps