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

OpenCV轮廓相关操作API (C++)

      在OpenCV中,轮廓(contours)是图像处理中的一个重要概念,通常用于形状分析、物体检测等任务。OpenCV提供了多种与轮廓相关的API,可以在C++中使用。

一.常用的与轮廓相关的操作及其对应的API函数

1.查找轮廓

findContours 函数用于在二值图像中查找轮廓。

void findContours(InputArray image, OutputArrayOfArrays contours, OutputArray hierarchy, int mode, int method, Point offset = Point() );

image: 输入的二值图像(通常为灰度图并经过阈值处理)。

contours: 检测到的轮廓,以std::vector<std::vector<Point>>形式存储。

hierarchy: 轮廓的拓扑信息,以std::vector<Vec4i>形式存储。

mode: 轮廓检索模式(如RETR_EXTERNAL, RETR_LIST, RETR_CCOMP, RETR_TREE)。

method: 轮廓逼近方法(如CHAIN_APPROX_SIMPLE, CHAIN_APPROX_TC89_L1, CHAIN_APPROX_TC89_KCOS, CHAIN_APPROX_NONE)。

offset: 可选的轮廓偏移量。

2.绘制轮廓

drawContours 函数用于在图像上绘制轮廓。

void drawContours(InputOutputArray image, InputArrayOfArrays contours, int contourIdx, const Scalar& color, int thickness = 1, int lineType = LINE_8, InputArray hierarchy = noArray(), int maxLevel = INT_MAX, Point offset = Point() );

image: 输出的图像。

contours: 轮廓,以std::vector<std::vector<Point>>形式存储。

contourIdx: 指定要绘制的轮廓索引,-1表示绘制所有轮廓。

color: 轮廓的颜色。

thickness: 轮廓线的厚度。负值表示填充轮廓。

lineType: 轮廓线的类型。

hierarchy: 可选的轮廓拓扑信息,用于指定绘制的轮廓层次。

maxLevel: 绘制轮廓的最大层次深度。

offset: 可选的轮廓偏移量。

3.轮廓近似

approxPolyDP 函数用于对轮廓进行多边形逼近。

void approxPolyDP(InputArray curve, OutputArray approxCurve, double epsilon, bool closed);

curve: 输入的轮廓。

approxCurve: 输出的逼近多边形。

epsilon: 逼近精度,表示轮廓到逼近多边形的最大距离。

closed: 指示逼近多边形是否闭合。

4.轮廓面积和周长

contourArea 和 arcLength 函数分别用于计算轮廓的面积和周长。

double contourArea(InputArray contour, bool oriented = false);

double arcLength(InputArray curve, bool closed);

contour: 输入的轮廓。

oriented: 当为true时,返回有符号面积(正值表示逆时针方向,负值表示顺时针方向)。

curve: 输入的轮廓或曲线。

closed: 指示曲线是否闭合。

5.轮廓矩

moments 函数用于计算轮廓的矩。

Moments moments(InputArray array, bool binaryImage = false);

array: 输入的轮廓或图像。

binaryImage: 当为true时,假定输入图像为二值图像。

Moments结构体包含各种矩,如m00, m10, m01, m20, m11, m02等,可以用来计算轮廓的几何属性,具体有:

a.空间矩(Spatial Moments)

空间矩是图像像素位置与其灰度值的加权和,它们描述了图像的整体分布。在 cv::Moments 结构体中,空间矩包括:

m00:零阶矩,表示图像的总亮度(或质量)。

m10:一阶矩关于 x 轴的分量,描述了图像在 x 方向上的亮度分布。

m01:一阶矩关于 y 轴的分量,描述了图像在 y 方向上的亮度分布。

m20、m11、m02:二阶矩,分别描述了图像在 x2 方向上的亮度分布。

m30、m21、m12、m03:三阶矩,进一步描述了图像的高阶亮度分布特性。

b.中心矩(Central Moments)

中心矩是相对于图像重心的矩,它们描述了图像形状相对于重心的分布。在 cv::Moments 结构体中,中心矩包括:

mu20、mu11、mu02:二阶中心矩,分别描述了图像形状在 x2 方向上的相对于重心的分布。

mu30、mu21、mu12、mu03:三阶中心矩,进一步描述了图像形状的高阶相对于重心的分布特性。

c.中心归一化矩(Normalized Central Moments)

中心归一化矩是通过将中心矩除以零阶中心矩的适当幂次来得到的,它们具有尺度不变性。在 cv::Moments 结构体中,虽然直接没有列出归一化中心矩的成员变量,

但可以通过中心矩和零阶中心矩(实际上在 cv::Moments 中是 m00,但注意 m00 不是中心矩,这里只是为了说明归一化的概念)来计算得到。

归一化中心矩的一般形式为:

nu_pq = mu_pq / (m00^((p+q)/2 + 1))

其中,nu_pq 表示 p+q 阶归一化中心矩,mu_pq 表示 p+q 阶中心矩,m00 表示零阶矩。

6.获取轮廓的凸包

通过cv::convexHull()获取轮廓的凸包。

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

points即输入的二维点集;

hull为输出的二维点集;

clockwise决定出来的轮廓是否为顺时针方向,为true时为顺时针方向;

returnPoints标志,为true时,hull将返回点集,此时为std::vector<cv::Point>类型,为false时,hull将返回返回对应于外壳点的轮廓点的索引。

二.代码示例

1.打开一个图片

#include <opencv2/opencv.hpp>

#include <iostream>

int main() {

    // 读取图像

    cv::Mat src = cv::imread("path_to_image.jpg", cv::IMREAD_GRAYSCALE);

    if (src.empty()) {

        std::cerr << "Could not open or find the image!" << std::endl;

        return -1;

    }

    // 阈值处理

    cv::Mat binary;

    cv::threshold(src, binary, 127, 255, cv::THRESH_BINARY);

    // 查找轮廓

    std::vector<std::vector<cv::Point>> contours;

    std::vector<cv::Vec4i> hierarchy;

    cv::findContours(binary, contours, hierarchy, cv::RETR_TREE, cv::CHAIN_APPROX_SIMPLE);

    // 绘制轮廓

    cv::Mat result;

    cv::cvtColor(src, result, cv::COLOR_GRAY2BGR);

    for (size_t i = 0; i < contours.size(); i++) {

        cv::drawContours(result, contours, (int)i, cv::Scalar(0, 255, 0), 2, cv::LINE_8, hierarchy, 0);

    }

    // 显示结果

    cv::imshow("Contours", result);

    cv::waitKey(0);

    return 0;

}

2.生成一个图像

#include <iostream>

#include <opencv2/opencv.hpp>

int main() {

    // 创建一个空白的图像

    cv::Mat image = cv::Mat::zeros(300, 300, CV_8UC1); // 单通道8位图像

    // 在图像中间画一个白色的圆形作为轮廓

    cv::circle(image, cv::Point(150, 150), 50, cv::Scalar(255), -1);

    // 查找图像中的轮廓

    std::vector<std::vector<cv::Point>> contours;

    cv::findContours(image, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);

    // 计算轮廓的矩

    cv::Moments moments = cv::moments(contours[0]);

    // 从矩中计算质心

    double cx = moments.m10 / moments.m00;

    double cy = moments.m01 / moments.m00;

    // 计算面积

    double area = moments.m00;

    // 在图像上标记质心

    cv::circle(image, cv::Point(static_cast<int>(cx), static_cast<int>(cy)), 5, cv::Scalar(128), -1);

    // 输出质心坐标和面积

    std::cout << "Centroid at (" << cx << ", " << cy << ")" << std::endl;

    std::cout << "Area: " << area << std::endl;

    // 显示图像

    cv::imshow("Contour with Centroid", image);

    cv::waitKey(0);

    return 0;

}

相关文章:

OpenCV轮廓相关操作API (C++)

在OpenCV中&#xff0c;轮廓&#xff08;contours&#xff09;是图像处理中的一个重要概念&#xff0c;通常用于形状分析、物体检测等任务。OpenCV提供了多种与轮廓相关的API&#xff0c;可以在C中使用。 一.常用的与轮廓相关的操作及其对应的API函数 1.查找轮廓 findContou…...

[开源]自动化定位建图系统

系统状态机&#xff1a; 效果展示&#xff1a; 1、 机器人建图定位系统-基础重定位&#xff0c;定位功能演示 2、 机器人建图定位系统-增量地图构建&#xff0c;手动回环检测演示 3、敬请期待… 开源链接&#xff1a; 1、多传感器融合里程计 https://gitee.com/li-wenhao-lw…...

linux ansible部署

ansible部署完后&#xff0c;执行报错 # ansible one -i hosts -m ping dataos193 | FAILED! > {"msg": "Using a SSH password instead of a key is not possible because Host Key checking is enabled and sshpass does not support this. Please add …...

《Rust权威指南》学习笔记(二)

枚举enum 1.枚举的定义和使用如下图所示&#xff1a; 定义时还可以给枚举的成员指定数据类型&#xff0c;例如&#xff1a;enum IpAddr{V4(u8, u8, u8, u8),V6(String),}。枚举的变体都位于标识符的命名空间下&#xff0c;使用::进行分隔。 2.一个特殊的枚举Option&#xff0…...

Redis内存碎片

什么是内存碎片? 你可以将内存碎片简单地理解为那些不可用的空闲内存。 举个例子&#xff1a;操作系统为你分配了 32 字节的连续内存空间&#xff0c;而你存储数据实际只需要使用 24 字节内存空间&#xff0c;那这多余出来的 8 字节内存空间如果后续没办法再被分配存储其他数…...

Express 加 sqlite3 写一个简单博客

例图&#xff1a; 搭建 命令&#xff1a; 前提已装好node.js 开始创建项目结构 npm init -y package.json:{"name": "ex01","version": "1.0.0","main": "index.js","scripts": {"test": &q…...

正则表达式进阶学习(一):环视、捕获分组与后向引用

一、环视&#xff08;零宽断言&#xff09; 理论部分 环视&#xff08;零宽断言&#xff09;是一种用于匹配位置而非字符的正则表达式技术。它的核心特点是&#xff1a;不消耗字符&#xff0c;只检查某个位置前后是否符合特定的条件。可以理解为&#xff0c;环视是在匹配前“…...

《Vue3 七》插槽 Slot

插槽可以让组件的使用者来决定组件中的某一块区域到底存放什么元素和内容。 使用插槽&#xff1a; 插槽的使用过程其实就是抽取共性、预留不同。将共同的元素、内容依然留在组件内进行封装&#xff1b;将不同的元素使用 slot 作为占位&#xff0c;让外部决定到底显示什么样的…...

【C++数据结构——线性表】顺序表的基本运算(头歌实践教学平台习题)【合集】

目录&#x1f60b; 任务描述 相关知识 一、线性表的基本概念 二、初始化线性表 三、销毁线性表 四、判定是否为空表 五、求线性表的长度 六、输出线性表 七、求线性表中某个数据元素值 八、按元素值查找 九、插入数据元素 十、删除数据元素 测试说明 通关代码 测…...

Linux C/C++编程-获得套接字地址、主机名称和主机信息

【图书推荐】《Linux C与C一线开发实践&#xff08;第2版&#xff09;》_linux c与c一线开发实践pdf-CSDN博客《Linux C与C一线开发实践&#xff08;第2版&#xff09;&#xff08;Linux技术丛书&#xff09;》(朱文伟&#xff0c;李建英)【摘要 书评 试读】- 京东图书 (jd.com…...

USB kbtab linux 驱动代码

#include <linux/kernel.h> #include <linux/slab.h> #include <linux/module.h> #include <linux/usb/input.h> #include <asm/unaligned.h> /* Pressure-threshold modules param code from */MODULE_AUTHOR(“xxx”); MODULE_DESCRIPTION(“…...

力扣 跳跃游戏

每次更新目标位置时&#xff0c;实际上是在做一个局部的最优选择&#xff0c;选择跳跃能够到达当前目标位置的最远位置。因为每次更新目标位置时&#xff0c;都是基于当前能跳跃到的最远位置&#xff0c;因此最终的结果是全局最优的。 题目 从前往后遍历&#xff0c;更新可以到…...

使用npm 插件[mmdc]将.mmd时序图转换为图片

使用npm 插件[mmdc]将.mmd时序图转换为图片 1. 安装 mmdc2. 转换为图片 可以使用 mmdc &#xff08;Mermaid CLI&#xff09;这个工具来将 .mmd 时序图&#xff08;Mermaid语法描述的时序图&#xff09;转换为图片&#xff0c;以下是使用步骤&#xff1a; 1. 安装 mmdc 确保…...

ffmpeg 常用命令

更详细请参考ffmpeg手册&#xff0c;下载ffmpegrelease版后在doc中就有&#xff0c;主页面。video filter 参考ffmpeg-filters.html -version -formats -demuxers -protocols -muxers -filters -devices —pix_fmts -codecs -sample_fmts -decoders -layouts -encoders -colors…...

从入门到实战:C 语言 strlen 函数通关指南

文章目录 一、strlen函数简介1. 函数构成2. 参数说明3. 使用示例 二、模拟实现strlen函数&#xff08;从新手角度逐步升级改进&#xff09;1. 基础版本&#xff08;利用循环计数&#xff09;2. 改进版本&#xff08;利用指针相减&#xff09;3. 递归版本&#xff08;利用递归思…...

npm install --global windows-build-tools --save 失败

注意以下点 为啥下载windows-build-tools&#xff0c;是因为node-sass4.14.1 一直下载不成功&#xff0c;提示python2 没有安装&#xff0c;最终要安装这个&#xff0c;但是安装这个又失败&#xff0c;主要有以下几个要注意的 1、node 版本 14.21.3 不能太高 2、管理员运行 …...

十种基础排序算法(C语言实现,带源码)(有具体排序例子,适合学习理解)

学习了十种常见的排序方法&#xff0c;此文章针对所学的排序方法进行整理&#xff08;通过C语言完成排序&#xff09;。 参考内容&#xff1a; https://blog.csdn.net/mwj327720862/article/details/80498455 https://www.runoob.com/w3cnote/ten-sorting-algorithm.html 1. 冒…...

基于fMRI数据计算脑脊液(CSF)与全脑BOLD信号的时间耦合分析

一、前言 笔者之前的文章《基于Dpabi和spm12的脑脊液(csf)分割和提取笔记》,介绍了如何从普通的fMRI数据中提取CSF信号。首先是基础的预处理,包括时间层校正、头动校正,再加上0.01-0.1Hz的带通滤波。接着用SPM12分割出CSF区域,设置一个比较严格的0.9阈值,确保提取的真是…...

实现websocket心跳检测,断线重连机制

WebSocket基础 WebSocket概念 WebSocket是一种革命性的 全双工通信协议 &#xff0c;构建在TCP之上&#xff0c;旨在简化客户端与服务器之间的数据交换过程。通过单次握手建立持久连接&#xff0c;WebSocket实现了真正的双向实时通信&#xff0c;显著提高了交互效率。这一特性…...

ComfyUI节点安装笔记

AI高速发展&#xff0c;版本更新相当快&#xff08;11月25日才安装的版本v.0.3.4&#xff0c;27日版本就已经更新到v.0.3.5了&#xff09;&#xff0c;在遇到问题&#xff0c;找到问题原因所在的过程中&#xff0c;ComfyUI版本、python版本、节点对环境版本的依赖&#xff0c;本…...

Python|GIF 解析与构建(5):手搓截屏和帧率控制

目录 Python&#xff5c;GIF 解析与构建&#xff08;5&#xff09;&#xff1a;手搓截屏和帧率控制 一、引言 二、技术实现&#xff1a;手搓截屏模块 2.1 核心原理 2.2 代码解析&#xff1a;ScreenshotData类 2.2.1 截图函数&#xff1a;capture_screen 三、技术实现&…...

深入剖析AI大模型:大模型时代的 Prompt 工程全解析

今天聊的内容&#xff0c;我认为是AI开发里面非常重要的内容。它在AI开发里无处不在&#xff0c;当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗"&#xff0c;或者让翻译模型 "将这段合同翻译成商务日语" 时&#xff0c;输入的这句话就是 Prompt。…...

1688商品列表API与其他数据源的对接思路

将1688商品列表API与其他数据源对接时&#xff0c;需结合业务场景设计数据流转链路&#xff0c;重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点&#xff1a; 一、核心对接场景与目标 商品数据同步 场景&#xff1a;将1688商品信息…...

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)

骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术&#xff0c;它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton)&#xff1a;由层级结构的骨头组成&#xff0c;类似于人体骨骼蒙皮 (Mesh Skinning)&#xff1a;将模型网格顶点绑定到骨骼上&#xff0c;使骨骼移动…...

Java 二维码

Java 二维码 **技术&#xff1a;**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...

Web后端基础(基础知识)

BS架构&#xff1a;Browser/Server&#xff0c;浏览器/服务器架构模式。客户端只需要浏览器&#xff0c;应用程序的逻辑和数据都存储在服务端。 优点&#xff1a;维护方便缺点&#xff1a;体验一般 CS架构&#xff1a;Client/Server&#xff0c;客户端/服务器架构模式。需要单独…...

离线语音识别方案分析

随着人工智能技术的不断发展&#xff0c;语音识别技术也得到了广泛的应用&#xff0c;从智能家居到车载系统&#xff0c;语音识别正在改变我们与设备的交互方式。尤其是离线语音识别&#xff0c;由于其在没有网络连接的情况下仍然能提供稳定、准确的语音处理能力&#xff0c;广…...

Mac flutter环境搭建

一、下载flutter sdk 制作 Android 应用 | Flutter 中文文档 - Flutter 中文开发者网站 - Flutter 1、查看mac电脑处理器选择sdk 2、解压 unzip ~/Downloads/flutter_macos_arm64_3.32.2-stable.zip \ -d ~/development/ 3、添加环境变量 命令行打开配置环境变量文件 ope…...

数据挖掘是什么?数据挖掘技术有哪些?

目录 一、数据挖掘是什么 二、常见的数据挖掘技术 1. 关联规则挖掘 2. 分类算法 3. 聚类分析 4. 回归分析 三、数据挖掘的应用领域 1. 商业领域 2. 医疗领域 3. 金融领域 4. 其他领域 四、数据挖掘面临的挑战和未来趋势 1. 面临的挑战 2. 未来趋势 五、总结 数据…...

使用homeassistant 插件将tasmota 接入到米家

我写一个一个 将本地tasmoat的的设备同通过ha集成到小爱同学的功能&#xff0c;利用了巴法接入小爱的功能&#xff0c;将本地mqtt转发给巴法以实现小爱控制的功能&#xff0c;前提条件。1需要tasmota 设备&#xff0c; 2.在本地搭建了mqtt服务可&#xff0c; 3.搭建了ha 4.在h…...