OpenCV基础知识(8)— 图形检测

前言:Hello大家好,我是小哥谈。图形检测是计算机视觉的一项重要功能。通过图形检测可以分析图像中可能存在的形状,然后对这些形状进行描绘,例如搜索并绘制图像的边缘,定位图像的位置,判断图像中有没有直线、有没有圆形等。虽然图形检测涉及非常深奥的数学算法,但是OpenCV已经将这些算法封装成了简单的方法,开发者只要学会如何调用方法、如何调整参数即可很好的实现检测功能。本节课就介绍如何检测图像的形状、图像所占的区域,以及如何查找图像中出现的几何图形等。🌈

 前期回顾:

         史上最全OpenCV常用方法及使用说明汇总,建议收藏!

         OpenCV基础知识(1)— OpenCV概述

         OpenCV基础知识(2)— 图像处理的基本操作

         OpenCV基础知识(3)— 图像数字化基础(像素、色彩空间)

         OpenCV基础知识(4)— 绘制图形

         OpenCV基础知识(5)— 几何变换

         OpenCV基础知识(6)— 滤波器

         OpenCV基础知识(7)— 腐蚀与膨胀

         目录

🚀1.图像的轮廓 

🚀2.轮廓的拟合

💥💥2.1 矩形包围框

💥💥2.2 圆形包围框

🚀3.Canny边缘检测

🚀4.霍夫变换

💥💥4.1 直线检测

💥💥4.2 圆环检测

🚀5.总结

🚀1.图像的轮廓 

轮廓,是指图像中图形或物体的外边缘线条。简单的几何图形轮廓是由平滑的线构成的,容易识别,但不规则的轮廓可能有许多个点构成,识别起来比较困难。

OpenCV提供的findContours()方法可以通过计算图像梯度来判断出图像的边缘,然后将边缘的点封装成数组返回。🌳

findContours()方法的语法格式如下:

contours,hierarchy = cv2.findContours(image,mode,method)

参数说明:

image:被检测的图像,必须是8位单通道二值图像。如果原始图像是彩色图像,必须转为灰度图像,并经过二值化阈值处理。

mode:轮廓的检索模式,具体值详见表。

参数值含义
cv2.RETR_EXTERNAL只检测外轮廓
CV2.RETR_LIST检测所有轮廓,但不建立层次关系。
CV2.RETR_CCOMP检测所有轮廓,并建立两级层次关系。
CV2.RETR_TREE检测所有轮廓,并建立树状结构的层次关系。

method:检测轮廓时使用的方法,具体值详见表。

参数值含义
cv2.CHAIN_APPROX_NONE储存轮廓上的所有点
cv2.CHAIN_APPROX_SIMPLE只保存水平、垂直或对角线轮廓的端点
CV2.CHAIN_APPROX_TC89_L1Ten-Chin1近似算法的一种
CV2.CHAIN_APPROX_TC89_KCOSTen-Chin1近似算法的一种

返回值说明:

contours:检测出的所有轮廓,list类型,每一个元素都是某个轮廓的像素坐标数组。

hierarchy:轮廓之间测层次关系。

通过findContours()方法找到图像轮廓之后,为了方便开发人员观测,最好能把轮廓画出来,于是OpenCV方法提供了drawContours()方法专门用来绘制这些轮廓。🌳

drawContours()方法的语法如下:

image = cv2.drawContours(image,contours,contourIdx,color,thickness,lineType,hierarchy,maxLevel,offse)

参数说明:

image:被绘制轮廓的原始图像,可以是多通道图像。

contours:findContours()方法得出的轮廓列表。

contourIdx:绘制轮廓的索引,如果为-1则绘制所有轮廓。

color:绘制颜色,使用RGB格式。

thickness:可选参数,画笔的粗细程度,如果该值为-1则绘制实心轮廓。

lineType:可选参数,绘制轮廓的线型。

hierarchy:可选参数,findContours()方法得出的层次关系。

maxLevel:可选参数,绘制轮廓的层次深度,最深绘制第maxLevel层。

offse:可选参数,偏移量,可以改变绘制结果的位置。

返回值说明:

image:同参数中的image,方法执行后原始图像中就包含绘制的轮廓了,可以不使用此返回值保存结果。

案例1:

绘制几何图像的轮廓,具体代码如下:

import cv2
img = cv2.imread("shape1.png")  # 读取原图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 彩色图像转为变成单通道灰度图像
t, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)  # 灰度图像转为二值图像
# 检测图像中出现的所有轮廓,记录轮廓的每一个点
contours, hierarchy = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
# 绘制所有轮廓,宽度为5,颜色为红色
cv2.drawContours(img, contours, -1, (0, 0, 255), 5)
cv2.imshow("img", img)  # 显示绘制结果
cv2.waitKey()  # 按下任何键盘按键后
cv2.destroyAllWindows()  # 释放所有窗体

运行效果如图所示:

案例2:

绘制花朵的轮廓。

绘制之前首先要降低图像中的噪声干扰,先进行滤波处理,再将图像处理成二值灰度图像,并检测出轮廓,再利用绘制轮廓的方法在原始图像中绘制轮廓🌺

具体代码如下:

import cv2
img = cv2.imread("flower.jpg")  # 读取原图
cv2.imshow("img", img)  # 显示原图
img = cv2.medianBlur(img, 5)  # 使用中值滤波去除噪点
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 原图从彩图变成单通道灰度图像
t, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)  # 灰度图像转化为二值图像
cv2.imshow("binary", binary)  # 显示二值化图像
# 获取二值化图像中的轮廓极轮廓层次数据
contours, hierarchy = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
cv2.drawContours(img, contours, -1, (0, 0, 255), 2)  # 在原图中绘制轮廓
cv2.imshow("contours", img)  # 显示绘有轮廓的图像
cv2.waitKey()  # 按下任何键盘按键后
cv2.destroyAllWindows()  # 释放所有窗体

运行效果如图所示:


🚀2.轮廓的拟合

拟合,是指将平面上的一系列点,用一条光滑的曲线连接起来。轮廓的拟合就是将凹凸不平的轮廓用平整的几何图形体现出来。

下面就为大家介绍如何按照轮廓绘制矩形包围框和圆形包围框。🌴

💥💥2.1 矩形包围框

矩形包围框是指图像轮廓的最小矩形边界。OpenCV提供的boundingRect()方法可以自动计算出轮廓最小矩形边界的坐标和宽高。🐳

boundingRect()方法的语法如下:

retval = cv2.boundingRect(array)

参数说明:

array:轮廓数组

返回值说明:

retval:元组类型,包含四个整数值,分别是最小矩形包围框左上角顶点的横坐标、左上角顶点的纵坐标、矩形的宽和矩形的高。所以也可以写成x,y,w,h = cv2.boundingRect(array)的形式。

案例:

为爆炸图形绘制矩形包围框。具体代码如下:

import cv2
img = cv2.imread("shape2.png")  # 读取原图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 从彩色图像变成单通道灰度图像
# 将灰度图像进行二值化阈值处理
t, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
# 获取二值化图像中的轮廓极轮廓层次数据
contours, hierarchy = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
x, y, w, h = cv2.boundingRect(contours[0])  # 获取第一个轮廓的最小矩形边框,记录坐标和宽高
cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 255), 2)  # 绘制红色矩形
cv2.imshow("img", img)  # 显示绘制结果
cv2.waitKey()  # 按下任何键盘按键后
cv2.destroyAllWindows()  # 释放所有窗体

运行效果如图所示:

💥💥2.2 圆形包围框

圆形包围框与矩形包围框同理,是图像轮廓的最小圆形边界。OpenCV提供的minEnclosingCircle()方法可以自动计算出轮廓最小圆形边界的圆心和半径。

minEnclosingCircle()方法的语法格式如下:

center,radius = cv2.minEnclosingCircle(points)

参数说明:

points:轮廓数组

返回值说明:

center:元组类型,包含两个浮点值,是最小圆形包围框圆心的横坐标和纵坐标。

radius:浮点类型,最小圆形包围框的半径。

案例:

为爆炸图形绘制圆形包围框。具体代码如下:

import cv2
img = cv2.imread("shape2.png")  # 读取原图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 从彩色图像变成单通道灰度图像
# 将灰度图像进行二值化阈值处理
t, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
# 获取二值化图像中的轮廓极轮廓层次数据
contours, hierarchy = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
center, radius = cv2.minEnclosingCircle(contours[0])  # 获取最小圆形边框的圆心点和半径
x = int(round(center[0]))  # 圆心点横坐标转为近似整数
y = int(round(center[1]))  # 圆心点纵坐标转为近似整数
cv2.circle(img, (x, y), int(radius), (0, 0, 255), 2)  # 绘制圆形
cv2.imshow("img", img)  # 显示绘制结果
cv2.waitKey()  # 按下任何键盘按键后
cv2.destroyAllWindows()  # 释放所有窗体

 运行效果如图所示:


🚀3.Canny边缘检测

Canny边缘检测算法是John F.Canny 于1986年开发出来的一个多级边缘检测算法,该算法根据像素的梯度变化寻找图像边缘,最终可以绘制出十分精细的二值边缘图像。🌿

OpenCV将Canny边缘检测算法封装在Canny()方法中,该方法的语法如下:

edgrs = cv2.Canny(image,threshold1,threshold2,apertureSize,L2gradient)

参数说明:

image:检测的原始图像

threshold1:计算过程中使用的第一个阈值,可以是最小阈值,也可以是最大阈值,通常用来设置最小阈值。

threshold2:计算过程中使用的第二个阈值,通常用来设置最大阈值。

apertureSize:可选参数,Sobel算子的孔径大小。

L2gradient:可选参数,计算图像梯度的标识,默认值为False。值为True时会采用更精准的算法进行计算。

返回值说明:

edges:计算后得出的边缘图像,是一个二值灰度图像。

说明:♨️♨️♨️

在开发过程中可以通过调整最小阈值和最大阈值来控制边缘检测的精细程度。当两个阈值都较小的时候,会检测出更多的细节;当两个阈值都较大的时候,会忽略较多的细节。

案例:

使用Canny算法检测美女图像,具体代码如下:

import cv2
img = cv2.imread("1.webp")  # 读取原图
r1 = cv2.Canny(img, 10, 50);  # 使用不同的阈值进行边缘检测

cv2.imshow("img", img)  # 显示原图
cv2.imshow("r1", r1)  # 显示边缘检测结果
cv2.waitKey()  # 按下任何键盘按键后
cv2.destroyAllWindows()  # 释放所有窗体

运行效果如图所示:


🚀4.霍夫变换

 霍夫变换是一种特征检测,通过算法识别图像的特征,从而判断出图像中的特殊形状,例如直线和圆。下面就为大家介绍如何检测图像中的直线和圆。

💥💥4.1 直线检测

霍夫直线变换是通过霍夫坐标系的直线与笛卡尔坐标系的点之间的映射关系来判断图像中的点是否构成直线。OpenCV将此封装成了两个方法,分别是cv2.HoughLines()方法和

cv2.HoughLinesP()方法,前者用于检测无线延长的直线,后者用于检测线段。🌼

本节就介绍比较常用的HoughLinesP()方法

HoughLinesP()方法名称最后有一个大写的P,该方法只能检测二值灰度图像,也就是只有两种像素值的黑白图像。方法最后会把找出的所有线段的两个端点坐标保存成一个数组

HoughLinesP()方法的语法如下:

lines = cv2.HoughLinesP(image,rho,theta,threshold,minLineLength,maxLineGap)

参数说明:

image:检测的原始图像

rho:检测直线使用的半径步长,值为1时,表示检测所有可能的半径步长。

theta:搜索直线的角度,值为π/180时,表示检测的所有角度。

threshold:阈值,该值越小,检测的直线就越多。

minLineLength:线段的最小长度,小于该长度的直线不会记录到结果中。

maxLineGap:线段之间的最小距离。

返回值说明:

lines:一个数组,元素为所有检测出的线段,每个线段也是一个数组,内容为线段两个端点的横纵坐标,格式为[[[x1,y1,x2,y2],[x1,y1,x2,y2]]]。

说明:♨️​​​​​​​♨️​​​​​​​♨️

使用该方法前需要先为原始图像进行降噪处理,否则会影响检测结果。

案例:

检测笔图像中出现的直线,具体代码如下:

import cv2
import numpy as np

img = cv2.imread("pen.jpg")  # 读取原图
o = img.copy()  # 复制原图
o = cv2.medianBlur(o, 5)  # 使用中值滤波进行降噪
gray = cv2.cvtColor(o, cv2.COLOR_BGR2GRAY)  # 从彩色图像变成单通道灰度图像
binary = cv2.Canny(o, 50, 150)  # 绘制边缘图像
# 检测直线,精度为1,全角度,阈值为15,线段最短100,最小间隔为18
lines = cv2.HoughLinesP(binary, 1, np.pi / 180, 15, minLineLength=100, maxLineGap=18)
for line in lines:  # 遍历所有直线
    x1, y1, x2, y2 = line[0]  # 读取直线两个端点的坐标
    cv2.line(img, (x1, y1), (x2, y2), (0, 0, 255), 2)  # 在原始图像上绘制直线
cv2.imshow("canny", binary)  # 显示二值化边缘图案
cv2.imshow("img", img)  # 显示绘制结果
cv2.waitKey()  # 按下任何键盘按键后
cv2.destroyAllWindows()  # 释放所有窗体

运行效果如图所示:

💥💥4.2 圆环检测

霍夫圆环变换的原理与霍夫直线变换类似。OpenCV提供的HoughCircle()方法用于检测图像中的圆,该方法在检测过程中进行两轮筛选:第一轮筛选会找出可能的是圆的圆心坐标,第二轮筛选会计算出这些圆心坐标可能的对应的半径长度。方法最后会将圆心坐标和半径长度封装成一个浮点型数组。🍃

HoughCircle()方法的语法格式如下:

circles = cv2.HoughCircle(image,method,dp,minDist,param1,param2,minRadius,maxRadius)

参数说明:

image:检测的原始图像

method:检测方法

dp:累加器分辨率与原始图像分辨率之比的倒数。值为1时,累加器与原始图像具有相同的分辨率;值为2时,累加器的分辨率为原始图像的1/2。通常使用1作为参数。

minDist:圆心之间的最小距离

param1:可选参数,Canny边缘检测使用的最大阈值。

param2:可选参数,检测圆环结果的投票数。第一轮筛选时投票数超过该值的圆才会进入第二轮筛选。值越大,检测出的圆越小,但越精准。

minRadius:可选参数,圆的最小半径。

maxRadius:可选参数,圆的最大半径。

返回值说明:

circles:一个数组,元素为所有检测出的圆,每个圆也是一个数组,内容为圆心的横、纵坐标和半径长度,格式为[[[x1,y1,r1],[x2,y2,r2]]]。

说明:♨️​​​​​​​♨️​​​​​​​♨️

使用该方法前需要先为原始图像进行降噪处理,否则会影响检测结果。

案例:

绘制硬币图像的圆环和对应圆心,具体代码如下:

import cv2
import numpy as np

img = cv2.imread("coin.jpg")  # 读取原图
o = img.copy()  # 复制原图
o = cv2.medianBlur(o, 5)  # 使用中值滤波进行降噪
gray = cv2.cvtColor(o, cv2.COLOR_BGR2GRAY)  # 从彩色图像变成单通道灰度图像
# 检测圆环,圆心最小间距为70,Canny最大阈值为100,投票数超过25。最小半径为10,最大半径为50
circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1, 70, param1=100, param2=25, minRadius=10, maxRadius=50)
circles = np.uint(np.around(circles))  # 将数组元素四舍五入成整数
for c in circles[0]:  # 遍历圆环结果
    x, y, r = c  # 圆心横坐标、纵坐标和圆半径
    cv2.circle(img, (x, y), r, (0, 0, 255), 3)  # 绘制圆环
    cv2.circle(img, (x, y), 2, (0, 0, 255), 3)  # 绘制圆心
cv2.imshow("img", img)  # 显示绘制结果
cv2.waitKey()  # 按下任何键盘按键后
cv2.destroyAllWindows()  # 释放所有窗体

运行效果如图所示:


🚀5.总结

总结:

🍀(1)图像的轮廓:先对图像做二值化处理,cv2.findContours()检测轮廓,cv2.drawContours()绘制轮廓。

🍀(2)轮廓的拟合:包括矩形包围框和圆形包围框。

🍀(3)Canny边缘检测:最实用、最简单、效果最好的边缘检测方法。阈值越小,边缘越多。

🍀(4)霍夫变换:包括直线检测和圆环检测。其中,直线检测是检测之前先降噪,再做二值化阈值处理,圆环检测是检测之前先降噪,再转为单通道灰度图像。


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

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

相关文章

【Terraform学习】使用 Terraform 创建Amazon VPC(Terraform-AWS最佳实战学习)

使用 Terraform 创建Amazon VPC 实验步骤 前提条件 安装 Terraform: 地址 下载仓库代码模版 本实验代码位于 task_vpc 文件夹中。 变量文件 variables.tf 在上面的代码中,您将声明,aws_access_key,aws_secret_key和 区域变量…

Vue3 中引入液晶数字字体(通常用于大屏设计)

一、下载 .ttf 字体文件到本地,放在 src 中的 assets 文件下 下载液晶字体 DS-Digital.ttf 二、在 css 文件中引入字体 /* src/assets/fonts/dsfont.css */ font-face {font-family: electronicFont;src: url(./DS-Digital.ttf);font-weight: normal;font-styl…

计算机毕业设计 志愿者服务系统 微信小程序设计与开发

本课题要求实现一套微信小程序志愿者服务管理,系统主要包括(管理员,志愿者和团体管理者)三个模块等功能。 。系统选用java语言,应用ssm框架, MySQL为后台数据库。系统主要包括首页、个人中心、志愿者管理、…

科研 | Zotero导入无PDF的参考文献、书籍

最近在用Zotero在Word中插入参考文献的时候发现,有些没在网上找到对应的PDF版本,但也不是必须要PDF版本的参考文献或者参考书籍,如何才能不影响正常的文献排版 主要是先在网上找到对应文献,书籍,网页等的ISBN&#xf…

【Qt学习】05:自定义封装界面类

OVERVIEW 自定义封装界面类1.QListWidget2.QTreeWidget3.QTableWidget4.StackedWidget5.Others6.自定义封装界面类-显示效果(1)添加设计师界面类(2)在ui中设计自定义界面(3)在需要使用的界面中添加&#xf…

Docker搭建个人网盘、私有仓库

1、使用mysql:5.6和 owncloud 镜像,构建一个个人网盘 [rootlocalhost ~]# docker pull mysql:5.6 [rootlocalhost ~]# docker pull owncloud [rootlocalhost ~]# docker run -itd --name mysql --env MYSQL_ROOT_PASSWORD123456 mysql:5.6 [rootlocalhost ~]#…

Python语言实现React框架

迷途小书童的 Note 读完需要 6分钟 速读仅需 2 分钟 1 reactpy 介绍 reactpy 是一个用 Python 语言实现的 ReactJS 框架。它可以让我们使用 Python 的方式来编写 React 的组件,构建用户界面。 reactpy 的目标是想要将 React 的优秀特性带入 Python 领域,…

(动态规划) 剑指 Offer 48. 最长不含重复字符的子字符串 ——【Leetcode每日一题】

❓剑指 Offer 48. 最长不含重复字符的子字符串 难度:中等 请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。 示例 1: 输入: “abcabcbb” 输出: 3 解释: 因为无重复字符的最长子串是 “abc”,所以其长度为…

macbookpro如何清理系统数据 macbookpro怎么删除软件

Macbook Pro是苹果公司的一款高性能笔记本电脑,它拥有强大的硬件和流畅的操作系统。然而,随着时间的推移,你可能会发现你的Macbook Pro变得越来越慢,储存空间也越来越紧张。这时候,你需要对你的Macbook Pro进行一些清理…

Linux驱动之platform设备驱动

目录 前言 一、Linux驱动的分离与分层 二、开发环境 三、驱动程序编写 3.2 platform 驱动模块程序 3.3 测试app程序 四、运行测试 4.1 编译 4.2 运行测试 前言 前面几章编写的设备驱动都非常的简单,都是对 IO进行最简单的读写操作。像 I2C、SPI、 LCD 等这…

Ansible 创建使用角色

使用 Ansible Galaxy 和要求文件 /ansible/roles/requirements.yml 。从以下 URL 下载角色并安装到 /ansible/roles : http://materials/haproxy.tar 此角色的名称应当为 balancer http://materials/phpinfo.tar 此角色的名称应当为 phpinfo #创建 vim /ansible/r…

leetcode3. 无重复字符的最长子串(滑动窗口 - java)

滑动窗口 无重复字符的最长子串滑动窗口 上期经典 无重复字符的最长子串 难度 - 中等 3. 无重复字符的最长子串 给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。 示例 1: 输入: s “abcabcbb” 输出: 3 解释: 因为无重复字符的最长子串是 “abc…

MySQL详细安装与配置

免安装版的Mysql MySQL关是一种关系数据库管理系统,所使用的 SQL 语言是用于访问数据库的最常用的 标准化语言,其特点为体积小、速度快、总体拥有成本低,尤其是开放源码这一特点,在 Web 应用方面 MySQL 是最好的 RDBMS(Relation…

postman访问ruoyi后台接口

打开若依页面,登录进去,F12打开控制台,选一个后台服务,把下图两个节点,补到postman请求header里面即可

Day46|leetcode 139.单词拆分

leetcode 139.单词拆分 题目链接:139. 单词拆分 - 力扣(LeetCode) 视频链接:动态规划之完全背包,你的背包如何装满?| LeetCode:139.单词拆分_哔哩哔哩_bilibili 题目概述 给你一个字符串 s 和一…

关于ios Universal Links apple-app-site-association文件 Not Found的问题

1. 背景说明 1.1 Universal Links 是什么 Support Universal Links 里面有说到 Universal Links 是什么、注意点、以及如何配置的。简单来说就是 当您支持通用链接时,iOS 用户可以点击指向您网站的链接,并无缝重定向到您安装的应用程序 大白话就是说&am…

【算法训练-链表】反转链表、区间反转链表、K个一组反转链表

从今天开始进行高频算法的训练,一方面训练自己的逻辑思维,一方面保持自己的竞争力。训练过程有这么两个基准原则: 首先训练题的来源呢有三个,首选的是三个都出现过的高频题,以:牛客101为基准分类&#xff…

MAYA粒子基础_场

重力场 牛顿场 径向场 均匀场和重力场的区别 空气场 推动物体 阻力场 推动物体 涡流场 湍流场 体积轴场

研磨设计模式day12命令模式

目录 定义 几个参数 场景描述 代码示例 参数化设置 命令模式的优点 本质 何时选用 定义 几个参数 Command:定义命令的接口。 ConcreteCommand:命令接口的实现对象。但不是真正实现,是通过接收者的功能来完成命令要执行的操作 Receiver&#x…

kafka-python 消费者消费不到消息

排除步骤1: 使用group_id”consumer_group_id_001“ 和 auto_offset_reset"earliest" from kafka import KafkaConsumerconsumer KafkaConsumer(bootstrap_servers["dev-kafka01.test.xxx.cloud:9092"],enable_auto_commitTrue, auto_commit…