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

news2025/1/8 5:56:02

      在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;

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2273035.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

安装vue脚手架出现的一系列问题

安装vue脚手架出现的一系列问题 前言使用 npm 安装 vue/cli2.权限问题及解决方法一&#xff1a;可以使用管理员权限进行安装。方法二&#xff1a;更改npm全局安装路径 前言 由于已有较长时间未进行 vue 项目开发&#xff0c;今日着手准备开发一个新的 vue 项目时&#xff0c;在…

前端JS中var、let、const之间的区别

&#x1f3ac; 江城开朗的豌豆&#xff1a;个人主页 &#x1f525; 个人专栏 :《 VUE 》 《 javaScript 》 &#x1f4dd; 个人网站 :《 江城开朗的豌豆&#x1fadb; 》 ⛺️ 生活的理想&#xff0c;就是为了理想的生活 ! 目录 一、var 二、let 三、const 四、区别 变量…

STM32+ADC+DMA快速循环转换

测试平台&#xff1a;STM32F405RGT6 uint32_t AD_Buf[100]{0}; HAL_ADC_Start_DMA(&hadc2,(uint32_t *)AD_Buf,100); while(1) {printf("AD_Buf:%d\n",AD_Buf[0]); }

Unity中 Xlua使用整理(一)

1.安装: 从GitHub上下载Xlua源码 Tencent/xLua: xLua is a lua programming solution for C# ( Unity, .Net, Mono) , it supports android, ios, windows, linux, osx, etc. (github.com) 下载Xlua压缩包&#xff0c;并解压将Aseet文件夹中的Xlua和Plugins文件夹复制到Unit…

js高阶-函数闭包this

闭包 一等公民 在js中函数是一等公民 函数使用很灵活,可以作为参数,也可以作为返回值 高阶函数 函数接收函数作为参数或者返回函数,则该函数称为高阶函数 eg: array.filter/reduce/find/findIndex/map.forEach 函数与方法 独立使用的 Function 做为对象的属性 method Wh…

Ubuntu 24.04.1 LTS nginx配置maccms

之前在Ubuntu 20.04中搭建过&#xff0c;现在换了新操作系统&#xff0c;顺便整理一下。 相关文章 《Ubuntu 20.04.1 LTS搭建nginx php7.4运行环境》 https://blog.csdn.net/lxyoucan/article/details/144850572《linux nginx maccms管理后台无法进入页面不存在和验证码不显…

【Ubuntu】想知道怎么通过命令行查看笔记本电池健康程度吗?

你想在 Ubuntu 中通过命令行检查电池健康状态&#xff0c;而不需要额外安装任何工具吗&#xff1f; 其实&#xff0c;你可以做到。 大多数在笔记本电脑上使用 Ubuntu 的用户都会通过顶部栏来监控电池电量&#xff08;我总是在顶部栏启用电池百分比显示&#xff0c;以便一目了…

ue5动画重定向,一键重定向。ue4小白人替换成ue5

这就是我们下载的 初学者动画内容包 点击设置选中列 绿色的是动画 黄色的关卡 蓝色是蓝图 ctrla 全选 ctrl鼠标左键 选中所有动画 重定向动画资产 不要选错&#xff0c;只要绿色 选择目标网格体 选择所有的绿色 动画 导出动画 添加前缀ycn 导出 一定要提前新建好存放的…

05容器篇(D2_集合 - D6_容器源码分析篇 - D1_ArrayList)

目录 本章目标 一、基本介绍 二、原理分析 1. 数据结构源码分析 2. 默认容量&最大容量 为什么最大容量要-8呢&#xff1f; 3. 为什么ArrayList查询快&#xff0c;增删慢&#xff1f; 4. 初始化容量 1> 创建ArrayList对象分析&#xff1a;无参数 2> 创建Arra…

TVbox 手机、智能电视节目一网打尽

文章目录 一、简要介绍二、下载地址 一、简要介绍 TVbox是目前最火爆的多端、多源的电视影音工具&#xff0c;是一款开源的自定义添加站源的影音工具。TVBox&#xff0c;支持电视频道直播。一款TV端影视工具&#xff0c;软件本身不具有任何影视资源&#xff0c;但可以通过配置…

IP Anycast 与 CDN

基于名字寻址而不是基于地址寻址早就不是什么新鲜事&#xff0c;我们日常生活中的寻址基本都是找名字&#xff0c;比如找厕所&#xff0c;找连锁店&#xff0c;我们倾向于去具有同样称呼的最近那家。IP 网络中的这种机制叫 Anycast。 是不是一下子就不需要过多解释了。所有具有…

【0x006D】HCI_Write_LE_Host_Support命令详解

目录 一、命令概述 二、命令格式及参数说明 2.1. HCI_Write_LE_Host_Support命令格式 2.2. LE_Supported_Host 三、生成事件及参数 3.1. HCI_Command_Complete 事件 3.2. Status 四、命令执行流程 4.1. 命令发起阶段&#xff08;主机端&#xff09; 4.2. 命令处理阶段…

Harmony OS开发之ArkUI框架速成九弹性布局和层叠布局

> 程序员Feri一名12年的程序员,做过开发带过团队创过业,擅长Java相关开发、鸿蒙开发、人工智能等,专注于程序员搞钱那点儿事,希望在搞钱的路上有你相伴&#xff01;君志所向,一往无前&#xff01; --- 1.弹性布局&#xff08;Flex&#xff09; 弹性布局分为单行布局和多行…

HarmonyOS-面试资料

1. HarmonyOS-面试资料 1.1. HarmonyOS 优点、特点 1.1.1. 优点 &#xff08;1&#xff09;在国家方面&#xff0c;是国产的系统&#xff0c;受国家支持不会有限制的情况。   &#xff08;2&#xff09;设备互连18N(1:手机 8&#xff1a;平板、PC、vr设备、可穿戴设备、智慧…

macos安装java8

下载 dmg方式安装 安装 双击pkg运行 输入java -version验证 配置环境变量 cd ~ ls -a输入 ls -a后查看是否已经存在.bash_profile文件&#xff0c;如果已经存在就不需要创建&#xff0c;如果不存在&#xff0c;继续执行下方命令创建文件 touch .bash_profile /usr/l…

记一次k8s下容器启动失败,容器无日志问题排查

问题 背景 本地开发时&#xff0c;某应用增加logback-spring.xml配置文件&#xff0c;加入必要的依赖&#xff1a; <dependency><groupId>net.logstash.logback</groupId><artifactId>logstash-logback-encoder</artifactId><version>8…

KAFKA入门:原理架构解析

文章目录 一、认识kafka二、架构介绍2.1 工作流程2.2 Kafka可靠性保证2.3 Kafka存储 一、认识kafka Kafka到底是个啥&#xff1f;用来干嘛的&#xff1f; 官方定义如下&#xff1a; Kafka is used for building real-time data pipelines and streaming apps. It is horizont…

Redis - 6 ( 9000 字 Redis 入门级教程 )

一&#xff1a;Redis Java 集成到 Spring Boot 1.1 使用 Spring Boot 连接 Redis 单机 在创建项目时&#xff0c;勾选 NoSQL 分类下的 Spring Data Redis&#xff0c;同时勾选 Web 分类下的 Spring Web。这样既能方便集成 Redis&#xff0c;又能通过 Web 接口进行后续测试&am…

笔记本如何录屏幕视频和声音?快速入门的两种方法

“你好&#xff01;我想要制作线上教学课程&#xff0c;包括录制课程内容和我的声音&#xff0c;然后分享给我的学生&#xff0c;以便他们课后复习&#xff0c;但我不知道笔记本如何录屏幕视频和声音&#xff1f;有没有好的工具推荐&#xff1f;” 随着远程办公、在线学习和直播…

Flutter中的网络请求图片存储为缓存,与定制删除本地缓存

Flutter中的网络请求图片存储为缓存&#xff0c;与定制删除本地缓存 1&#xff1a;封装请求图片函数 2&#xff1a;访问的图片都会转为本地缓存&#xff0c;当相同的请求url&#xff0c;会在本地调用图片 3&#xff1a;本地缓存管理【windows与andriod已经测试】【有页面】【有…