当前位置: 首页 > article >正文

OpenCV结构分析与形状描述符(8)点集凸包计算函数convexHull()的使用

  • 操作系统:ubuntu22.04
  • OpenCV版本:OpenCV4.9
  • IDE:Visual Studio Code
  • 编程语言:C++11

算法描述

查找一个点集的凸包。
函数 cv::convexHull 使用斯克拉斯基算法(Sklansky’s algorithm)来查找一个二维点集的凸包,在当前实现中该算法的时间复杂度为 O(N logN)。

函数 cv::convexHull 是 OpenCV 库中的一个功能,用于计算一组二维点的凸包。凸包可以理解为是最小的凸多边形,它能够包含给定的所有点。这个函数利用了Sklansky算法或其他高效算法来完成计算,其时间复杂度在当前实现中为 O(N logN),其中 N 是输入点的数量。

函数原型


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

参数

  • 参数points Input 2D point set, stored in std::vector or Mat.
  • 参数hull 输出的凸包。它可以是一个整数向量的索引或者是点的向量。在第一种情况下,凸包元素是以0为基础的索引,在原始数组中的凸包点(因为凸包点集是原始点集中的一子集)。在第二种情况下,凸包元素本身就是凸包的点。
  • 参数clockwise 方向标志。如果为真,则输出的凸包是按照顺时针方向排列的。否则,它是按照逆时针方向排列的。假设的坐标系统X轴指向右侧,Y轴向上。
  • 参数returnPoints 操作标志。在矩阵的情况下,当此标志为真时,函数返回凸包的点。否则,它返回凸包点的索引。当输出数组是 std::vector 时,此标志被忽略,输出取决于向量的类型:std::vector 表示 returnPoints=false,std::vector 表示 returnPoints=true。

代码示例

include <iostream>
#include <opencv2/opencv.hpp>
#include <vector>

using namespace std;
using namespace cv;

int main() {
    // 创建一个随机点集
    vector<Point2f> points;
    for (int i = 0; i < 10; ++i) {
        points.push_back(Point2f(rand() % 500, rand() % 500));
    }

    // 计算凸包
    vector<vector<Point2f>> hulls;
    vector<int> hullIndices;
    convexHull(points, hullIndices, false);

    // 将索引转换为实际的点
    for (auto& index : hullIndices) {
        hulls.push_back(vector<Point2f>{points[index]});
    }

    // 创建一个空白图像来显示点和凸包
    Mat img = Mat::zeros(512, 512, CV_8UC3);

    // 绘制原始点
    for (const auto& pt : points) {
        circle(img, pt, 3, Scalar(0, 0, 255), -1); // 红色圆圈表示原始点
    }

    imshow("circle image", img);

    // 绘制凸包
    int numPoints = hulls.size();
    for (int i = 0; i < numPoints; ++i) {
        line(img, hulls[i][0], hulls[(i + 1) % numPoints][0], Scalar(0, 255, 0), 2); // 绿色线条表示凸包
    }

    // 显示结果
    imshow("Convex Hull", img);
    waitKey(0);

    return 0;
}

运行结果

在这里插入图片描述


http://www.kler.cn/a/294239.html

相关文章:

  • C语言打印时间精确到毫秒
  • 前缀和技巧解析
  • PNG图片批量压缩exe工具+功能纯净+不改变原始尺寸
  • 专题十八_动态规划_斐波那契数列模型_路径问题_算法专题详细总结
  • 成都睿明智科技有限公司解锁抖音电商新玩法
  • 代码随想录第二十一天| 669. 修剪二叉搜索树 108.将有序数组转换为二叉搜索树 538.把二叉搜索树转换为累加树
  • java设计模式day02--(创建型模式:工厂模式、原型模式、建造者模式)
  • 【python】python指南(三):使用正则表达式re提取文本中的http链接
  • 【Netty】netty中都是用了哪些设计模式
  • BIO、NIO、AIO 有什么区别?
  • 进程间通信-进程池
  • 《Cloud Native Data Center Networking》(云原生数据中心网络设计)读书笔记 -- 09部署OSPF
  • 前向代理和反向代理的区别是什么?
  • JWT详解:一种轻量级的身份验证和授权机制
  • 2024年AI芯片峰会——边缘端侧AI芯片专场
  • 力扣172.阶乘后的0
  • elasticsearch文档Delete By Query API(一)
  • 蚂蚁数科独立后首度公布业务进展和战略布局
  • 已经30岁了,想转行从头开始现实吗?什么样的工作算好工作?
  • 网页时装购物系统:Spring Boot框架的高效实现
  • 《Foundation 滑块》
  • Codeforces Round 971 (Div. 4) A~G2
  • 【网络安全】CSRF漏洞—CSRF基础漏洞防御
  • linux系统中,计算两个文件的相对路径
  • class 6: vue.js 3 组件化开发
  • SpringBoot学习(4)(yml配置信息书写和获取)(SpringEL表达式语言)