17- OpenCV:图像矩(Image Moments)和点多边形测试

目录

一、图像矩

1、矩的概念介绍

2、相关的API

3、代码演示

二、点多边形测试

1、概念介绍-点多边形测试

2、cv::pointPolygonTest

3、代码演示


一、图像矩

引言

在数字图像处理、计算机视觉与相关领域中,图像矩(Image moments)是指图像的某些特定像素灰度的加权平均值(矩),或者是图像具有类似功能或意义的属性。

图像矩通常用来描述 分割 后的图像对象。可以通过图像的矩来获得图像的部分性质,包括面积(或总体亮度),以及有关几何中心方向的信息 。

1、矩的概念介绍

图像矩是用于描述图像形状特征的一种数学工具。它们可以用于计算图像的几何特征,如质心、面积、方向等。

在图像处理中,常用的图像矩包括原始矩和中心矩。通过计算图像的原始矩和中心矩,可以得到一些常用的图像特征,如图像的面积、质心位置、方向、轮廓等。这些特征对于图像识别、形状匹配和目标跟踪等应用非常有用。

(1)原始矩:描述了图像中像素的位置和强度信息。

(2)几何矩  :

P代表像素,* 位置,算出所有的和

(3)中心距  :中心矩是以质心为中心的矩,相比原始矩,只要添加一个平移即可。中心矩是相对于图像质心的矩,可以用来描述图像的旋转和缩放特征。

周边的点到中心的距离

(4)中心归一化距

(5)图像中心Center(x0,y0)

2、相关的API

(1)计算生成数据

(2)cv::moments( )

cv::moments(

InputArray  array,//输入数据

bool   binaryImage=false // 是否为二值图像

)

(3)cv::contourArea()

contourArea(

InputArray  contour,//输入轮廓数据

bool   oriented// 默认false、返回绝对值

)

(4)cv::arcLength()

arcLength(

InputArray  curve,//输入曲线数据

bool   closed// 是否是封闭曲线

)

3、代码演示

主要的流程步骤:

(1)提取图像边缘

(2)发现轮廓

(3)计算每个轮廓对象的矩

(4)计算每个对象的中心、弧长、面积

#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>using namespace std;
using namespace cv;Mat src, gray_src;
int threshold_value = 80;
int threshold_max = 255;
const char* output_win = "image moents demo";
RNG rng(12345);
void Demo_Moments(int, void*);
int main(int argc, char** argv) {src = imread("D:/vcprojects/images/circle.png");if (!src.data) {printf("could not load image...\n");return -1;}cvtColor(src, gray_src, CV_BGR2GRAY);GaussianBlur(gray_src, gray_src, Size(3, 3), 0, 0);char input_win[] = "input image";namedWindow(input_win, CV_WINDOW_AUTOSIZE);namedWindow(output_win, CV_WINDOW_AUTOSIZE);imshow(input_win, src);createTrackbar("Threshold Value : ", output_win, &threshold_value, threshold_max, Demo_Moments);Demo_Moments(0, 0);waitKey(0);return 0;
}void Demo_Moments(int, void*) {Mat canny_output;vector<vector<Point>> contours;vector<Vec4i> hierachy;Canny(gray_src, canny_output, threshold_value, threshold_value * 2, 3, false);findContours(canny_output, contours, hierachy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));vector<Moments> contours_moments(contours.size());vector<Point2f> ccs(contours.size());for (size_t i = 0; i < contours.size(); i++) {contours_moments[i] = moments(contours[i]);ccs[i] = Point(static_cast<float>(contours_moments[i].m10 / contours_moments[i].m00), static_cast<float>(contours_moments[i].m01 / contours_moments[i].m00));}Mat drawImg;// = Mat::zeros(src.size(), CV_8UC3);src.copyTo(drawImg);for (size_t i = 0; i < contours.size(); i++) {if (contours[i].size() < 100) {continue;}Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));printf("center point x : %.2f y : %.2f\n", ccs[i].x, ccs[i].y);printf("contours %d area : %.2f   arc length : %.2f\n", i, contourArea(contours[i]), arcLength(contours[i], true));drawContours(drawImg, contours, i, color, 2, 8, hierachy, 0, Point(0, 0));circle(drawImg, ccs[i], 2, color,2, 8);}imshow(output_win, drawImg);return;
}

效果展示:

二、点多边形测试

1、概念介绍-点多边形测试

测试一个点是否在给定的多边形内部,边缘或者外部的一个方法。

根据左边的图进行点多边形测试之后,知道每个点在图像内部、边缘或者是在外部;

并计算出每个点到中间的距离,根据这些距离可以生出右边的图。

            

2、cv::pointPolygonTest

double cv::pointPolygonTest(

InputArray  contour,// 输入的轮廓

Point2f  pt, // 测试点

bool  measureDist // 是否返回距离值,true返回实际距离,

                                如果是false,1表示在内面,0表示在边界上,-1表示在外部

)

返回数据是double类型。

3、代码演示

演示代码主要步骤:

- 构建一张400x400大小的图片, Mat::Zero(400, 400, CV_8UC1)

- 画上一个六边形的闭合区域line

- 发现轮廓

- 对图像中所有像素点做点 多边形测试,得到距离,归一化后显示。

#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>using namespace std;
using namespace cv;
int main(int argc, char** argv) {const int r = 100;Mat src = Mat::zeros(r * 4, r * 4, CV_8UC1);vector<Point2f> vert(6);vert[0] = Point(3 * r / 2, static_cast<int>(1.34*r));   vert[1] = Point(1 * r, 2 * r);vert[2] = Point(3 * r / 2, static_cast<int>(2.866*r));   vert[3] = Point(5 * r / 2, static_cast<int>(2.866*r));vert[4] = Point(3 * r, 2 * r);   vert[5] = Point(5 * r / 2, static_cast<int>(1.34*r));for (int i = 0; i < 6; i++) {line(src, vert[i], vert[(i + 1) % 6], Scalar(255), 3, 8, 0);}vector<vector<Point>> contours;vector<Vec4i> hierachy;Mat csrc;src.copyTo(csrc);findContours(csrc, contours, hierachy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));Mat raw_dist = Mat::zeros(csrc.size(), CV_32FC1);for (int row = 0; row < raw_dist.rows; row++) {for (int col = 0; col < raw_dist.cols; col++) {double dist = pointPolygonTest(contours[0], Point2f(static_cast<float>(col), static_cast<float>(row)), true);raw_dist.at<float>(row, col) = static_cast<float>(dist);}}double minValue, maxValue;minMaxLoc(raw_dist, &minValue, &maxValue, 0, 0, Mat());Mat drawImg = Mat::zeros(src.size(), CV_8UC3);for (int row = 0; row < drawImg.rows; row++) {for (int col = 0; col < drawImg.cols; col++) {float dist = raw_dist.at<float>(row, col);if (dist > 0) {drawImg.at<Vec3b>(row, col)[0] = (uchar)(abs(1.0 - (dist / maxValue)) * 255);}else if (dist < 0) {drawImg.at<Vec3b>(row, col)[2] = (uchar)(abs(1.0 - (dist / minValue)) * 255);} else {drawImg.at<Vec3b>(row, col)[0] = (uchar)(abs(255 - dist));drawImg.at<Vec3b>(row, col)[1] = (uchar)(abs(255 - dist));drawImg.at<Vec3b>(row, col)[2] = (uchar)(abs(255 - dist));}}}const char* output_win = "point polygon test demo";char input_win[] = "input image";namedWindow(input_win, CV_WINDOW_AUTOSIZE);namedWindow(output_win, CV_WINDOW_AUTOSIZE);imshow(input_win, src);imshow(output_win, drawImg);waitKey(0);return 0;
}

效果展示:

可以了解一下不同位置的点:

(1)内部

drawImg.at<Vec3b>(row, col)[0] = (uchar)((abs(dist / maxValue) * 255);

(2)外部

drawImg.at<Vec3b>(row, col)[1] = (uchar)((abs(dist / minValue) * 255);

(3)边缘线

drawImg.at<Vec3b>(row, col)[0] =255;
drawImg.at<Vec3b>(row, col)[1] = saturate_cast<uchar>(minValue);
drawImg.at<Vec3b>(row, col)[2] = saturate_cast<uchar>(minValue);

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

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

相关文章

Go的两阶段延迟执行

Go 的 defer 不仅仅是用于清理任务&#xff0c;还可以用于准备任务&#xff0c;考虑以下示例&#xff1a; func setupTeardown() func() {fmt.Println("Run initialization")return func() {fmt.Println("Run cleanup")} }func main() {defer setupTeardo…

conda环境更改jupyter的环境

要在Jupyter中更改Conda环境&#xff0c;可以按照以下步骤进行操作&#xff1a; 1. 打开终端或命令提示符窗口。 2. 激活目标Conda环境。输入以下命令并按Enter键&#xff1a; conda activate <environment_name> 其中<environment_name>是你要激活…

深拷贝的几种方法

1、JSON.parse()和JSON.stringify() 可以将JavaScript对象序列化为一个JSON字符串&#xff0c;再使用JSON.parse()将其解析为一个新的对象&#xff0c;从而实现深拷贝。需要注意的是&#xff0c;该方法只能处理部分数据类型&#xff0c;例如字符串、数字、布尔值、数组和对象等…

Tomcat 部署项目时 war 和 war exploded区别

在 Tomcat 调试部署的时候&#xff0c;我们通常会看到有下面 2 个选项。 是选择war还是war exploded 这里首先看一下他们两个的区别&#xff1a; war 模式&#xff1a;将WEB工程以包的形式上传到服务器 &#xff1b;war exploded 模式&#xff1a;将WEB工程以当前文件夹的位置…

Debezium发布历史102

原文地址&#xff1a; https://debezium.io/blog/2021/02/24/debezium-1-5-beta1-released/ 欢迎关注留言&#xff0c;我是收集整理小能手&#xff0c;工具翻译&#xff0c;仅供参考&#xff0c;笔芯笔芯. Debezium 1.5.0.Beta1 发布 2021 年 2 月 24 日 作者&#xff1a; Gu…

总结了一下中继引擎(can中继器,TCP总机器)开发实际经验

多路数据进行中继的研究 1.数据中继的概念 数据中继是一种数据传输技术&#xff0c;用于在两个通信设备之间提供数字信号的传输。它利用数字信道传输数据信号&#xff0c;可以提供永久性和半永久性连接的数字数据传输信道。 数据中继的主要作用是提高通信质量和可靠性&#xf…

详解WebRTC rtc::Thread实现

rtc::Thread介绍 rtc::Thread类不仅仅实现了线程这个执行器&#xff08;比如posix底层调用pthread相关接口创建线程&#xff0c;管理线程等&#xff09;&#xff0c;还包括消息队列&#xff08;message_queue)的实现&#xff0c;rtc::Thread启动后就作为一个永不停止的event l…

Compose中的重组、state、remember

文章目录 一、前言二、示例代码三、参考链接: 一、前言 在Compose中UI采用State状态来控制UI变化&#xff0c;根据状态的不同来显示不同的内容&#xff0c;每次UI的重新变化成为重组。通过remember可以将state的数据保存起来(或者实例对象&#xff0c;毕竟条件不改变的话默认只…

《Pandas 简易速速上手小册》第8章:Pandas 高级数据分析技巧(2024 最新版)

文章目录 8.1 使用 apply 和 map 函数8.1.1 基础知识8.1.2 重点案例&#xff1a;客户数据清洗和转换8.1.3 拓展案例一&#xff1a;产品评分调整8.1.4 拓展案例二&#xff1a;地址格式化 8.2 性能优化技巧8.2.1 基础知识8.2.2 重点案例&#xff1a;大型销售数据分析8.2.3 拓展案…

BUUCTF-Real-[Flask]SSTI

目录 漏洞描述 模板注入漏洞如何产生&#xff1f; 漏洞检测 漏洞利用 get flag ​编辑 漏洞描述 Flask框架&#xff08;jinja2&#xff09;服务端模板注入漏洞分析&#xff08;SSTI&#xff09; Flask 是一个 web 框架。也就是说 Flask 为您提供工具、库和技术来允许您构…

JAVA面试题之三分布式和微服务的区别是什么?

面试题之三 分布式和微服务的区别是什么? 难度指数:3星 考察频率:50% 开发年限:3年左右 二者是隶属于不同的概念。 一.概念 微服务是系统架构的设计方式,是将复杂的业务拆分成多个微型的服务,让这些服务可以单独部署和运行。服务与服务之间可以使用RPC、OpenFeign…

基于PSO-BP神经网络的风电功率MATLAB预测程序

微❤关注“电气仔推送”获得资料&#xff08;专享优惠&#xff09; 参考文献 基于风电场运行特性的风电功率预测及应用分析——倪巡天 资源简介 由于自然风具有一定的随机性、不确定性与波动性&#xff0c;这将会使风电场的功率预测受到一定程度的影响&#xff0c;它们之间…

骨传导耳机的工作原理是什么?跟一般的耳机相比有什么特点?

骨传导耳机是利用骨传导技术研发而成一种新型蓝牙耳机&#xff0c;其传声方式很独特&#xff0c;不通过空气传导&#xff0c;而是通过人体骨骼来传递声音。 和传统的耳机相比&#xff0c;在佩戴方式和传声方式上都有所不同。 1、佩戴方式不同 首先就是佩戴方式不同&#xff0…

Java实现学生信息管理系统:从Excel中提取数据的实用方法

在Java中实现学生信息管理系统并从Excel中读取数据&#xff0c;通常适用于以下场景&#xff1a; 数据迁移和集成&#xff1a;如果你有一个现存的学生信息管理系统&#xff0c;该系统可能使用数据库或其他存储方式&#xff0c;但你想将这些数据迁移到新的系统。Excel文件可能提…

自动化测试框架:DrissionPage

自动化测试框架&#xff1a;DrissionPage 如果只要控制浏览器&#xff0c;导入ChromiumPage&#xff1a;如果只要收发数据包&#xff0c;导入SessionPage&#xff1a;WebPage是功能最全面的页面类&#xff0c;既可控制浏览器&#xff0c;也可收发数据包。常用1、定位元素2、爬取…

Spring Boot--08--Mybatis 之Mapper在IDEA中自动注入警告的解决方案

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 问题原因 解决方案方法1&#xff1a;为 Autowired 注解设置required false方法2&#xff1a;用 Resource 替换 Autowired方法3&#xff1a;在Mapper接口上加上Repo…

EXCEL VBA调用百度api识别身份证

EXCEL VBA调用百度api识别身份证 Sub BC_识别身份证()Dim SHD, SHX As WorksheetDim AppKey, SecretKey, Token, PathY As StringDim jSon, JSonA, WithHttp As ObjectDim Pic, oDom, oW, jsCode, paramsDim ARX, BRX, DRX, ERX, ZADDim StrText, StrUrl As StringDim StrA, S…

振动传感器接头MIL-C-5015玻璃烧结插座

振动传感器接头MIL-C-5015玻璃烧结插座产品主要用于加速度传感器&#xff0c;倾角传感器&#xff0c;耐高低温&#xff0c;耐腐蚀&#xff0c;适合使用恶劣环境。适用品牌有&#xff1a;MEGGITT&#xff0c;VibraSens,CTC measurement,BENTLY(本特利&#xff09;等众多品牌可定…

【代码随想录-链表】环形链表 II

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学习,不断总结,共同进步,活到老学到老导航 檀越剑指大厂系列:全面总结 jav…

C++ 入门(五)— 头文件(Header files)

文章目录 头文件的用途使用标准库头文件使用头文件传播前向声明避免将函数或变量定义放在头文件中尖括号与双引号VSCode中添加来自其他目录的头文件 头文件保护标头保护不会阻止标头包含在不同的代码文件中pragma once总结 头文件的用途 C 代码文件&#xff08;扩展名为 .cpp&…