Python-OpenCV中的图像处理-图像轮廓

Python-OpenCV中的图像处理-图像轮廓

  • 轮廓
    • 什么是轮廓
    • 查找轮廓
    • 绘制轮廓
  • 轮廓特征
    • 图像的矩
    • 轮廓面积
    • 轮廓周长(弧长)
    • 轮廓近似
    • 凸包
    • 轮廓边界矩形

轮廓

什么是轮廓

轮廓可以简单认为成将连续的点(连着边界)连在一起的曲线,具有相同的颜色或者灰度。轮廓在形状分析和物体的检测和识别中很有用。

  • 为了更加准确,要使用二值化图像。在寻找轮廓之前,要进行阈值化处理或者 Canny 边界检测。
  • 查找轮廓的函数会修改原始图像。如果你在找到轮廓之后还想使用原始图像的话,你应该将原始图像存储到其他变量中。
  • 在 OpenCV 中,查找轮廓就像在黑色背景中超白色物体。你应该记住,要找的物体应该是白色而背景应该是黑色。

查找轮廓

函数 cv2.findContours() 有三个参数,第一个是输入图像,第二个是轮廓检索模式,第三个是轮廓近似方法。返回值有三个,第一个是图像,第二个是轮廓,第三个是(轮廓的)层析结构。轮廓(第二个返回值)是一个 Python列表,其中存储这图像中的所有轮廓。每一个轮廓都是一个 Numpy 数组,包含对象边界点( x, y)的坐标。

ret, thresh = cv2.threshold(imgray, 127, 255, 0)
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

cv2.CHAIN_APPROX_NONE:储存所有的边界点(点数很多)
cv2.CHAIN_APPROX_SIMPLE:储存所有的近似直线点(点数很少)

绘制轮廓

函数 cv2.drawContours() 可以被用来绘制轮廓。它可以根据你提供的边界点绘制任何形状。它的第一个参数是原始图像,第二个参数是轮廓,一个 Python 列表。第三个参数是轮廓的索引(在绘制独立轮廓是很有用,当设置为 -1 时绘制所有轮廓)。接下来的参数是轮廓的颜色和厚度等。

  • 绘制所有轮廓 image = cv2.drawContours(img, contours, -1, (0, 255, 0), 3)
  • 绘制指定轮廓 image = cv2.drawContours(img, contours, 0, (0, 255, 0), 3)
import numpy as np
import cv2# 轮廓:连着边界连续的点连在一起的曲线,具有相同的颜色或者灰度。
# 轮廓在形状分析和物体的检测和识别中很有用。# 1.为了准确,要使用二值化图像。需要进行阀值化处理或Canny边界检测。
# 2.查找轮廓的函数会修改元素图像。
# 3.在OpenCV中,查找轮廓就像在黑色背景中找白色物体。# cv2.findContours() # 查找轮廓
# cv2.drawContours() # 绘制轮廓img = cv2.imread('./resource/image/opencv-logo2.png')
imgcp = cv2.imread('./resource/image/opencv-logo2.png')
imgray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)ret, thresh = cv2.threshold(imgray, 127, 255, 0)
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# contours 轮廓
# hierarchy 层次# image = cv2.drawContours(img, contours, -1, (0, 255, 0), 3) # 绘制所有轮廓
image = cv2.drawContours(img, contours, 3, (0, 255, 0), 3) # 绘制第4个轮廓
print(cv2.getVersionString())
print(type(contours))
print(len(contours))
cv2.imshow('img', imgcp)
cv2.imshow('image', image)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述

轮廓特征

  • 查找轮廓的不同特征:矩、面积、周长(也叫弧长)、重心、边界框等

图像的矩

  • 在图像处理、计算机视觉和相关领域,图像矩是图像像素强度的某个特定的加权平均值(矩),或者是这种矩的函数,通常被选择为具有某种吸引人的特性或解释。图像矩在分割后对描述物体很有用。通过图像矩找到的图像的简单属性包括面积(或总强度)、其中心点和关于其方向的信息。
  • 图像的矩可以帮助我们计算图像的质心,面积等。
  • 函数cv2.moments()计算得到矩,返回一个字典。
    根据矩值可以计算对象的重心:
    C x = M 10 M 00 , C y = M 01 M 00 C_x=\frac{M_{10}}{M_{00}},C_y=\frac{M_{01}}{M_{00}} Cx=M00M10,Cy=M00M01
import numpy as np
import cv2
from matplotlib import pyplot as plt# 矩:图像的矩可以帮助我们计算图像的质心,面积等
# cv2.moments() 计算得到矩,以一个字典形式返回# 读取图像
img = cv2.imread('./resource/opencv/image/box2.png', cv2.IMREAD_COLOR)
img1 = img.copy()
gray = cv2.imread('./resource/opencv/image/box2.png', cv2.IMREAD_GRAYSCALE)# 阀值处理
(ret, thresh) = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)# 查找所有轮廓
(contours, hierarchy) = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
print('找到轮廓数:',len(contours))# 计算轮廓索引为0的图像矩
cnt = contours[0]
M = cv2.moments(cnt)
print('moments()计数结果M:',M)# 计算重心(质点)
#根据这些矩值计算出对象的重心:
# Cx = M10/M00
# Cy = M01/M00
cx = int(M['m10']/M['m00'])
cy = int(M['m01']/M['m00'])
print(cx,cy)# 绘制轮廓
cv2.drawContours(img1, contours, 0, (0, 255, 0), 2)# 绘制质点
cv2.circle(img1, (cx, cy), 5, (255, 0, 0), -1)plt.subplot(121), plt.imshow(img)
plt.subplot(122), plt.imshow(img1)
plt.show()

程序运行结果:
找到轮廓数: 1
moments()计数结果M: {‘m00’: 10032.0, ‘m10’: 1294128.0, ‘m01’: 1284096.0, ‘m20’: 177807168.0, ‘m11’: 165648384.0, ‘m02’: 170838272.0, ‘m30’: 25740205920.0, ‘m21’: 22759317504.0, ‘m12’: 22038137088.0, ‘m03’: 23524638720.0, ‘mu20’: 10864656.0, ‘mu11’: 0.0, ‘mu02’: 6473984.0, ‘mu30’: 0.0, ‘mu21’: 0.0, ‘mu12’: 0.0, ‘mu03’: 0.0, ‘nu20’: 0.10795454545454546, ‘nu11’: 0.0, ‘nu02’: 0.06432748538011696, ‘nu30’: 0.0, ‘nu21’: 0.0, ‘nu12’: 0.0, ‘nu03’: 0.0}
质点: 129 128

下图红色圆点是质点,绿色框是轮廓:
在这里插入图片描述

轮廓面积

  • 轮廓的面积可以使用函数 cv2.contourArea() 计算得到,也可以使用矩
    ( 0 阶矩), M[‘m00’]。
  • area = cv2.contourArea(cnt)
import numpy as np
import cv2
from matplotlib import pyplot as pltimg = cv2.imread('./resource/opencv/image/box2.png', cv2.IMREAD_COLOR)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)(ret, thresh) = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
(contours, hierarchy) = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)cnt = contours[0]
M = cv2.moments(cnt)
area = cv2.contourArea(cnt)
print(cnt)
print(area)
print(M['m00'])

[[[ 72 84]]
[[ 72 172]]
[[186 172]]
[[186 84]]]
10032.0
10032.0

轮廓周长(弧长)

  • 也被称为弧长。可以使用函数 cv2.arcLength() 计算得到。这个函数的第二参数可以用来指定对象的形状是闭合的( True),还是打开的(一条曲线)。
  • perimeter = cv2.arcLength(cnt,True)
import numpy as np
import cv2img = cv2.imread('./resource/opencv/image/box2.png', cv2.IMREAD_COLOR)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)(ret, thresh) = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
(contours, hierarchy) = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)# 第一个参数轮廓,第二次参数形状闭合的(True),还是打开的一条曲线
perimeter = cv2.arcLength(contours[0], True)
print(perimeter) #404.0

轮廓近似

  • 将轮廓形状近似到另外一种由更少点组成的轮廓形状,新轮廓的点的数目由我们设定的准确度来决定。使用的Douglas-Peucker算法,维基百科获得更多此算法的细节。
  • 假设要在一幅图像中查找一个矩形,但是由于图像的种种原因,我们不能得到一个完美的矩形,而是一个“坏形状”。现在你就可以使用这个函数来近似这个形状()了。
  • epsilon = 0.1*cv2.arcLength(cnt,True)
    approx = cv2.approxPolyDP(cnt,epsilon,True)
import numpy as np
import cv2
from matplotlib import pyplot as pltimg = cv2.imread('./resource/opencv/image/approx2.jpg', cv2.IMREAD_COLOR)
img_draw1 = img.copy()
img_draw2 = img.copy()gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
(ret, thresh) = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
(contours, hierarchy) = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)# epsilon=10%
epsilon01 = 0.1 * cv2.arcLength(contours[0], True)
# epsilon=1%
epsilon001  = 0.01 * cv2.arcLength(contours[0], True)
approx_01 = cv2.approxPolyDP(contours[0], epsilon01, True)
approx_001 = cv2.approxPolyDP(contours[0], epsilon001, True)cv2.drawContours(img_draw1, approx_01, -1, (0, 0, 255), 5)
cv2.drawContours(img_draw2, approx_001, -1, (0, 0, 255), 5)plt.subplot(131), plt.imshow(img), plt.title('original')
plt.subplot(132), plt.imshow(img_draw1), plt.title('epsilon=10%')
plt.subplot(133), plt.imshow(img_draw2), plt.title('epsilon=1%')
plt.show()

在这里插入图片描述

凸包

轮廓边界矩形

import numpy as np
import cv2
from matplotlib import pyplot as plt# 轮廓边界矩形# 读取图像
img = cv2.imread('./resource/image/opencv-logo2.png', cv2.IMREAD_COLOR)# 转成灰度
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 图像阀值处理 
ret, thresh = cv2.threshold(img_gray, 127, 255, 0)# 查找轮廓
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)# 绘制轮廓边界矩形
for i in range(0, len(contours)):x, y, w, h = cv2.boundingRect(contours[i])print(x,y,w,h)img = cv2.rectangle(img, (x,y), (x+w, y+h), (0,255,255), 3)cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述

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

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

相关文章

Flutter系列文章-实战项目

在本篇文章中,我们将通过一个实际的 Flutter 应用来综合运用最近学到的知识,包括保存到数据库、进行 HTTP 请求等。我们将开发一个简单的天气应用,可以根据用户输入的城市名获取该城市的天气信息,并将用户查询的城市列表保存到本地…

redis的缓存更新策略

目录 三种缓存更新策略 业务场景: 主动更新的三种实现 操作缓存和数据库时有三个问题 1.删除缓存还是更新缓存? 2.如何保证缓存与数据库的操作的同时成功或失败? 3.先操作缓存还是先操作数据库? 缓存更新策略的最佳实践方案&am…

【效率提升—Python脚本】根据Verilog文件自动生成tb文件

文章目录 Verilog端口文件(仅做示范用)对应的tb文件相应代码 在数字IC设计过程中,根据顶层生成testbench时存在很多重复性工作,因此为了提高工作效率,特地开发此脚本。 Verilog端口文件(仅做示范用&#xf…

JVM深入 —— JVM的体系架构

前言 能否真正理解JVM的底层实现原理是进阶Java技术的必由之路,Java通过JVM虚拟机的设计使得Java的延拓性更好,平台无关性是其同时兼顾移动端和服务器端开发的重要特性。在本篇文章中,荔枝将会仔细梳理JVM的体系架构和理论知识,希…

C语言第十课----------------扫雷----------数组的经典练手题

作者前言 🎂 ✨✨✨✨✨✨🍧🍧🍧🍧🍧🍧🍧🎂 🎂 作者介绍: 🎂🎂 🎂…

软件验收测试包括几种类型?验收测试报告有什么好处?

在软件开发中,验收测试是软件项目在开发完成后进行的最后一项测试工作。它是确认软件是否满足预期要求,并准备将软件交付用户的核心环节,它可以确保软件的质量和功能符合用户的需求和期望。 一、软件验收测试的类型 软件验收测试可以分为多…

鸿鹄工程项目管理系统em Spring Cloud+Spring Boot+前后端分离构建工程项目管理系统em

​ Java版工程项目管理系统 Spring CloudSpring BootMybatisVueElementUI前后端分离 功能清单如下: 首页 工作台:待办工作、消息通知、预警信息,点击可进入相应的列表 项目进度图表:选择(总体或单个)项目…

Sencha Ext.NET Crack 快速应用程序的正确工具集

Sencha Ext.NET Crack 快速应用程序的正确工具集 Sencha Ext.NET是一个高级的ASP.NET核心组件框架,它包含了强大的跨浏览器Sencha Ext JS库。通过140多个预构建和专业测试的UI组件实现企业级性能和生产效率。Sencha Ext.NET使用尖端的Web技术创建功能强大的Web应用程…

1、如何实现两台电脑之间数据相互读写

一、确保两台电脑在同一个局域网中,可以使用网线【动态配置】进行两台电脑互连。 二、静态配置: 将IP地址和网关设为192.168.0.1,目的是让这台电脑做另一台电脑的网关,子网掩码一点击会自动添加。第二台电脑同样打开设置,此处IP地…

JUC并发编程(JUC核心类、TimeUnit类、原子操作类、CASAQS)附带相关面试题

目录 1.JUC并发编程的核心类 2.TimeUnit(时间单元) 3.原子操作类 4.CAS 、AQS机制 1.JUC并发编程的核心类 虽然java中的多线程有效的提升了程序的效率,但是也引发了一系列可能发生的问题,比如死锁,公平性、资源管理…

python基础3——流程控制

文章目录 一、操作符1.1 比较操作符1.2 逻辑操作符1.3 成员操作符1.4 身份操作符 二、流程控制2.1 条件判断2.2 循环语句2.2.1 for循环2.2.2 while循环 2.3 continue与break语句2.4 文件操作函数 三、函数3.1 定义函数3.2 作用域3.3 闭包3.4 函数装饰器3.5 内建函数 一、操作符…

vuejs 设计与实现 - 渲染器的设计

渲染器与响应式系统的结合 本节,我们暂时将渲染器限定在 DOM 平台。既然渲染器用来渲染真实 DOM 元素,那么严格来说,下面的函数就是一个合格的渲染器: // 渲染器: function renderer(domString, container) {container.innerHTM…