【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 rng

rng.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 it
    src_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 = 255
    thresh = 100  # initial threshold
    cv.createTrackbar('Canny Thresh:', source_window, thresh, max_thresh, thresh_callback)
    thresh_callback(thresh)

    cv.waitKey()

看看核心函数 thresh_callback

计算 canny 边缘检测,调用找轮廓函数,获取所有边缘轮廓

def thresh_callback(val):
    threshold = val

    canny_output = cv.Canny(src_gray, threshold, threshold * 2)

    contours, _ = cv.findContours(canny_output, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)

计算每个轮廓的矩

    # Get the moments
    mu = [None] * len(contours)
    for i in range(len(contours)):
        mu[i] = cv.moments(contours[i])

计算每个轮廓的质心,图片中所有像素点的横坐标除以图片的像素点个数(面积),结果为质心的横坐标

同理可以计算出质心的纵坐标

    # Get the mass centers
    mc = [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 contours

    drawing = 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 function
    for 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 rng

rng.seed(12345)


def thresh_callback(val):
    threshold = val

    canny_output = cv.Canny(src_gray, threshold, threshold * 2)

    contours, _ = cv.findContours(canny_output, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)

    # Get the moments
    mu = [None] * len(contours)
    for i in range(len(contours)):
        mu[i] = cv.moments(contours[i])

    # Get the mass centers
    mc = [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 contours

    drawing = 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 function
    for 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 it
    src_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 = 255
    thresh = 100  # initial threshold
    cv.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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【漏洞复现】CVE-2022-45206 CVE-2023-38905 SQL Injection

漏洞信息 NVD - CVE-2022-45206 Jeecg-boot v3.4.3 was discovered to contain a SQL injection vulnerability via the component /sys/duplicate/check. NVD - CVE-2023-38905 SQL injection vulnerability in Jeecg-boot v.3.5.0 and before allows a local attacker to…

现代风格VUE3易支付用户控制中心

适用系统 彩虹易支付 技术栈 vitevue3elementuiplusphp 亮点 独立前端代码,扩展开发,不改动系统文件,不影响原版升级 支持功能订制 界面预览

开发技术-Java改变图片格式

图片上传页未做控制,导致上传的是GIF格式,导致图片识别失败。需要将GIF格式转为JPEG格式。 代码,是找AI写的,记录一下: import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; im…

【计算机视觉基础CV】03-深度学习图像分类实战:鲜花数据集加载与预处理详解

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

Unity-Editor扩展GUI基本实现一个可拖拉放的格子列表

短短几百行代码,好吧,又是“参考”了国外的月亮 操作,还真地挺自然的。。。。。。国外的实现有点小牛 拖拉,增加+ 一个Element 鼠标左键长按,可以出提示 鼠标右键,清除Element, 有点小bug,不是很自然地完全清除, using System.Collections; using System.Collecti…

修改vscode中emmet中jsx和tsx语法中className的扩展符号从单引号到双引号 - HTML代码补全 - 单引号双引号

效果图 实现步骤 文件 > 首选项 > 设置搜索“”在settings.json中修改,增加 "emmet.syntaxProfiles": {"html": {"attr_quotes": "single"},"jsx": {"attr_quotes": "double","…

首批|云轴科技ZStack成为开放智算产业联盟首批会员单位

近日 ,在Linux基金会AI & Data及中国开源软件推进联盟的指导之下,开放智算产业联盟成立大会在北京成功召开。在大会上,联盟首次公布了组织架构并颁发了首批会员单位证书。凭借ZStack AIOS平台智塔和在智算领域的技术创新,云轴…

HTN 78A3 6V~140V输入,3A实地异步降压变换器

1、特征 3A降压,内置250mΩ高侧功率管 输入电压范围:6V~140V 脉冲跳跃模式使得轻载下高效率 最高1MHZ可编程开关频率 COT纹波电压控制架构 欠压保护、过流保护和过热关断保护 无铅封装,ESOP8 2、应用 二轮电瓶车 太阳能系统 高压电池组 …

以太网帧、IP数据报图解

注:本文为 “以太网帧、IP数据报”图解相关文章合辑。 未整理去重。 以太网帧、IP数据报的图解格式(包含相关例题讲解) Rebecca.Yan已于 2023-05-27 14:13:19 修改 一、基础知识 UDP 段、IP 数据包,以太网帧图示 通信过程中&…

汽车IVI中控开发入门及进阶(三十九):ADAS的车道线检测

概述: 自动驾驶汽车中确保驾驶员和乘客安全环境的重要系统之一是高级驾驶员辅助系统(ADAS)。自适应巡航控制、自动制动/转向、车道保持系统、盲点辅助、车道偏离警告系统和车道检测都是ADAS的示例。车道检测向车辆的智能系统显示特定于车道线结构几何特征的信息,以显示车道…

Liveweb视频汇聚平台支持WebRTC协议赋能H.265视频流畅传输

随着科技的飞速发展和网络技术的不断革新,视频监控已经广泛应用于社会各个领域,成为现代安全管理的重要组成部分。在视频监控领域,视频编码技术的选择尤为重要,它不仅关系到视频的质量,还直接影响到视频的传输效率和兼…

搭建一个简单的Web服务器(Apache2.4)

一、下载安装包 Apache服务器的官方下载地址:http://httpd.apache.org windows系统的安装软件下载地址:https://www.apachelounge.com/download/ 下载的是免安装的版本:httpd-2.4.62-240904-win64-VS17.zip 解压后将 Apache24 拷贝到 D 盘&…

NTFS 文件搜索库

NTFS 文件搜索库 中文 | English 一个快速搜索NTFS卷文件的库 在这里插入图片描述 特性 快速扫描 NTFS 格式驱动器上的所有文件实时快速同步文件变更(创建, 更名, 删除)支持通配符查询文件名或文件路径重启自动更新文件变动, 无需重新进行全盘扫描 API描述 初始化并指定…

Ubuntu下C语言操作kafka示例

目录 安装kafka: 安装librdkafka consumer Producer 测试运行 安装kafka: Ubuntu下Kafka安装及使用_ubuntu安装kafka-CSDN博客 安装librdkafka github地址:GitHub - confluentinc/librdkafka: The Apache Kafka C/C library $ apt in…

JavaScript基础学习

1.一元运算符 正负号,自增运算符 2.比较运算符 判断相等用 字符串比较,比较的是ASC码 尽量不要比较小数,小数有精度 不同类型比较会有隐式转换 3.运算符优先级 4.分支语句 除了0,其余数字都是真。除了空字符串&#xff0c…

SQL进阶技巧:如何计算商品需求与到货队列表进出计划?

目录 0 需求描述 1 数据准备 2 问题分析 3 小结 累计到货数量计算 出货数量计算 剩余数量计算 0 需求描述 假设现有多种商品的订单需求表 DEMO_REQUIREMENT,以及商品的到货队列表 DEMO_ARR_QUEUE,要求按照业务需要,设计一个报表&#…

“调用函数”多出一个None

Python中函数缺省返回空值,试图打印没有return的函数都将是None。 (笔记模板由python脚本于2024年12月20日 19:59:03创建,本篇笔记适合会自定义python函数的coder翻阅) 【学习的细节是欢悦的历程】 Python 官网:https://www.python.org/ Fre…

Flask内存马学习

文章目录 参考文章环境搭建before_request方法构造内存马after_request方法构造内存马errorhandler方式构造内存马add_url_rule方式构造内存马 参考文章 https://www.mewo.cc/archives/10/ https://www.cnblogs.com/gxngxngxn/p/18181936 前人栽树, 后人乘凉 大佬们太nb了, …

在Win11系统上安装Android Studio

诸神缄默不语-个人CSDN博文目录 下载地址:https://developer.android.google.cn/studio?hlzh-cn 官方安装教程:https://developer.android.google.cn/studio/install?hlzh-cn 点击Next,默认会同时安装Android Studio和Android虚拟机&#…

Python读取Excel批量写入到PPT生成词卡

一、问题的提出 有网友想把Excel表中的三列数据,分别是:单词、音标和释义分别写入到PPT当中,每一张PPT写一个单词的内容。这种批量操作是python的强项,尤其是在办公领域,它能较好地解放双手,读取Excel表后…