当前位置:网站首页>OpenCV 轮廓 —— 轮廓匹配
OpenCV 轮廓 —— 轮廓匹配
2022-08-09 16:52:00 【为为为什么】
一个跟轮廓相关的最常用到的功能是如何匹配多条轮廓。我们或许需要比较两条计算好的轮廓,或者比较一条轮廓和一个抽象模板。这两种情况都会在本文讨论。
矩
- 相关介绍
- 比较两条轮廓最简洁的方法之一是比较它们的轮廓矩。轮廓矩代表了一条轮廓、一幅图像、一组点集的某些高级特征。下面的所有讨论对轮廓、图像、点集都同样适用,简便起见,将它们统称为对象。矩的数值定义如下式:
在上式中, m_{p, q} 代表对象中所有像素的总和, 其中每个像素 x, y 的像素值都乘以因子 x^{p} y^{q} , 在 m_{00} 时, 这个因子等于 1 。.
- 因此若图像为二值图(例如,所有像素都等于0或者1),则 m_{00} 代表图像上所有值非零的区域。当处理轮廓时,结果是轮廓的长度。
- 将m_{10}和m_{01}相加再除以mo,能得到整个对象的平均x值和y值。
cv2.moments
计算多边形或光栅化形状的所有矩,最高可达三阶。 官方文档
- 仅适用于来自 Python 绑定的轮廓矩计算: 注意,输入数组的 numpy 类型应该是
np.int32或np.float32。 - 函数使用
cv2.moments(
array[, # 单通道2D图像
binaryImage] # 如果为真,所有非零的图像像素将被视为1。该参数仅用于图像。
) ->
retval # 矩结果- retval 包含多组矩:
矩名称 | 含义 |
|---|---|
m00 | 零阶矩 |
m10, m01 | 一阶矩 |
m20, m11, m02 | 二阶矩 |
m30, m12, m21, m03 | 三阶矩 |
mu20, mu11, mu02 | 二阶中心距 |
mu30, mu21, mu12, mu03 | 三阶中心距 |
nu20, nu11, nu02 | 二阶归一化中心矩 |
nu30, nu21, nu12, nu03 | 三阶归一化中心矩 |
- 示例代码
img = 255 - mt.cv_rgb_imread('conc.png', gray=True)
contours, hierarchy = cv2.findContours(img, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
res = np.zeros_like(img)
cv2.drawContours(res, [contours[0]], -1, [200], 3)
mom_res = cv2.moments(res, True)
-->
mom_res
{
'm00':5991.0
'm10':1325055.0
'm01':1749761.0
'm20':344323579.0
'm11':349473277.0
'm02':669951437.0
'm30':96933608139.0
'm21':85341328483.0
'm12':127841748675.0
'm03':288309060455.0
'mu20':51255518.07110667
'mu11':-37528819.78768152
'mu02':158907611.74194622
'mu30':-1894707829.496994
'mu21':1377304228.770937
'mu12':1587438731.2496796
'mu03':-182940816.065979
'nu20':1.428045313703228
'nu11':-1.0456016687269127
'nu02':4.4273724820231575
'nu30':-0.682015038155167
'nu21':0.49577152820752285
'nu12':0.571411100966244
'nu03':-0.06585099069469698
}- 计算第二个 Hu 不变矩测试归一化中心矩:
- 公式为:
- 示例代码:
def h2(mom):
v20 = mom['nu20']
v02 = mom['nu02']
v11 = mom['nu11']
h2 = (v20 + v02) ** 2 + 4 * (v11 ** 2)
return h2
img = 255 - mt.cv_rgb_imread('conc.png', gray=True)
contours, hierarchy = cv2.findContours(img, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
res = np.zeros_like(img)
cv2.drawContours(res, [contours[0]], -1, [200], -1)
another_res = mt.image_resize(np.rot90(res), factor=0.5)
mom_res = cv2.moments(res, True)
mom_another_res = cv2.moments(another_res, True)
h2_1 = h2(mom_res)
h2_2 = h2(mom_another_res)
PIS([res, str(h2_1)], [another_res, str(h2_2)])Hu 矩
cv2.HuMoments
函数用于计算 Hu 矩: 官方代码
- 函数使用
cv2.HuMoments(
moments[, # cv2.moments 函数的输出结果
hu]
) ->
hu # 输出 7 个 Hu 不变矩- 示例代码
img = 255 - mt.cv_rgb_imread('conc.png', gray=True)
contours, hierarchy = cv2.findContours(img, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
res = np.zeros_like(img)
cv2.drawContours(res, [contours[0]], -1, [200], -1)
another_res = mt.image_resize(np.rot90(res), factor=0.5)
mom_res = cv2.moments(res, True)
mom_another_res = cv2.moments(another_res, True)
hu_res = cv2.HuMoments(mom_res)
hu_another_res = cv2.HuMoments(mom_another_res)
-->
hu_res
array([[2.65472790e-01],
[3.67973951e-02],
[4.31746085e-03],
[1.65053925e-03],
[4.40583128e-06],
[3.16616604e-04],
[4.73966676e-08]])
hu_another_res
array([[2.65294556e-01],
[3.67252753e-02],
[4.27103909e-03],
[1.62915379e-03],
[4.29714551e-06],
[3.12207937e-04],
[5.03721607e-08]])使用Hu矩进行匹配
- 我们想要使用Hu矩比较两个物体,并判定它们是否相似。对“相似”的定义可能有很多。为了使比较过程变得简单,OpenCV的函数
cv2.matchShapes允许我们简单提供两个物体,然后计算它们的矩,并根据我们提供的标准进行比较。
cv2.matchShapes
该函数比较两个形状,所有三个实现的方法都使用 Hu 不变量。 官方文档
- 函数使用
cv2.matchShapes(
contour1, # 第一个轮廓或灰度图像。
contour2, # 第二轮廓或灰度图像。
method, # 比对方法
parameter # 方法参数(OpenCV 4.5.5 暂时还不支持)
) ->
retvalmethod:ShapeMatchModes
- A, B 分别表示两个输入的物体轮廓
- 其中 h_{i}^{A}, h_{i}^{B} 为 A,B 的 Hu 不变矩
- 示例代码
img = 255 - mt.cv_rgb_imread('conc.png', gray=True)
contours, hierarchy = cv2.findContours(img, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
res1 = np.zeros_like(img)
res2 = np.zeros_like(img)
cv2.drawContours(res1, [contours[0]], -1, [200], -1)
cv2.drawContours(res2, [contours[6]], -1, [200], -1)
another_res = mt.image_resize(np.rot90(res1), factor=0.5)
match_res1 = cv2.matchShapes(res1, another_res, cv2.CONTOURS_MATCH_I1, None)
match_res2 = cv2.matchShapes(res1, res2, cv2.CONTOURS_MATCH_I1, None)
PIS([res1, 'source img'], [another_res, f"match score {format(match_res1, '.3f')}"], [res2, f"match score {format(match_res2, '.3f')}"])利用形状场景方法比较轮廓
OpenCV 努力提供比矩匹配更好的形状匹配算法
https://docs.opencv.org/4.5.5/d1/d85/group__shape.html#ga1d058c5d00f6292da61422af2f3f4adc
- 在 OpenCV 4.5.5 中还没有实现,有传说在 3.5 的版本中有相关函数
源码
https://github.com/zywvvd/Python_Practise/tree/master/OpenCV/Chapter 14
参考资料
- 《学习OpenCV》 第十四章
边栏推荐
猜你喜欢

如何在 PC 机上测试移动端的网页?

重谈联想5G编码投票事件

What is test development and why is it so popular now?

Logic unauthorized and horizontal and vertical unauthorized payment tampering, verification code bypass, interface

【Pycharm好用功能】

Can't install the Vmware virtual machine on the Ark Kai server?

方舟:生存进化开服务器端口映射教程

WinForm(四)一种实现登录的方式

一键生成 API 文档的妙招

动手学深度学习_全卷积网络 FCN
随机推荐
What you should know about futures account opening
Discuz!论坛程序安装+模板配置教程
最新!2022版新员工基础安全知识教育培训PPT,企业拿去直接用
AlphaControls 控件 TsPanel TsGroupBox 块与组的结合
基于CAP组件实现补偿事务与幂等性保障
基于ABP和Magicodes实现Excel导出操作
[Pycharm easy to use function]
【代码审计】——PHP项目类RCE及文件包含下载删除
Discuz! Forum program installation + template configuration tutorial
How to adjust futures account opening process and handling fee
字节也开始缩招了...
Jenkins deploys services to remote servers using pipelines
LINE Verda Programming Contest (AtCoder Beginner Contest 263) A~E 题解
What platform is EPIC?
逻辑越权和水平垂直越权支付篡改,验证码绕过,接口
怎样选择一个好的SaaS知识库工具?
【工业数字化大讲堂 第二十一期】企业数字化能碳AI管控平台,特邀技术中心总经理 王勇老师分享,8月11日(周四)下午4点
【ROS2原理9】 QoS - 截止日期、活跃度和寿命
如何在 PC 机上测试移动端的网页?
About the common Hook encapsulation of DOM (2)