c++视觉处理---计算轮廓面积

news2025/9/20 17:30:53

矩的计算:cv::moments

cv::moments 是OpenCV中用于计算图像或轮廓的矩特征的函数。矩特征是一种用于描述图像或轮廓的几何特性的方法,包括中心矩、归一化中心矩、中心矩矩和归一化中心矩矩等。这些特征在形状分析、对象识别和物体测量等领域非常有用。

cv::moments 函数的基本用法如下:

cv::Moments cv::moments(const cv::Mat& array, bool binaryImage = false);
  • array: 输入的图像或轮廓。
  • binaryImage: 一个布尔值,指定输入是否为二进制图像。如果设置为 true,将仅考虑轮廓内的像素。

这个函数返回一个 cv::Moments 对象,其中包含了各种矩特征的值,可以通过 m 成员变量来访问这些值,如 m.m00m.m01m.m10 等。

轮廓面积:cv::contourArea

cv::contourArea 是OpenCV中用于计算轮廓的面积的函数。它接受一个轮廓作为输入,并返回该轮廓所围成区域的面积。这个函数非常有用,可以用于形状分析、对象测量和图像处理中的各种任务。

cv::contourArea 函数的基本用法如下:

double cv::contourArea(const std::vector<cv::Point>& contour, bool oriented = false);
  • contour: 输入的轮廓,通常是一个 std::vector<cv::Point>
  • oriented: 一个布尔值,指定是否考虑轮廓的方向。如果设置为 true,则会考虑轮廓的方向,如果为 false,则忽略方向。

这个函数返回一个 double 类型的值,表示轮廓所围成区域的面积。
cv::arcLength
cv::arcLength 是OpenCV中用于计算轮廓的弧长(周长)的函数。它接受一个轮廓作为输入,并返回轮廓的弧长。弧长是轮廓的所有线段(弧段)长度的总和。

轮廓长度:cv::arcLength 函数的基本用法如下:

double cv::arcLength(const std::vector<cv::Point>& contour, bool closed);
  • contour: 输入的轮廓,通常是一个 std::vector<cv::Point>
  • closed: 一个布尔值,指定轮廓是否封闭。如果设置为 true,则轮廓被认为是封闭的,如果为 false,则认为是开放的。

这个函数返回一个 double 类型的值,表示轮廓的弧长。

查找和绘制图像轮廓矩

#include <opencv2/opencv.hpp>
#include <iostream>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

using namespace std;
using namespace cv;
#include <iostream>
#include <fstream>
using namespace cv; //包含cv命名空间
#include <opencv2/core/core.hpp>
//-- - --【宏定义部分】---- ---- ----------
//描述: 定义一些辅助宏
#define WINDOW_NAME1 "【原始图】" //为窗口标题定义的宏
#define WINDOW_NAME2 "【图像轮廓】" //为窗口标题定义的宏
//--【全局变量声明部分】------------------------
// 描述: 全局变量的声明
Mat g_srcImage; Mat g_grayImage;
int g_nThresh = 100;
int g_nMaxThresh = 255;
RNG g_rng(12345);
Mat g_cannyMat_output;
vector<vector<Point> > g_vContours;
vector<Vec4i> g_vHierarchy;
// ---------------------【全局变量声明部分】-------------------
// 描述: 全局变量的声明
//
void on_ThreshChange(int, void*);
static void ShowHelpText();
//-【main()函数】------------------------
// 描述: 控制台应用程序的入口函数, 我们的程序从这里开始执行
int main(int argc, char** argv)
{
	//【0】改变 console字体颜色
	system("color 1E");
	//读入原图像,返回3通道图像数据
	g_srcImage = imread("1.jpg", 1);
	// 把原图像转化成灰度图像并进行平滑
	cvtColor(g_srcImage, g_grayImage, COLOR_BGR2GRAY);
	blur(g_grayImage, g_grayImage, Size(3, 3));
	// 创建新窗口
	namedWindow(WINDOW_NAME1, WINDOW_AUTOSIZE);
	imshow(WINDOW_NAME1, g_srcImage);
	//创建滚动条并进行初始化
	createTrackbar(" 阈值", WINDOW_NAME1, &g_nThresh, g_nMaxThresh, on_ThreshChange);
	on_ThreshChange(0, 0);
	waitKey(0);
	return(0);
}
//-----------------------【on_ThreshChange()函数】-------------------
// 描述: 回调函数
//--
void on_ThreshChange(int, void*)
{
	// 使用Canndy检测边缘
	Canny(g_grayImage, g_cannyMat_output, g_nThresh, g_nThresh * 2, 3);
	// 找到轮廓
	findContours(g_cannyMat_output, g_vContours, g_vHierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));
	// 计算矩
	vector<Moments> mu(g_vContours.size());
	for (unsigned int i = 0; i < g_vContours.size(); i++)
	{
		mu[i] = moments(g_vContours[i], false);
	}
	// 计算中心矩
	vector<Point2f> mc(g_vContours.size());
	for (unsigned int i = 0; i < g_vContours.size(); i++)
	{
		mc[i] = Point2f(static_cast<float>(mu[i].m10 / mu[i].m00), static_cast<float>(mu[i].m01 / mu[i].m00));
	}
	// 绘制轮廓
	Mat drawing = Mat::zeros(g_cannyMat_output.size(), CV_8UC3); for (unsigned int i = 0; i < g_vContours.size(); i++)
	{
		Scalar color = Scalar(g_rng.uniform(0, 255),
			g_rng.uniform(0, 255), g_rng.uniform(0, 255));//随机生成颜色值
		drawContours(drawing, g_vContours, i, color, 2, 8, g_vHierarchy, 0, Point());//绘制外层和内层轮廓
		circle(drawing, mc[i], 4, color, -1, 8, 0);;//绘制圆
	}
	// 显示到窗口中
	namedWindow(WINDOW_NAME2, WINDOW_AUTOSIZE);
	imshow(WINDOW_NAME2, drawing);
	// 通过 m00计算轮廓面积并且和OpenCV函数比较
	printf("\t 输出内容:面积和轮廓长度\n");
	for (unsigned int i = 0; i < g_vContours.size(); i++)
	{
		printf(" >通过m00计算出轮廓[%d]的面积:(M_00) = %,2f \n OpenCV函数计算出的面积=%.2f , 长度: %.2f \n\n", i, mu[i].m00,
			contourArea(g_vContours[i]), arcLength(g_vContours[i], true));
		Scalar color = Scalar(g_rng.uniform(0, 255),
			g_rng.uniform(0, 255), g_rng.uniform(0, 255));
		drawContours(drawing, g_vContours, i, color, 2, 8, g_vHierarchy, 0, Point());
		circle(drawing, mc[i], 4, color, -1, 8, 0);
	}
}

在这里插入图片描述

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

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

相关文章

携多项创新成果燃爆全场,移远通信亮相中国移动全球合作伙伴大会

10月11日&#xff0c; 2023中国移动全球合作伙伴大会盛大开幕&#xff0c;本次大会为期三天&#xff0c;以“算启新程 智享未来”为主题&#xff0c;为业界带来一场极具科技性、创新性、前瞻性的数智盛宴。 作为中国移动的重要合作伙伴&#xff0c;移远通信携5G、RedCap、卫星通…

数据结构:二叉排序树

什么是二叉排序树&#xff1f; 二叉排序树要么是空二叉树&#xff0c;要么具有如下特点&#xff1a; 二叉排序树中&#xff0c;如果其根结点有左子树&#xff0c;那么左子树上所有结点的值都小于根结点的值&#xff1b;二叉排序树中&#xff0c;如果其根结点有右子树&#xf…

Nlopt在matlab中的配置教程

step1&#xff1a;克隆代码并编译 编译的前提是已经安装好MinGW64 # 使用镜像加速 git clone https://gitclone.com/github.com/stevengj/nloptcd nlopt mkdir build cd build cmake -G"MinGW Makefiles" .. cmake --build .# 注意此处博主在mingw安装目录将mingw3…

golang 獲取 prometheus數據

使用github上的一個庫 1.安裝庫 go get github.com/prometheus/client_golang 2.導入 在import中導入&#xff0c;記得要在go.mod中更新一下 ------------------------------------------------------------------------------------ Address: "http://xx.xx.xx:9090…

ROS IMU 数据发布---rviz_imu_plugin的安装

ROS中发布IMU传感器消息 - 润新知 按照上述链接的方法执行 catkin_make install -DCMAKE_INSTALL_PREFIX/opt/ros/noetic 后报错 这个错误是因为在安装过程中&#xff0c;CMake无法将文件复制到目标路径。这可能是由于权限不足导致的。可以尝试使用以下命令更改目标文件夹的…

Mac删除不在程序坞的程序

现象描述&#xff1a;删除某个程序时&#xff08;通过‘程序’列表中将该应用移动到废纸篓里&#xff09;&#xff0c;该应用程序正在运行中&#xff0c;删除过程该程序未提示正在运行中&#xff0c;仅仅删除了图标&#xff08;在此吐槽下该程序的交互&#xff0c;产品没有考虑…

sql文件数据量太大,不打开sql文件,使用sqlplus往oracle数据库中写入大量数据

1、sqlplus 用户名/密码XE 2、往数据库中写入语句的sql文件路径 3、commit; (分号要写)如果不提交的话&#xff0c;数据库中新写入的数据不显示。

Allegro在测量时如何同时显示双单位

Allegro在测量时,默认只显示单个单位,根据PCB文件设计时所设定的单位决定,显示mil或mm。对于习惯看某个参数的设计者来说不方便。那如何同时显示mil和mm双单位呢? 点击Setup菜单 选择User Preferences...(用户参数设置) 跳出下面的对话框,选择Display→Element(元素)→…

【error】root - Exception during pool initialization

报错提示&#xff1a;root - Exception during pool initialization. 错误原因&#xff1a; 配置数据库出错 我的错误配置&#xff1a; spring.datasource.urljdbc:mysql://localhost:3306/springboot?serverTimezoneGMT spring.datasource.nameroot spring.datasource.pass…

Java实现基数排序

今天迷茫一天&#xff0c;没时间补博客&#xff0c;我就分享一个我认为最好的排序&#xff0c;思想也很容易解决很多关于字符串和数组问题&#xff0c;举个例子吧&#xff0c;求相邻元素的差值。 1.前言 基数排序是一种非比较排序算法&#xff0c;它将待排序的数字按照其每一位…

stm32学习笔记:EXIT中断

1、中断系统 中断系统是管理和执行中断的逻辑结构&#xff0c;外部中断是众多能产生中断的外设之一。 1.中断&#xff1a; 在主程序运行过程中&#xff0c;出现了特定的中断触发条件 (中断源&#xff0c;如对于外部中断来说可以是引脚发生了电平跳变&#xff0c;对于定时器来…

el-table组件的封装

前言&#xff1a;仔细看懂本篇博客&#xff0c;玩转element table 不成问题 &#xff0c;个人理解所谓封装&#xff0c;就是把经常都要公用的东西&#xff0c;拿出来&#xff0c;可以多次复用。公用方法&#xff0c;公用页面都可以封装。 其实封装也并不是有多难&#xff0c;思…

Linux和UNIX的关系及区别

UNIX 与 Linux 之间的关系是一个很有意思的话题。在目前主流的服务器端操作系统中&#xff0c;UNIX 诞生于 20 世纪 60 年代末&#xff0c;Windows 诞生于 20 世纪 80 年代中期&#xff0c;Linux 诞生于 20 世纪 90 年代初&#xff0c;可以说 UNIX 是操作系统中的"老大哥&…

瑞芯微 | 如何固定以太口地址为指定ip?

rxw的RK3568的evb1公板&#xff0c;有2个以太口&#xff0c; 默认UI界面只能配置eth0&#xff0c;无法配置eth1&#xff0c; 实际应用中&#xff0c;有时需要一旦有网线插入&#xff0c;就需要该地址设置为指定IP地址。 本文介绍2个最简单的方法实现固定IP。 一、通过修改i…

电脑提示kernel32.dll的错误提示窗口怎么办,解决kernel32.dll丢的办法

当你在使用电脑时&#xff0c;突然收到kernel32.dll丢失或找不到的错误提示窗口&#xff0c;这个时候先不要让自己的心态爆炸&#xff0c;解决的办法会有很多种&#xff0c;其实问题都不大&#xff0c;就能够很好的解决文件缺失的问题。接下来就把方法推进给大家。 一.解决kern…

Docker逃逸---CVE-2020-15257浅析

一、产生原因 在版本1.3.9之前和1.4.0~1.4.2的Containerd中&#xff0c;由于在网络模式为host的情况下&#xff0c;容器与宿主机共享一套Network namespace &#xff0c;此时containerd-shim API暴露给了用户&#xff0c;而且访问控制仅仅验证了连接进程的有效UID为0&#xff…

网站列表页加密:三次请求后返回内容多\r

一、抓包第一次请求 url aHR0cDovL2N5eHcuY24vQ29sdW1uLmFzcHg/Y29saWQ9MTA抓包&#xff0c;需要清理浏览器cookie&#xff0c;或者无痕模式打开网址&#xff0c;否则返回的包不全&#xff0c;依照下图中的第一个包进行requests请求 第一次请求后返回 <!DOCTYPE html>…

每年高考时间是几月几号 高考开始时间

高考是高中生最重要的一个阶段&#xff0c;甚至影响着很多学生的未来&#xff0c;相信大家都很关注高考的具体时间是什么时候&#xff0c;本次将详细给您介绍高考的具体开始时间以及结束时间。 每年高考的时间都是6月7日开始&#xff0c;一共持续三天时间左右&#xff0c;但是…

Java面试题-0919

集合篇 Java面试题-集合篇HashMap底层实现原理概述javaSE进阶-哈希表 为了满足hashmap集合的不重复存储&#xff0c;为什么要重写hashcode和equals方法&#xff1f; 首先理解一下hashmap的插入元素的前提&#xff1a; hashmap会根据元素的hashcode取模进行比较&#xff0c;当…

HDLbits: Lemmings3

Lemmings又多了一种状态&#xff1a;dig&#xff0c;我按照上一篇文章里大神的思路又多加了两种状态&#xff1a;LEFT_DIGGING与RIGHT_DIGGING&#xff0c;写出了如下的代码&#xff1a; module top_module(input clk,input areset, // Freshly brainwashed Lemmings walk …