凸包

【opencv】凸包算法之寻找凸包convexHull

好久不见. 提交于 2019-12-07 17:14:27
1.概述 凸包(Convex Hull)是一个计算几何(图形学)中的概念,在一个实数向量空间V中,对于给定集合X,所有包含X的凸集的交集S被称为X的凸包。 X的凸包可以用X内所有点(x1, x2….xn)的线性组合来构造。在二维欧几里得空间中,凸包可以想象为一条刚好包着所有点的橡皮圈,用不严谨的话来讲,给定二维平面上的点集,凸包就是将最外层的点连接起来构成的凸多边形,它能包含点集中所有的点。常见的有Graham’s Scan法和Jarvis步进法 2.原理 2.1Graham’s Scan法 Graham扫描法通过不断在凸壳中加入新的点和去除影响凸性的点,最后形成凸包。算法的主体由两部分组成,先是排序,然后扫描。 (1)点集排序 为了得到加入新点的顺序,Graham扫描法的第一步是对点集排序,对杂乱的点集进行梳理,这也是这种算法能够得到更高效的根本原因。排序的方法有极角坐标排序(极角序)和直角坐标排序(水平序)两种方法。在实现的时候,直角坐标排序比较方便。 对于极角序,首先选取一个参考点,一般选取横坐标最小的点作为参考点,如果有多个这样的点就从这些点钟选取纵坐标最小的点。如下图: 这样就决定了参考点的性质:点集中任意两点和参考点锁成的倒角为锐角。 极角排序以参考点为极角坐标系原点,根据上述参考点性质,可以设所有点的极角均在(-90,90]之间,排序完成后如下图所示: (2)栈扫描

opencv3检测凸包convexHull函数-使用方式二

青春壹個敷衍的年華 提交于 2019-12-07 17:14:13
#include<opencv2/opencv.hpp> #include<iostream> #include<vector> using namespace cv; using namespace std; int main() { RNG &rng = theRNG(); Mat srcImage = imread("1.jpg"); imshow("【原图】", srcImage); //因为后期需要在二值图像中寻找轮廓,所以需要进行阀值操作或是使用canny边缘检测操作,无论是哪种方式,都需要输入一张灰度图像 //所以这里先进行图像格式的转换 Mat grayImage; cvtColor(srcImage, grayImage, CV_BGR2GRAY); //处理图像之前先对图像进行滤波操作 Mat blurImage; GaussianBlur(grayImage, blurImage, Size(3, 3), 0, 0); imshow("【高斯滤波后的灰度图】", blurImage); //这里采用边缘检测的方式来生成二值图像 Mat cannyImage; Canny(blurImage, cannyImage, 1, 128); //在得到的二值图像中寻找轮廓 //g_vcontours用来存储 所有轮廓 的 点向量 vector<vector<Point

OpenCV之凸包(convexhull)

社会主义新天地 提交于 2019-12-07 17:12:20
关于凸包原理:Convex Hull 在多維空間中有一群散佈各處的點,「凸包」是包覆這群點的所有外殼當中,表面積暨容積最小的一個外殼,而最小的外殼一定是凸的。 作者提到多种实现方法: Graham’s Scan Jarvis’ March( Gift Wrapping Algorithm ) 具体参考下面链接: http://www.csie.ntnu.edu.tw/~u91029/ConvexHull.html OpenCV 样例 OpenCV3.4版本 https://docs.opencv.org/3.4.4/d5/d04/samples_2cpp_2convexhull_8cpp-example.html#a12 OpenCV2.4版本 https://docs.opencv.org/2.4.13.7/doc/tutorials/imgproc/shapedescriptors/hull/hull.html 通过上面的学习,我们已经掌握了凸包的使用方法。接下来我们动手自己实现一个: int main() { Mat img(500, 500, CV_8UC3); RNG& rng = theRNG(); cout << "\n这个程序演示了凸包函数的使用,任意给定一些点,求 来源: CSDN 作者: 北络 链接: https://blog.csdn.net

opencv学习(四十一)之寻找凸包convexHull()

半腔热情 提交于 2019-12-07 17:11:45
1.概述 凸包(Convex Hull)是一个计算几何(图形学)中的概念,在一个实数向量空间V中,对于给定集合X,所有包含X的凸集的交集S被称为X的凸包。 X的凸包可以用X内所有点(x1, x2….xn)的线性组合来构造。在二维欧几里得空间中,凸包可以想象为一条刚好包着所有点的橡皮圈,用不严谨的话来讲,给定二维平面上的点集,凸包就是将最外层的点连接起来构成的凸多边形,它能包含点集中所有的点。常见的有Graham’s Scan法和Jarvis步进法 2.原理 2.1Graham’s Scan法 Graham扫描法通过不断在凸壳中加入新的点和去除影响凸性的点,最后形成凸包。算法的主体由两部分组成,先是排序,然后扫描。 (1)点集排序 为了得到加入新点的顺序,Graham扫描法的第一步是对点集排序,对杂乱的点集进行梳理,这也是这种算法能够得到更高效的根本原因。排序的方法有极角坐标排序(极角序)和直角坐标排序(水平序)两种方法。在实现的时候,直角坐标排序比较方便。 对于极角序,首先选取一个参考点,一般选取横坐标最小的点作为参考点,如果有多个这样的点就从这些点钟选取纵坐标最小的点。如下图: 这样就决定了参考点的性质:点集中任意两点和参考点锁成的倒角为锐角。 极角排序以参考点为极角坐标系原点,根据上述参考点性质,可以设所有点的极角均在(-90,90]之间,排序完成后如下图所示: (2)栈扫描

opencv3检测凸包convexHull函数-使用方法一

限于喜欢 提交于 2019-12-07 17:11:33
#include<iostream> #include<opencv2/opencv.hpp> #include<vector> using namespace cv; using namespace std; int main() { //先初始化变量 Mat srcImage(Size(600, 600), CV_8UC3, Scalar(0)); Mat saveImage; srcImage.copyTo(saveImage); RNG &rng = theRNG(); char key; Point midPoint; //hull 变量用来存储点的序号 vector<int> hull; while (1) { //因为下面是入栈操作,所以,需要在循环内为变量分配空间,否则,栈内的数据无法出栈 vector<Point> points; //首先确定随机点的坐标,以及随机点落定的范围 int count = (unsigned int)rng % 100 + 3; for (int i = 0; i < count; i++) { //确定随机点的范围 midPoint.x = rng.uniform(srcImage.cols / 4, srcImage.cols * 3 / 4); midPoint.y = rng.uniform(srcImage.rows / 4

二维凸包模板

不打扰是莪最后的温柔 提交于 2019-12-06 12:53:23
[LuoguP2742] 凸包,就是说用一根有弹性的橡皮筋来围住平面上一堆点,然后求这根橡皮筋的长度 这里要有一些前置芝士: 向量积 Code: 1 #include <bits/stdc++.h> 2 using namespace std; 3 const int N = 1e4 + 7; 4 int n; 5 double ans; 6 struct node{ 7 double x, y; 8 }stk[N], a[N]; 9 double Cj(node a1, node a2, node b1, node b2) { 10 return (a2.x - a1.x) * (b2.y - b1.y) - (b2.x - b1.x) * (a2.y - a1.y); 11 }//向量的叉积,公式是(x1*y2 - x2 * y1) 12 //如果叉积大于0,代表左旋,反之就是右旋 13 double getdis(node a, node b) {//两点间距离公式 14 return sqrt((double)(a.x - b.x) * (a.x - b.x) + (double)(a.y - b.y) * (a.y - b.y)); 15 } 16 bool cmp(node a1, node b) {//按叉积排序 17 double now = Cj(a[1], a1

旋转卡壳

自古美人都是妖i 提交于 2019-12-06 11:56:44
例题: P1452 . 题意:找到所有点对的最大距离。 一个凸包可以把所有点给包含进去,很明显最大距离点对是凸包上的点的点对。于是现在求凸包的最长直径。 旋转卡壳 依次按照极角枚举凸包上的边,找出与这条边最远距离的顶点,寻找这个点可以通过叉积算三角形面积实现。很明显顺次枚举边时,顶点也是顺次移动的,可以证明移动顶点复杂度为 \(O(n)\) 。对于每个边和其对应顶点所形成的三角形,答案与这三条边取 \(max\) 就行了。 为什么对于一条边找最远顶点一定包含了最长直径?可以发现直径对应的两个顶点,一定存在一个包含了这两个点和这两个点中某个点的相邻点的一个三角形,那么也一定会更新到这条边。 来源: https://www.cnblogs.com/redegg/p/11982037.html

@codeforces - 932F@ Escape Through Leaf

混江龙づ霸主 提交于 2019-12-04 11:58:01
目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定一个 n 个点的树(标号1~n),以结点 1 为根。每个结点有两个点权 ai 与 bi。 你可以从一个点出发跳到它的子树中的某个结点去(不能跳到自己)。 从 x 跳到 y 所花费的代价为 ax * by,跳跃的总代价为每次跳跃的代价之和。 对于每个结点,计算从它出发跳到某一叶子结点的最小代价和。 Input 第一行包含一个整数 n (2 ≤ n ≤ 10^5),表示树中的结点数量。 第二行包含 n 个整数 a1, a2, ..., an (-10^5≤ai≤10^5)。 第三行包含 n 个整数 b1, b2, ..., bn (-10^5≤bi≤10^5)。 接下来 n-1 行每行包含两个整数 ui 和 vi (1≤ui, vi≤n),描述了树中的一条边。 Output 输出 n 个空格分开的整数,第 i 个描述了从第 i 个结点跳到叶子结点的最小代价和。 Examples Input 3 2 10 -1 7 -7 5 2 3 2 1 Output 10 50 0 Input 4 5 -10 5 7 -8 -80 -3 -10 2 1 2 4 1 3 Output -300 100 0 0 @solution@ 本题方法很多,可以转成 dfs

2019.11.13题解

ε祈祈猫儿з 提交于 2019-12-04 10:41:15
写在前面: 距离出发去秦皇岛还有1天的时间,突然昨天的一场考试暴露了很多问题, 例如T1二分条件写反挂掉80pts,T2数组开小挂了20pts,这么弱智的问题真的不应该出现, 何况现在距离CSP仅剩2天,考场上一定要认真检查低错,检查数组大小和内存限制,不要仅仅相信对拍 A. A 标签: 单调栈维护凸包 题解: 首先发现这个其实是一个假的二次函数,因为它没有常数项,所以可以提出一个x,维护两个凸包,在凸包上二分即可 也可以把询问离线做到O(n) B. B 标签: 期望 题解: 首先考虑把贡献分开统计,即: $ ans=a[1]+\sum\limits_{i=2}^{n}f[i] $ 其中f[i]表示在a[1]取完之后i取走的期望个数 现在的问题在于求f[i],可以枚举a[i]的个数为j 但是我们发现假如a[i]在j-1之前已经选完,概率会发生改变, 所以需要分类讨论: 1>a[1]先选完: $ val=\sum_{j=0}^{a[i]-1}\frac{C(j+a[1]-1,j)}{2^{(a[1]+j)}} $ 2>a[i]先选完: $ val=a[i]*(1-\sum_{j=0}^{a[i]-1}\frac{C(a[1]+k-1,k)}{2^{(a[1]+k)}}) $ 这里的概率无法直接得出,所以需要用1减去i选了小于a[i]个的概率 (对于n<=2可以Dp得出概率

poj3348(求凸包面积)

拜拜、爱过 提交于 2019-12-04 02:16:12
题目链接:https://vjudge.net/problem/POJ-3348 题意:转换题意后即是求凸包的面积。 思路:   套模板,求凸包面积即转换为多个三角形面积之和,用叉积求,然后除2,因为本题除50,所以最后除100。 AC code: #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; const int maxn=10005; const double PI=acos(-1.0); struct Point{ int x,y; Point():x(0),y(0){} Point(int x,int y):x(x),y(y){} }list[maxn]; int stack[maxn],top; //计算叉积p0p1×p0p2 int cross(Point p0,Point p1,Point p2){ return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y); } //计算p1p2的距离 double dis(Point p1,Point p2){ return sqrt((double)(p2.x-p1.x)*(p2.x-p1.x)+(p2.y-p1.y)*(p2.y-p1.y));