opencv 基础50-图像轮廓学习03-Hu矩函数介绍及示例-cv2.HuMoments()

什么是Hu 矩?

Hu 矩(Hu Moments)是由计算机视觉领域的科学家Ming-Kuei Hu于1962年提出的一种图像特征描述方法。这些矩是用于描述图像形状和几何特征的不变特征,具有平移、旋转和尺度不变性,适用于图像识别、匹配和形状分析等任务。

Ming-Kuei Hu在其论文中提出了七个用于形状描述的独特特征,称之为Hu矩。这些特征通过一系列组合和归一化操作,能够捕获图像的不同几何属性,如大小、形状、旋转等,同时保持了对这些变换的不变性。这使得Hu矩在图像处理领域中成为了一种重要的特征表示方法。

以下是七个Hu矩的表示:

  1. 第一不变矩(Invariant Moment 1):描述图像的大小。

  2. 第二不变矩(Invariant Moment 2):描述图像的形状,与图像的缩放无关。

  3. 第三不变矩(Invariant Moment 3):描述图像的形状,与图像的缩放无关。

  4. 第四不变矩(Invariant Moment 4):描述图像的形状和旋转,与图像的缩放无关。

  5. 第五不变矩(Invariant Moment 5):描述图像的形状和旋转,与图像的缩放无关。

  6. 第六不变矩(Invariant Moment 6):描述图像的形状,与图像的缩放和旋转无关。

  7. 第七不变矩(Invariant Moment 7):描述图像的形状,与图像的缩放和旋转无关。

Hu 矩 应用场景?

Hu 矩(Hu Moments)由于其对图像形状的不变性,适用于多种图像处理和模式识别应用场景。以下是一些常见的Hu矩应用场景:

  1. 形状识别:Hu矩可以用于描述图像中的形状,从而实现形状识别。它们对图像的尺度、旋转和平移变换具有不变性,因此可以在不同的姿态和尺寸下进行形状匹配。

  2. 模式识别:Hu矩可以用于模式识别任务,如字符识别、手写字体识别等。它们可以捕获图像的局部和全局特征,从而实现对不同模式的识别。

  3. 目标检测:Hu矩可以用于图像中目标的检测和定位。通过比较目标和待检测区域的Hu矩特征,可以判断目标是否存在并确定其位置。

  4. 图像匹配:Hu矩可以用于图像的匹配和对准。通过计算图像的Hu矩特征,可以找到相似的图像或对象。

  5. 图像检索:在图像检索任务中,Hu矩可以用作图像的特征表示,从而实现对相似图像的检索。

  6. 物体排序:Hu矩可以用于对物体进行排序,根据其形状特征的相似性进行排列。

  7. 医学图像分析:在医学图像领域,Hu矩可以用于描述器官和病变的形状特征,实现图像分析和诊断。

  8. 遥感图像分析:在遥感图像分析中,Hu矩可以用于分析地物的形状和分布,如土地利用分类等

Hu矩函数介绍

函数 cv2.HuMoments()的语法格式为:

hu = cv2.HuMoments( m )

式中返回值 hu,表示返回的 Hu 矩值;参数 m,是由函数 cv2.moments()计算得到矩特征值。

Hu 矩是归一化中心矩的线性组合,每一个矩都是通过归一化中心矩的组合运算得到的。
函数 cv2.moments()返回的归一化中心矩中包含:

  • 二阶 Hu 矩:nu20, nu11, nu02
  • 三阶 Hu 矩:nu30, nu21, nu12, nu03
    为了表述上的方便,将上述字母“nu”表示为字母“v”,则归一化中心矩为:
  • 二阶 Hu 矩:v20, v11, v02
  • 三阶 Hu 矩:v30, v21, v12, v03
    上述 7 个 Hu 矩的计算公式为:

在这里插入图片描述

代码示例:

本例对 Hu 矩中的第 0 个矩ℎ0 = 𝑣20 + 𝑣02的关系进行验证,即 Hu 矩中第 0 个矩对应的函数 cv2.moments()的返回值为:

ℎ0 = 𝑛𝑢20 + 𝑛𝑢02

代码如下:

import cv2
o1 = cv2.imread('cs1.bmp')
gray = cv2.cvtColor(o1,cv2.COLOR_BGR2GRAY)
#获取图像的Hu矩
HuM1=cv2.HuMoments(cv2.moments(gray)).flatten()
print("cv2.moments(gray)=\n",cv2.moments(gray))
print("\nHuM1=\n",HuM1)
print("\ncv2.moments(gray)['nu20']+cv2.moments(gray)['nu02']=%f+%f=%f\n"%(cv2.moments(gray)['nu20'],cv2.moments(gray)['nu02'],cv2.moments(gray)['nu20']+cv2.moments(gray)['nu02']))
print("HuM1[0]=",HuM1[0])
print("\nHu[0]-(nu02+nu20)=",HuM1[0]-(cv2.moments(gray)['nu20']+cv2.moments(gray)['nu02']))

运行结果:

cv2.moments(gray)={'m00': 2729265.0, 'm10': 823361085.0, 'm01': 353802555.0, 'm20': 256058984145.0, 'm11': 104985534390.0, 'm02': 47279854725.0, 'm30': 81917664997185.0, 'm21': 32126275537320.0, 'm12': 13822864338150.0, 'm03': 6484319942535.0, 'mu20': 7668492092.239544, 'mu11': -1749156290.6675763, 'mu02': 1415401136.0198045, 'mu30': 43285283824.24758, 'mu21': -12028503719.706358, 'mu12': 13036213891.873255, 'mu03': -11670178717.880629, 'nu20': 0.0010294815371794516, 'nu11': -0.0002348211467422498, 'nu02': 0.00019001510593064498, 'nu30': 3.517434386213551e-06, 'nu21': -9.77456282143905e-07, 'nu12': 1.0593444921255944e-06, 'nu03': -9.48338194620685e-07}HuM1=[ 1.21949664e-03  9.25267773e-07  4.05157060e-12  2.46555893e-112.41189094e-22  2.27497012e-14 -5.05282814e-23]cv2.moments(gray)['nu20']+cv2.moments(gray)['nu02']=0.001029+0.000190=0.001219HuM1[0]= 0.0012194966431100965Hu[0]-(nu02+nu20)= 0.0

程序运行结果显示“Hu[0]-(nu02+nu20)= 0.0”。从该结果可知,关系ℎ0 = 𝑛𝑛20 + 𝑛𝑢02成立。

示例2: 计算三幅不同图像的 Hu 矩,并进行比较。

代码如下:

import cv2
o1 = cv2.imread('cs1.bmp')
gray1 = cv2.cvtColor(o1,cv2.COLOR_BGR2GRAY)
HuM1=cv2.HuMoments(cv2.moments(gray1)).flatten()
#----------------计算图像 o2 的 Hu 矩-------------------
o2 = cv2.imread('cs3.bmp')
gray2 = cv2.cvtColor(o2,cv2.COLOR_BGR2GRAY)
HuM2=cv2.HuMoments(cv2.moments(gray2)).flatten()
#----------------计算图像 o3 的 Hu 矩-------------------
o3 = cv2.imread('lena.bmp')
gray3 = cv2.cvtColor(o3,cv2.COLOR_BGR2GRAY)
HuM3=cv2.HuMoments(cv2.moments(gray3)).flatten()
#---------打印图像 o1、图像 o2、图像 o3 的特征值------------
print("o1.shape=",o1.shape)
print("o2.shape=",o2.shape)
print("o3.shape=",o3.shape)
print("cv2.moments(gray1)=\n",cv2.moments(gray1))
print("cv2.moments(gray2)=\n",cv2.moments(gray2))
print("cv2.moments(gray3)=\n",cv2.moments(gray3))
print("\nHuM1=\n",HuM1)
print("\nHuM2=\n",HuM2)
print("\nHuM3=\n",HuM3)
#---------计算图像 o1 与图像 o2、图像 o3 的 Hu 矩之差----------------
print("\nHuM1-HuM2=",HuM1-HuM2)
print("\nHuM1-HuM3=",HuM1-HuM3)
#---------显示图像----------------
cv2.imshow("original1",o1)
cv2.imshow("original2",o2)
cv2.imshow("original3",o3)
cv2.waitKey()
cv2.destroyAllWindows()

运行结果:
显示各个图像的 shape 属性、moments 属性、HuMoments 属性,以及不同图像的 Hu 矩之差

o1.shape= (425, 514, 3)
o2.shape= (425, 514, 3)
o3.shape= (512, 512, 3)
cv2.moments(gray1)={'m00': 2729265.0, 'm10': 823361085.0, 'm01': 353802555.0, 'm20': 256058984145.0, 'm11': 104985534390.0, 'm02': 47279854725.0, 'm30': 81917664997185.0, 'm21': 32126275537320.0, 'm12': 13822864338150.0, 'm03': 6484319942535.0, 'mu20': 7668492092.239544, 'mu11': -1749156290.6675763, 'mu02': 1415401136.0198045, 'mu30': 43285283824.24758, 'mu21': -12028503719.706358, 'mu12': 13036213891.873255, 'mu03': -11670178717.880629, 'nu20': 0.0010294815371794516, 'nu11': -0.0002348211467422498, 'nu02': 0.00019001510593064498, 'nu30': 3.517434386213551e-06, 'nu21': -9.77456282143905e-07, 'nu12': 1.0593444921255944e-06, 'nu03': -9.48338194620685e-07}
cv2.moments(gray2)={'m00': 1755675.0, 'm10': 518360685.0, 'm01': 190849140.0, 'm20': 156229722135.0, 'm11': 55624504050.0, 'm02': 21328437150.0, 'm30': 47992502493915.0, 'm21': 16559578863270.0, 'm12': 6135747671370.0, 'm03': 2448843661890.0, 'mu20': 3184426306.5185323, 'mu11': -723448129.1111062, 'mu02': 582345624.666668, 'mu30': -14508249198.719406, 'mu21': 3955540976.461006, 'mu12': -4161129804.772763, 'mu03': 3747496072.0989423, 'nu20': 0.0010331014067430548, 'nu11': -0.00023470327398074627, 'nu02': 0.00018892636416872804, 'nu30': -3.552259578607564e-06, 'nu21': 9.684909688102524e-07, 'nu12': -1.018828185563436e-06, 'nu03': 9.175523962658914e-07}
cv2.moments(gray3)={'m00': 32524520.0, 'm10': 8668693016.0, 'm01': 8048246168.0, 'm20': 3012074835288.0, 'm11': 2188197716912.0, 'm02': 2697437187672.0, 'm30': 1162360702630328.0, 'm21': 771188127583648.0, 'm12': 737629807045152.0, 'm03': 1024874860779368.0, 'mu20': 701626022956.6517, 'mu11': 43115319152.08315, 'mu02': 705885386731.4578, 'mu30': -14447234840441.977, 'mu21': 2862363425762.6274, 'mu12': -2650458863973.0146, 'mu03': 8044566997348.251, 'nu20': 0.0006632601374460898, 'nu11': 4.0757713612639876e-05, 'nu02': 0.0006672865932933315, 'nu30': -2.3947351703101653e-06, 'nu21': 4.7445773821681405e-07, 'nu12': -4.393330024129607e-07, 'nu03': 1.3334460006519109e-06}HuM1=[ 1.21949664e-03  9.25267773e-07  4.05157060e-12  2.46555893e-112.41189094e-22  2.27497012e-14 -5.05282814e-23]HuM2=[ 1.22202777e-03  9.32974010e-07  4.19762083e-12  2.44520029e-112.44855011e-22  2.27298009e-14 -3.76120600e-23]HuM3=[ 1.33054673e-03  6.66097722e-09  1.16744767e-12  1.13004583e-11-2.02613532e-24 -8.54504575e-16  4.09952009e-23]HuM1-HuM2= [-2.53112780e-06 -7.70623675e-09 -1.46050222e-13  2.03586345e-13-3.66591675e-24  1.99003443e-17 -1.29162214e-23]HuM1-HuM3= [-1.11050088e-04  9.18606796e-07  2.88412294e-12  1.33551309e-112.43215229e-22  2.36042058e-14 -9.15234823e-23]

从上述输出结果可以看到,由于 Hu 矩的值本身就非常小,因此在这里并没有发现两个对象的 Hu 矩差值的特殊意义。那怎么样才行让这三个图进行更明显的匹配呢? opencv 提供了函数 cv2.matchShapes()允许我们提供两个对象,对二者的 Hu 矩进行比较。

形状匹配函数 cv2.matchShapes()

函数 cv2.matchShapes()的语法格式为:

retval = cv2.matchShapes( contour1, contour2, method, parameter )

式中 retval 是返回值。
该函数有如下 4 个参数:

  • contour1:第 1 个轮廓或者灰度图像。
  • contour2:第 2 个轮廓或者灰度图像。
  • method:比较两个对象的 Hu 矩的方法,具体如表 12-1 所示

在这里插入图片描述
在表 12-1 中,A 表示对象 1,B 表示对象 2:

在这里插入图片描述
式中,ℎ𝑖𝐴和ℎ𝑖𝐵分别是对象 A 和对象 B 的 Hu 矩。

  • parameter:应用于 method 的特定参数,该参数为扩展参数,目前(新版本)不支持该参数,因此将该值设置为 0。

示例:使用函数 cv2.matchShapes()计算三幅不同图像的匹配度。

代码如下:

import cv2
o1 = cv2.imread('cs1.bmp')
o2 = cv2.imread('cs2.bmp')
o3 = cv2.imread('cc.bmp')gray1 = cv2.cvtColor(o1,cv2.COLOR_BGR2GRAY)
gray2 = cv2.cvtColor(o2,cv2.COLOR_BGR2GRAY)
gray3 = cv2.cvtColor(o3,cv2.COLOR_BGR2GRAY)ret, binary1 = cv2.threshold(gray1,127,255,cv2.THRESH_BINARY)
ret, binary2 = cv2.threshold(gray2,127,255,cv2.THRESH_BINARY)
ret, binary3 = cv2.threshold(gray3,127,255,cv2.THRESH_BINARY)contours1, hierarchy = cv2.findContours(binary1,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)
contours2, hierarchy = cv2.findContours(binary2,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)
contours3, hierarchy = cv2.findContours(binary3,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)cnt1 = contours1[0]
cnt2 = contours2[0]
cnt3 = contours3[0]ret0 = cv2.matchShapes(cnt1,cnt1,1,0.0)
ret1 = cv2.matchShapes(cnt1,cnt2,1,0.0)
ret2 = cv2.matchShapes(cnt1,cnt3,1,0.0)print("相同图像的 matchShape=",ret0)
print("相似图像的 matchShape=",ret1)
print("不相似图像的 matchShape=",ret2)cv2.imshow("o1",o1)
cv2.imshow("o2",o2)
cv2.imshow("o3",o3)
cv2.waitKey()
cv2.destroyAllWindows()

运行结果:

相同图像的 matchShape= 0.0
相似图像的 matchShape= 0.10720296440067095
不相似图像的 matchShape= 0.5338506830800509

在这里插入图片描述

从以上结果可以看出:

  • 同一幅图像的 Hu 矩是不变的,二者差值为 0。
  • 相似的图像即使发生了平移、旋转和缩放后,函数 cv2.matchShapes()的返回值仍然比较
    接近。例如,图像 o1 和图像 o2,o2 是对 o1 经过缩放、旋转和平移后得到的,但是对
    二者应用 cv2.matchShapes()函数后,返回值的差较小。
  • 不相似图像 cv2.matchShapes()函数返回值的差较大。例如,图像 o1 和图像 o3 的差别较大,因此对二者应用 cv2.matchShapes()函数后,返回值的差也较大

所以当两图片的Hu 矩 二者的差值为0或者接近0 ,说明两个图片的轮廓基本上是一致的。


实验原图:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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

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

相关文章

C语言链表操作

目录 链表基本操作 删除重复元素 查找倒数第N个节点 查找中间节点 约瑟夫环 循环链表 合并有序链表 逆置链表 逆置链表(双向链表) 链表基本操作 //linklist.c#include "linklist.h" #include <stdlib.h>struct node *head NULL; struct node *tail…

React 18 state 状态更新函数

参考文章 把一系列 state 更新加入队列 设置组件 state 会把一次重新渲染加入队列。但有时可能会希望在下次渲染加入队列之前对 state 的值执行多次操作。为此&#xff0c;了解 React 如何批量更新 state 会很有帮助。 React 会对 state 更新进行批处理 在下面的示例中&…

Docker查看、创建、进入容器相关的命令

1.查看、创建、进入容器的指令 用-it指令创建出来的容器&#xff0c;创建完成之后会立马进入容器。退出之后立马关闭容器。 docker run -it --namec1 centos:7 /bin/bash退出容器&#xff1a; exit查看现在正在运行的容器命令&#xff1a; docker ps查看历史容器&#xff0…

docker小白第二天

centos上安装docker docker官网&#xff0c;docker官网&#xff0c;找到下图中的doc文档。 进入如下页面 选中manuals&#xff0c;安装docker引擎。 最终centos下的docker安装文档链接&#xff1a;安装文档链接. 具体安装步骤&#xff1a; 1、打开Centos&#xff0c;输入命…

【BASH】回顾与知识点梳理(十五)

【BASH】回顾与知识点梳理 十五 十五. 指令与文件的搜寻15.1 脚本文件名的搜寻which (寻找『执行档』) 15.2 文件档名的搜寻whereis (由一些特定的目录中寻找文件文件名)locate / updatedbfind与时间有关的选项与使用者或组名有关的参数与文件权限及名称有关的参数额外可进行的…

JVM垃圾回收

如何确定垃圾 对堆垃圾回收前的第一步就是要判断哪些对象已经死亡&#xff08;即不能再被任何途径使用的对象&#xff09; 引用计数法 这个方法就是为对象添加计数器来标识引用个数&#xff0c;计数器为 0 的对象就是不可能再被使用的。但是这种方法存在循环引用问题&#x…

布谷鸟配音:一站式配音软件

这是一款智能语音合成软件&#xff0c;可以快速将文字转换成语音&#xff0c;拥有多种真人模拟发音&#xff0c;可以选择不同男声、女声、童声&#xff0c;以及四川话、粤语等中文方言和外语配音&#xff0c;并且可对语速、语调、节奏、数字读法、多音字、背景音等进行全方位设…

less、sass的使用及其区别

CSS预处理器 CSS 预处理器是一种扩展了原生 CSS 的工具&#xff0c;它们添加了一些编程语言的特性&#xff0c;以便更有效地编写、组织和维护样式代码。预处理器允许开发者使用变量、嵌套、函数、混合等功能&#xff0c;从而使 CSS 更具可读性、可维护性和重用性&#xff0c;特…

学习笔记整理-JS-01-语法与变量

文章目录 一、语法与变量1. 初识JavaScript2. JavaScript的历史3. JavaScript与ECMAScript的关系4. JavaScript的体系5. JavaScript的语言风格和特性 二、语法1. JavaScript的书写位置2. 认识输出语句3. REPL环境&#xff0c;交互式解析器4. 变量是什么5. 重点内容 一、语法与变…

使用python快速搭建HTTP服务实现局域网网页浏览或文件传输

1.使用命令行&#xff08;CMD&#xff09;来快速搭建一个HTTP服务器 你可以借助Python的http.server模块。以下是在命令行中使用Python快速搭建HTTP服务器的步骤&#xff1a; 打开命令提示符&#xff08;CMD&#xff09;。 进入你想要共享文件的目录。使用 cd 命令来切换到目…

二、编写第一个 Spring MVC 程序

文章目录 一、编写第一个 Spring MVC 程序 一、编写第一个 Spring MVC 程序 代码示例 创建 maven 项目&#xff0c;以此项目为父项目&#xff0c;在父项目的 pom.xml 中导入相关依赖 <dependencies><dependency><groupId>junit</groupId><artifactI…

分支和循环语句(2)(C语言)

目录 do...while()循环 do语句的语法 do语句的特点 do while循环中的break和continue 练习 goto语句 do...while()循环 do语句的语法 do 循环语句; while(表达式); do语句的特点 循环至少执行一次&#xff0c;使用的场景有限&#xff0c;所以不是经常使用。 #inc…

【uniapp】uniapp自动导入自定义组件和设置分包:

文章目录 一、自动导入自定义组件&#xff1a;二、设置分包和预加载&#xff1a; 一、自动导入自定义组件&#xff1a; 【Volar 官网】https://github.com/vuejs/language-tools 二、设置分包和预加载&#xff1a; 【官方文档】https://uniapp.dcloud.net.cn/collocation…

【服务平台】Rancher运行和管理Docker和Kubernetes,提供管理生产中的容器所需的整个软件堆栈

Rancher是一个开源软件平台&#xff0c;使组织能够在生产中运行和管理Docker和Kubernetes。使用Rancher&#xff0c;组织不再需要使用一套独特的开源技术从头开始构建容器服务平台。Rancher提供了管理生产中的容器所需的整个软件堆栈。  完整软件堆栈 Rancher是供采用容器的团…

idea添加作者信息

idea添加作者信息 自定义作者信息idea添加作者信息自定义作者信息 自定义作者信息 idea添加作者信息 在idea中&#xff0c;经常会有这些波浪纹提示&#xff0c;放在上面之后会提示添加作者信息,点击添加作者信息后&#xff0c;但是不是自己想要的 这里提取的话好像没什么办法…

JavaWeb课程学习--Day01

HTML 建立css文件&#xff1a; css使用方式&#xff1a; <span>...</span>无语意包裹标签 css中的三种选择器&#xff1a; 注意&#xff1a;播放视音频时要留出播放空间 盒子模型&#xff1a; 表格标签&#xff1a; 以上表格&#xff1a; 表单标签&#xff1a; 表…

分布式 - 服务器Nginx:一小时入门系列之动静分离

文章目录 1. 动静分离的好处2. 分离静态文件3. 修改 Nginx 配置文件4. location 命令修饰符优先级 1. 动静分离的好处 Apache Tocmat 严格来说是一款java EE服务器&#xff0c;主要是用来处理 servlet请求。处理css、js、图片这些静态文件的IO性能不够好&#xff0c;因此&…

ROS学习--HelloWorld的实现(C++)

1.创建工作空间并初始化 mkdir -p 自定义空间名称/src cd 自定义空间名称 catkin_make上述命令&#xff0c;首先会创建一个工作空间以及一个 src 子目录&#xff0c;然后再进入工作空间调用 catkin_make命令编译。 2.进入 src 创建 ros 包并添加依赖 cd src catkin_create_pk…

苏纷享首届生态人脉会成功举办,纷享销客助力伙伴共同发展

近日&#xff0c;纷享销客&苏纷享成功举办了首届生态人脉会&#xff0c;该活动于8月3日下午在苏州东方之门举行。本次会议汇聚了来自近20家企业的销售精英&#xff0c;包括金蝶、泛微、夏谷、蚂蚁分工、创享、黑湖智造等众多知名企业。会议秉持着“建立生态、共同发展、深耕…

时间复杂度与空间复杂度的详解

目录 1.时间复杂度 2.时间复杂度计算例题 3.空间复杂度 1.时间复杂度 算法中的基本操作的执行次数&#xff0c;为算法的时间复杂度。 如何表达 时间复杂度&#xff1f; 大O的渐进表示法 实际中我们计算时间复杂度时&#xff0c;我们其实并不一定要计算精确的执行次数&#xf…