【python】OpenCV—Image Moments
文章目录
- 1、功能描述
- 2、图像矩
- 3、代码实现
- 4、效果展示
- 5、完整代码
- 6、涉及到的库函数
- cv2.moments
- 7、参考
1、功能描述
计算图像的矩,以质心为例
2、图像矩
什么叫图像的矩,在数字图像处理中有什么作用? - 谢博琛的回答 - 知乎
https://www.zhihu.com/question/26803016/answer/888699124
0 阶矩 m 00 m_{00} m00:目标区域的面积(Area)
1 阶矩 m 01 , m 10 m_{01}, m_{10} m01,m10:目标区域的质心(Centroid)
2 阶矩 m 02 , m 20 , m 11 m_{02}, m_{20}, m_{11} m02,m20,m11:即惯性矩,可计算目标图像的方向
3 阶矩 m 03 , m 30 , m 12 , m 21 m_{03}, m_{30}, m_{12}, m_{21} m03,m30,m12,m21:目标区域的方位和斜度,反应目标的扭曲
Hu 矩:目标区域往往伴随着空间变换(平移,尺度,旋转),所以需要在普通矩的基础上构造出具备不变性的矩组
中心矩:构造平移不变性
一文弄懂图像的矩和相关应用
矩是统计学的一个概念(pencv中的图像矩(空间矩,中心矩,归一化中心矩,Hu矩))
图像矩(Image moments)是指图像的某些特定像素灰度的加权平均值(矩),或者是图像具有类似功能或意义的属性。
图像矩通常用来描述分割后的图像对象。可以通过图像的矩来获得图像的部分性质,包括面积(或总体亮度),以及有关几何中心和方向的信息 。
例如工业缺陷检测中(实操教程|使用计算机视觉算法检测钢板中的焊接缺陷),使用图像矩测量缺陷严重性
3、代码实现
导入必要的库函数,固定随机种子,以保证绘制出来的图片色彩固定随机
from __future__ import print_function
from __future__ import division
import cv2 as cv
import numpy as np
import argparse
import random as rngrng.seed(12345)
读取图片,为空打印 could not open or find xxx
parser = argparse.ArgumentParser(description='Code for Image Moments tutorial.')parser.add_argument('--input', help='Path to input image.', default='1.jpg')args = parser.parse_args()src = cv.imread(cv.samples.findFile(args.input))if src is None:print('Could not open or find the image:', args.input)exit(0)
图片转化为灰度图,做模糊处理,并在窗口中显示
# Convert image to gray and blur itsrc_gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)src_gray = cv.blur(src_gray, (3, 3))source_window = 'Source'cv.namedWindow(source_window)cv.imshow(source_window, src)
调用 canny 算子边缘检测找出图片中需要计算矩的轮廓
把 canny 算子的 threshold 设置为滑动条的形式进行回调,默认为 100
max_thresh = 255thresh = 100 # initial thresholdcv.createTrackbar('Canny Thresh:', source_window, thresh, max_thresh, thresh_callback)thresh_callback(thresh)cv.waitKey()
看看核心函数 thresh_callback
计算 canny 边缘检测,调用找轮廓函数,获取所有边缘轮廓
def thresh_callback(val):threshold = valcanny_output = cv.Canny(src_gray, threshold, threshold * 2)contours, _ = cv.findContours(canny_output, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
计算每个轮廓的矩
# Get the momentsmu = [None] * len(contours)for i in range(len(contours)):mu[i] = cv.moments(contours[i])
计算每个轮廓的质心,图片中所有像素点的横坐标除以图片的像素点个数(面积),结果为质心的横坐标
同理可以计算出质心的纵坐标
# Get the mass centersmc = [None] * len(contours)for i in range(len(contours)):# add 1e-5 to avoid division by zero# print(mu[i]['m00'], mu[i]['m10'], mu[i]['m01'])mc[i] = (mu[i]['m10'] / (mu[i]['m00'] + 1e-5), mu[i]['m01'] / (mu[i]['m00'] + 1e-5))
看看计算出来的矩的所有信息
mu[0]
output
{'m00': 1.0, 'm10': 668.0, 'm01': 876.3333333333333, 'm20': 446224.1666666666, 'm11': 585390.6666666666, 'm02': 767960.1666666666, 'm30': 298077966.0, 'm21': 391041111.3666667, 'm12': 512997391.3333333, 'm03': 672989190.1, 'mu20': 0.16666666662786156, 'mu11': 0.0, 'mu02': 0.055555555620230734, 'mu30': 5.960464477539063e-08, 'mu21': -0.022222160400502844, 'mu12': 9.778887033462524e-09, 'mu03': 0.007407426834106445, 'nu20': 0.16666666662786156, 'nu11': 0.0, 'nu02': 0.055555555620230734, 'nu30': 5.960464477539063e-08, 'nu21': -0.022222160400502844, 'nu12': 9.778887033462524e-09, 'nu03': 0.007407426834106445}
绘制轮廓,绘制每个轮廓的质心,保存结果
# Draw contoursdrawing = np.zeros((canny_output.shape[0], canny_output.shape[1], 3), dtype=np.uint8)for i in range(len(contours)):color = (rng.randint(0, 256), rng.randint(0, 256), rng.randint(0, 256))cv.drawContours(drawing, contours, i, color, 2)cv.circle(drawing, (int(mc[i][0]), int(mc[i][1])), 4, color, -1)cv.imshow('Contours', drawing)cv.imwrite("result.jpg", drawing)
对比下我们通过图片矩计算出来的面积和直接调用 opencv 接口的轮廓面积
# Calculate the area with the moments 00 and compare with the result of the OpenCV functionfor i in range(len(contours)):print(' * Contour[%d] - Area (M_00) = %.2f - Area OpenCV: %.2f - Length: %.2f' % (i, mu[i]['m00'], cv.contourArea(contours[i]), cv.arcLength(contours[i], True)))
output
* Contour[0] - Area (M_00) = 1.00 - Area OpenCV: 1.00 - Length: 17.66* Contour[1] - Area (M_00) = 0.00 - Area OpenCV: 0.00 - Length: 426.14* Contour[2] - Area (M_00) = 1.50 - Area OpenCV: 1.50 - Length: 67.90......* Contour[539] - Area (M_00) = 92.00 - Area OpenCV: 92.00 - Length: 541.41* Contour[540] - Area (M_00) = 21.50 - Area OpenCV: 21.50 - Length: 84.47* Contour[541] - Area (M_00) = 81.50 - Area OpenCV: 81.50 - Length: 289.49* Contour[542] - Area (M_00) = 61.00 - Area OpenCV: 61.00 - Length: 452.42
可以看到结果是一致的
4、效果展示
输入图片
threshold = 10
threshold = 60
threshold = 112
threshold = 163
threshold = 214
只绘制矩,不绘制轮廓
eg,threshold = 125
输入图片
threshold = 64
输入图片
threshold = 64
输入图片
threshold = 64
输入图片
threshold = 64
输入图片
threshold = 64
输入图片
threshold = 64
5、完整代码
from __future__ import print_function
from __future__ import division
import cv2 as cv
import numpy as np
import argparse
import random as rngrng.seed(12345)def thresh_callback(val):threshold = valcanny_output = cv.Canny(src_gray, threshold, threshold * 2)contours, _ = cv.findContours(canny_output, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)# Get the momentsmu = [None] * len(contours)for i in range(len(contours)):mu[i] = cv.moments(contours[i])# Get the mass centersmc = [None] * len(contours)for i in range(len(contours)):# add 1e-5 to avoid division by zero# print(mu[i]['m00'], mu[i]['m10'], mu[i]['m01'])mc[i] = (mu[i]['m10'] / (mu[i]['m00'] + 1e-5), mu[i]['m01'] / (mu[i]['m00'] + 1e-5))# Draw contoursdrawing = np.zeros((canny_output.shape[0], canny_output.shape[1], 3), dtype=np.uint8)for i in range(len(contours)):color = (rng.randint(0, 256), rng.randint(0, 256), rng.randint(0, 256))cv.drawContours(drawing, contours, i, color, 2)cv.circle(drawing, (int(mc[i][0]), int(mc[i][1])), 4, color, -1)cv.imshow('Contours', drawing)cv.imwrite("result.jpg", drawing)# Calculate the area with the moments 00 and compare with the result of the OpenCV functionfor i in range(len(contours)):print(' * Contour[%d] - Area (M_00) = %.2f - Area OpenCV: %.2f - Length: %.2f' % (i, mu[i]['m00'], cv.contourArea(contours[i]), cv.arcLength(contours[i], True)))if __name__ == "__main__":parser = argparse.ArgumentParser(description='Code for Image Moments tutorial.')parser.add_argument('--input', help='Path to input image.', default='1.jpg')args = parser.parse_args()src = cv.imread(cv.samples.findFile(args.input))if src is None:print('Could not open or find the image:', args.input)exit(0)# Convert image to gray and blur itsrc_gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)src_gray = cv.blur(src_gray, (3, 3))source_window = 'Source'cv.namedWindow(source_window)cv.imshow(source_window, src)max_thresh = 255thresh = 100 # initial thresholdcv.createTrackbar('Canny Thresh:', source_window, thresh, max_thresh, thresh_callback)thresh_callback(thresh)cv.waitKey()
6、涉及到的库函数
cv2.moments
cv2.moments
是 OpenCV 库中的一个函数,用于计算图像轮廓的矩。
一、函数原型
retval = cv2.moments(array[, binaryImage])
二、参数说明
-
array:表示轮廓的数组,可以是点集、灰度图像或二值图像。当 array 是点集时,函数会将这些点集当成轮廓中的顶点,把整个点集作为一条轮廓来处理,而不是将它们当成独立的点来看待。
-
binaryImage:可选参数,布尔值。当该参数为 True 时,array 内所有的非零值都被处理为 1。
三、返回值
- retval:一个字典对象,包含了轮廓的各种矩信息。这些矩可以用于进一步分析,如计算轮廓的重心、长宽比、旋转角度等。
四、矩的类型和含义
- 零阶矩(m00):表示轮廓的面积。这是一个比较直观的含义,可以通过 M[“m00”] 来访问。
- 一阶矩(m10, m01):与轮廓的质心位置有关。其中,m10 表示关于 x 轴的亮度加权平均值(即质心的 x 坐标),m01 表示关于 y 轴的亮度加权平均值(即质心的 y 坐标)。
- 二阶矩及更高阶矩:提供了关于图像形状相对于其中心的分布信息,以及更复杂的形状特征。
五、使用示例
import cv2
import numpy as np# 读取图像
img = cv2.imread("image.jpg")# 转换为灰度图像并二值化
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)# 查找轮廓
contours, _ = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)# 计算每个轮廓的矩
for contour in contours:M = cv2.moments(contour)print("轮廓的矩:", M)print("轮廓的面积:", M["m00"])
六、注意事项
- 在使用 cv2.moments 函数之前,需要确保已经正确读取了图像并找到了轮廓。
- 返回值是一个字典对象,可以通过键来访问不同类型的矩值。
- 矩值可以用于后续的形状分析和特征提取任务中。
综上所述,cv2.moments 函数是 OpenCV 库中用于计算图像轮廓矩的重要工具,它提供了关于图像形状的重要信息,并广泛应用于形状分析、特征提取和形状识别等任务中。
7、参考
- https://docs.opencv.org/5.x/d0/d49/tutorial_moments.html
相关文章:

【python】OpenCV—Image Moments
文章目录 1、功能描述2、图像矩3、代码实现4、效果展示5、完整代码6、涉及到的库函数cv2.moments 7、参考 1、功能描述 计算图像的矩,以质心为例 2、图像矩 什么叫图像的矩,在数字图像处理中有什么作用? - 谢博琛的回答 - 知乎 https://ww…...

环境变量的知识
目录 1. 环境变量的概念 2. 命令行参数 2.1 2.2 创建 code.c 文件 2.3 对比 ./code 执行和直接 code 执行 2.4 怎么可以不带 ./ 2.4.1 把我们的二进制文件拷贝到 usr/bin 路径下,也不用带 ./ 了 2.4.2 把我们自己的路径添加到环境变量里 3. 认识PATH 3.…...

ATECLOUD测试平台有哪些功能?
测试方案搭建 可视化拖拽编程:采用零代码的图文拖拽形式,用户通过鼠标拖拽节点和连线,即可可视化地构建测试模型,无需懂得代码开发,15 分钟左右就能快速搭建项目,大大降低了上手门槛。 子项目多层嵌套&am…...

使用pyinstaller打包pyqt的程序,运行后提示ModuleNotFoundError: No module named ‘Ui_main‘
环境:windowpython3.9pyqt6 使用pyqt UI编辑器生成了main.ui ,main.ui编译成了Ui_main.py main.py 使用当前目录下的Ui_main.py。 打包过程没报错,运行报错。 错误如下: 解决方法:pyinstaller -Fw main.py --paths. 使…...

搭建分布式Spark集群
title: 搭建分布式Spark集群 date: 2024-11-29 12:00:00 categories: - 服务器 tags: - Spark - 大数据搭建分布式Spark集群 本次实验环境:Centos 7-2009、Hadoop-3.1.4、JDK 8、Zookeeper-3.6.3、scala-2.11.5、Spark-3.2.1 功能规划 MasterSlave1Slave2主节点…...

Django基础 - 01入门简介
一、 基本概念 1.1 Django说明 Django发布于2005年, 网络框架, 用Python编写的开源的Web应用框架。采用了MVC框架模式,也称为MTV模式。官网: https://www.djangoproject.com1.2 MVC框架 Model: 封装和数据库相关…...

简单的bytebuddy学习笔记
简单的bytebuddy学习笔记 此笔记对应b站bytebuddy学习视频进行整理,此为视频地址,此处为具体的练习代码地址 一、简介 ByteBuddy是基于ASM (ow2.io)实现的字节码操作类库。比起ASM,ByteBuddy的API更加简单易用。开发者无需了解class file …...

【服务端】Redis 内存超限问题的深入探讨
在 Java 后端开发中,Redis 内存超限是一个常见的问题,可能由多种原因引起。理解这些原因以及如何处理已经超出限制的数据对于保持系统的稳定性和性能至关重要。 一、Redis 内存超限的原因分析 Redis 是一个高性能的内存键值对存储系统,它在…...

Springboot logback 日志打印配置文件,每个日志文件100M,之后滚动到下一个日志文件,日志保留30天(包含traceid)
全部配置 logback.xml <?xml version"1.0" encoding"UTF-8"?> <configuration debug"false"><property name"LOG_HOME" value"log"/><property name"LOG_NAME" value"admin"/&g…...

《计算机组成及汇编语言原理》阅读笔记:p1-p8
《计算机组成及汇编语言原理》学习第 1 天,p1-p8 总结,总计 8 页。 一、技术总结 1.Intel 8088 microprocessor(微处理器), 1979-1988。 2.MS-DOS Microsoft Disk Operating System的缩写,是一个操作系统(operating system)。…...

【游戏中orika完成一个Entity的复制及其Entity异步落地的实现】 1.ctrl+shift+a是飞书下的截图 2.落地实现
一、orika工具使用 1)工具类 package com.xinyue.game.utils;import ma.glasnost.orika.MapperFactory; import ma.glasnost.orika.impl.DefaultMapperFactory;/*** author 王广帅* since 2022/2/8 22:37*/ public class XyBeanCopyUtil {private static MapperFactory mappe…...

在 Ubuntu 上安装 MySQL 的详细指南
在Ubuntu环境中安装 mysql-server 以及 MySQL 开发包(包括头文件和动态库文件),并处理最新版本MySQL初始自动生成的用户名和密码,可以通过官方的APT包管理器轻松完成。以下是详细的步骤指南,包括从官方仓库和MySQL官方…...

Java 优化springboot jar 内存 年轻代和老年代的比例 减少垃圾清理耗时 如调整 -XX:NewRatio
-XX:NewRatio 是 Java Virtual Machine (JVM) 的一个选项,用于调整 年轻代(Young Generation)和 老年代(Old Generation)之间的内存比例。 1. 含义 XX:NewRatioN 用于指定 老年代 与 年轻代 的内存比例。 N 的含义&…...

嵌入式驱动RK3566 HDMI eDP MIPI 背光 屏幕选型与调试提升篇-eDP屏
eDP是嵌入式显示端口,具有高数据传输速率,高带宽,高分辨率、高刷新率、低电压、简化接口数量等特点。现大多数笔记本电脑都是用的这种接口。整个eDP是很复杂的,这里我们不讲底层原理,我们先掌握如何用泰山派来驱动各种…...

在Java虚拟机(JVM)中,方法可以分为虚方法和非虚方法。
在Java虚拟机(JVM)中,方法可以分为虚方法和非虚方法。以下是关于这两种方法的详细解释: 一、虚方法(Virtual Method) 定义:虚方法是指在运行时由实例的实际类型决定的方法。在Java中,所有的非私有、非静态、非final方法都是虚方法。当调用一个虚方法时,JVM会根据实…...

【windows】sonarqube起不来的问题解决
1. 现象与本质 因JDK的问题(比如版本太低或者太高,推荐JDK17)或者其他环境因素,导致sonarqube启动后自动关闭了。 从日志来看,根本看不出来什么,只有警告,没有ERROR,警告也不是本质问题&#…...

golang异常
panic如果不处理会导致应用进程挂掉 defer recover可以处理这种情况 一个recover只处理自己协程 产生panic的情况 空指针 数组越界 空map中添加键值对 错误,error接口,不严重 error.wrapof解决嵌套问题或者error.unwrap erroe.is方法,判断是…...

搭建MongoDB
title: 搭建MongoDB date: 2024-11-30 23:30:00 categories: - 服务器 tags: - MongoDB - 大数据搭建MongoDB 环境:Centos 7-2009 1. 创建MongoDB的国内yum源 # 下载Centos7对应最新版7.0.15的安装包 cat >> /etc/yum.repos.d/mongodb.repo << &quo…...

Android中坐标体系知识超详细讲解
说来说去都不如画图示意简单易懂啊!!!真是的! 来吧先上张图! (一)首先明确一下android 中的坐标系统: 屏幕的左上角是坐标系统原点(0,0) 原点向右延伸是X轴正…...

不需要服务器,使用netlify快速部署自己的网站
Netlify简介 1.1 Netlify的功能与特点 Netlify 是一个功能强大的静态网站托管平台,它不仅提供了简单的网站部署功能,还集成了许多现代化的开发工具和服务,帮助开发者更高效地构建、部署和管理网站。Netlify 的核心功能包括: 自动…...

Swin transformer 论文阅读记录 代码分析
该篇文章,是我解析 Swin transformer 论文原理(结合pytorch版本代码)所记,图片来源于源paper或其他相应博客。 代码也非原始代码,而是从代码里摘出来的片段,配上简单数据,以便理解。 当然&…...

信息安全概论
文章目录 预测题重要考点1.遇到什么威胁有什么漏洞怎么缓解分析题2.网络安全现状分析 2.网络安全亮点 时间信息安全概论期末简答题软件学院实验室服务器安全风险分析与PDRR策略 1.1 信息时代的特点1.2 信息安全威胁1.3信息安全趋势1.4 研究网络与信息安全的意义2.1安全风险分析…...

2024年12月16日Github流行趋势
项目名称:PDFMathTranslate 项目维护者:Byaidu reycn hellofinch Wybxc YadominJinta项目介绍:基于 AI 完整保留排版的 PDF 文档全文双语翻译,支持 Google/DeepL/Ollama/OpenAI 等服务,提供 CLI/GUI/Docker。项目star数…...

Go 1.24即将到来!
Go 1.24 尚未发布。以下是正在撰写中的发布说明,预计 Go 1.24 将于 2025 年 2 月发布。 语言改进 Go 1.24 现在全面支持 泛型类型别名:类型别名可以像定义类型一样被参数化。详情请参阅语言规范。目前,可通过设置 GOEXPERIMENTnoaliastypep…...

FFmpeg库之ffplay
文章目录 FFmpeg环境搭建ffplay使用通用选项视频选项音频选项快捷键使用滤镜直播拉流 FFmpeg环境搭建 FFmpeg官网 FFmpeg环境搭建 ./configure \--prefix"$HOME/ffmpeg" \--extra-cflags"-I$HOME/ffmpeg/include" \--extra-ldflags"-L$HOME/ffmpeg…...

scala中模式匹配的应用
package test34object test6 {case class Person(name:String)case class Student(name:String, className:String)// match case 能根据 类名和属性的信息,匹配到对应的类// 注意:// 1 匹配的时候,case class的属性个数要对上// 2 属性名不需…...

WebRTC搭建与应用(一)-ICE服务搭建
WebRTC搭建与应用(一) 近期由于项目需要在研究前端WebGL渲染转为云渲染,借此机会对WebRTC、ICE信令协议等有了初步了解,在此记录一下,以防遗忘。 第一章 ICE服务搭建 文章目录 WebRTC搭建与应用(一)前言一、ICE是什么?二、什么…...

【计算机视觉基础CV】03-深度学习图像分类实战:鲜花数据集加载与预处理详解
本文将深入介绍鲜花分类数据集的加载与处理方式,同时详细解释代码的每一步骤并给出更丰富的实践建议和拓展思路。以实用为导向,为读者提供从数据组织、预处理、加载到可视化展示的完整过程,并为后续模型训练打下基础。 前言 在计算机视觉的深…...

Kafka学习篇
Architecture 系统间解耦,异步通信,削峰填谷 Topic 消息主题,用于存储消息 Partition 分区,通过扩大分区,可以提高存储量 Broker 部署Kafka服务的设备 Leader kafka主分区 Follwer kafka从分区 高性能之道:…...

冬日养仓鼠小指南:温暖与陪伴同行
随着冬日的脚步悄然来临,家中可爱的小仓鼠也需要我们给予更多的关怀与呵护。仓鼠虽小,但它们的冬日养护却大有学问,关乎着这些小生命能否健康快乐地度过寒冷季节。 保暖是冬季养仓鼠的首要任务。我们可以为仓鼠的小窝增添一些保暖材料&#…...