09 OpenCV图形检测
1 轮廓描边
cv2.findContours()
函数是OpenCV中用于寻找轮廓的函数之一。它可以用于在二值图像中查找并检测出所有的物体轮廓,以及计算出这些轮廓的各种属性,例如面积、周长、质心等。
cv2.findContours()
函数的语法如下:
contours, hierarchy = cv2.findContours(image, mode, method[, contours[, hierarchy[, offset]]])
其中,参数含义如下:
image
:输入二值图像。mode
:轮廓检索模式。有三种可选模式:cv2.RETR_EXTERNAL
,表示只检测外部轮廓;cv2.RETR_LIST
,表示检测所有轮廓,并将它们存储在列表中;cv2.RETR_TREE
,表示检测所有轮廓,并构建轮廓的完整层次结构。method
:轮廓近似方法。有四种可选方法:cv2.CHAIN_APPROX_NONE
,表示存储所有的轮廓点;cv2.CHAIN_APPROX_SIMPLE
,表示仅存储轮廓的终点坐标;cv2.CHAIN_APPROX_TC89_L1
和cv2.CHAIN_APPROX_TC89_KCOS
,表示使用Teague的链逼近算法来压缩轮廓点。contours
:可选参数,用于存储检测到的轮廓。如果提供了该参数,则函数会将轮廓存储在该参数中。hierarchy
:可选参数,用于存储轮廓的层次结构信息。如果提供了该参数,则函数会将层次结构信息存储在该参数中。offset
:可选参数,指定检测到的轮廓点的偏移量。默认为(0, 0)
。
cv2.findContours()
函数会返回两个值:contours
和 hierarchy
。其中,contours
是一个包含所有检测到的轮廓的Python列表,每个轮廓都是由一组点构成的Numpy数组。而 hierarchy
是一个包含轮廓的层次结构信息的Numpy数组。
因为输入图像必须是二值图像,所以需要先将彩色图像转变为灰度图像,再转换为二值图像,才能输入进参数值中。
下面尝试对前面文章的主图进行描边:
import cv2 # 读入图像
img = cv2.imread('test.png') # 将图像转换为灰度图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 对灰度图像进行二值化处理
ret, thresh = cv2.threshold(gray, 180, 255, cv2.THRESH_BINARY) # 查找轮廓
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) # 在图像上绘制轮廓
cv2.drawContours(img, contours, -1, (0, 0, 255), 1) # 显示结果
cv2.imshow('Original', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
这段代码首先使用 cv2.imread()
函数读入图像,然后使用 cv2.cvtColor()
函数将该图像转换为灰度图像。接着,我们对灰度图像进行了二值化处理,并使用 cv2.findContours()
函数查找图像中的轮廓。最后使用 cv2.drawContours()
函数将所有轮廓绘制在原始图像上,并使用 cv2.imshow()
函数显示处理后的图像。
2 轮廓拟合
轮廓拟合可以将凹凸不平的轮廓以平滑曲线进行连接。常用的有矩形拟合cv2.boundingRect
和圆形拟合cv2.minEnclosingCircle
。二者都是在cv2.findContours()
的基础上进行拟合。
2.1 最小外接矩形
cv2.boundingRect()
函数可以用于计算轮廓的最小外接矩形,即将轮廓拟合到一个矩形框中,并返回该矩形框的左上角坐标以及宽度和高度。该函数的语法如下:
x, y, w, h = cv2.boundingRect(contour)
其中,contour
是一个Numpy数组,表示待计算的轮廓。函数返回的 x
和 y
分别表示最小外接矩形的左上角坐标,而 w
和 h
则分别表示矩形的宽度和高度
2.2 最小外接圆
cv2.minEnclosingCircle()
函数可以用于计算轮廓的最小外接圆,即将轮廓拟合到一个圆形中,并返回该圆的圆心坐标和半径。该函数的语法如下:
(x, y), radius = cv2.minEnclosingCircle(contour)
其中,contour
是一个Numpy数组,表示待计算的轮廓。函数返回的 (x, y)
是最小外接圆的圆心坐标,而 radius
则是圆的半径。
2.3 示例代码
import cv2 # 读入图像
img = cv2.imread('test.png') # 将图像转换为灰度图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 对灰度图像进行二值化处理
ret, thresh = cv2.threshold(gray, 180, 255, cv2.THRESH_BINARY) # 查找轮廓
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 绘制最小外接矩形和最小外接圆
for contour in contours: # 计算最小外接矩形 x, y, w, h = cv2.boundingRect(contour) cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 255), 2) # 计算最小外接圆 (x, y), radius = cv2.minEnclosingCircle(contour) center = (int(x), int(y)) radius = int(radius) cv2.circle(img, center, radius, (0, 255, 0), 2) # 显示结果
cv2.imshow('Original', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
最终,基本上每个文章都被画上了矩形框与圆形框。
3 凸包
OpenCV中的凸包是一个用于计算给定点集的凸包形状的函数。凸包是一个包围给定点集的最小凸多边形或凸多面体。凸多边形或凸多面体的特点是其边缘不会凹陷(可以理解为不会有大于180°的角),而是向外弯曲,使得所有点都位于其内部或边缘上。
在OpenCV中,可以使用cv2.convexHull()函数来计算给定点集的凸包。该函数接受一个点集作为输入,并返回凸包形状的点集。该函数使用的算法称为Graham-Scan算法,该算法在O(n log n)时间内计算给定点集的凸包。
示例代码如下:
import cv2 # 读入图像
img = cv2.imread('test.png') # 将图像转换为灰度图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 对灰度图像进行二值化处理
ret, thresh = cv2.threshold(gray, 180, 255, cv2.THRESH_BINARY) # 查找轮廓
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 绘制凸包
for contour in contours: hull = cv2.convexHull(contour) cv2.polylines(img, [hull], True, (0, 0, 255), 2) # 显示结果
cv2.imshow('Original', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
4 Canny边缘检测
Canny边缘检测是一种广泛使用的方法,用于检测图像中的边缘。在OpenCV中,可以使用cv2.Canny()函数来执行Canny边缘检测。
cv2.Canny()函数使用以下步骤来检测图像中的边缘:
- 降噪:使用高斯滤波器对输入图像进行模糊处理,以减少图像中的噪声。
- 计算梯度:对模糊图像使用Sobel算子来计算图像中每个像素的梯度。这可以帮助识别像素值变化最剧烈的位置,即可能的边缘。
- 非极大值抑制:在图像中沿着梯度方向找到局部最大值,将它们保留为可能的边缘点,而抑制其他非最大值的像素点。
- 双阈值检测:根据两个阈值(高阈值和低阈值)将可能的边缘点分类为强边缘和弱边缘。如果像素值大于高阈值,则被标记为强边缘;如果像素值在低阈值和高阈值之间,则被标记为弱边缘。如果像素值低于低阈值,则被抑制。
- 边缘连接:在图像中连接强边缘,并删除与弱边缘不相连的弱边缘。
通过调整高阈值和低阈值,可以影响Canny边缘检测的结果。较高的阈值将产生更少的强边缘,而较低的阈值将产生更多的弱边缘。通常建议将高阈值设置为低阈值的3到2倍之间。
下面的代码展示了阈值对边缘检测的影响:
import cv2
img = cv2.imread("test.png") # 读取原图
r1 = cv2.Canny(img, 25, 50) # 使用不同的阈值进行边缘检测
r2 = cv2.Canny(img, 100, 200)
r3 = cv2.Canny(img, 200, 400) cv2.imshow("img", img)
cv2.imshow("r1", r1) # 显示边缘检测结果
cv2.imshow("r2", r2)
cv2.imshow("r3", r3)
cv2.waitKey()
cv2.destroyAllWindows()
5 霍夫变换
霍夫变换(Hough Transform)是一种常见的图像处理技术,用于检测图像中的各种形状。在OpenCV中,可以使用cv2.HoughLines()和cv2.HoughCircles()函数来执行霍夫变换。
5.1 检测直线
cv2.HoughLines()
函数用于检测二维平面上的直线。该函数接受二值化图像和一些可选参数作为输入,并返回检测到的直线的端点坐标。在进行霍夫变换之前,需要使用cv2.Canny()
函数对输入图像进行边缘检测。函数将返回一个二维数组,其中每一行表示检测到的一条直线的两个端点坐标。
cv2.HoughLines()
函数语法如下:
lines = cv2.HoughLines(image, rho, theta, threshold, lines=None, srn=None, stn=None, min_theta=None, max_theta=None)
其中,参数含义如下:
image
:输入的二值化图像,即通过cv2.Canny()等函数得到的边缘图像。rho
:表示距离精度,以像素为单位。通常取值为1。theta
:表示角度精度,以弧度为单位。通常取值为np.pi/180,表示以1度为单位。threshold
:表示在霍夫空间中的最小投票数,用于确定一条直线是否存在。通常取值范围为0到图像宽高之和的一半。lines
:可选输出参数,用于存储检测到的直线,以numpy.ndarray格式返回。srn
:可选参数,表示霍夫梯度中径向和角度分辨率之间的参数,通常取默认值0。stn
:可选参数,表示霍夫梯度中两个角度之间的分辨率,通常取默认值0。min_theta
和max_theta
:可选参数,表示需要检测的直线的角度范围,以弧度为单位。
该函数将返回一个包含检测到的直线的端点坐标的numpy.ndarray数组。数组中每一行表示检测到的一条直线,包括两个端点的rho和theta值。
霍夫变换是一种计算密集型算法,处理大型图像时可能需要一定的计算时间。此外,霍夫变换对输入图像的质量要求较高,因此必须在边缘检测和二值化等预处理步骤上进行仔细的参数调整和图像优化,以获得最佳结果。
检测图像中存在直线的代码:
import cv2
import numpy as np img = cv2.imread("test.png") # 读取原图
o = img.copy() # 复制原图
o = cv2.medianBlur(o, 5) # 使用中值滤波进行降噪
gray = cv2.cvtColor(o, cv2.COLOR_BGR2GRAY) # 从彩色图像变成单通道灰度图像
binary = cv2.Canny(o, 50, 150) # 绘制边缘图像
# 检测直线,精度为1,全角度,阈值为100,线段最短100,最小间隔为30
lines = cv2.HoughLinesP(binary, 1, np.pi / 180, 100, minLineLength=100, maxLineGap=30)
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()
5.2 检测圆形
cv2.HoughCircles()
函数用于检测圆形。该函数接受二值化图像、检测算法的参数以及圆的最小和最大半径作为输入,并返回检测到的圆的圆心坐标和半径。函数将返回一个三维数组,其中每个元素表示检测到的一个圆形,包括圆心坐标和半径。
cv2.HoughCircles()
函数语法如下:
circles = cv2.HoughCircles(image, method, dp, minDist, circles=None, param1=None, param2=None, minRadius=None, maxRadius=None)
其中:
image
:输入的二值化图像,即通过cv2.Canny()等函数得到的边缘图像。method
:表示霍夫变换检测圆形的方法。目前支持两种方法:cv2.HOUGH_GRADIENT和cv2.HOUGH_GRADIENT_ALT。dp
:表示霍夫梯度中心之间的累加器分辨率的反比例系数。通常取值为1,表示与图像像素一样的分辨率。minDist
:表示圆形之间的最小距离,以像素为单位。通常取值为圆形直径的两倍左右。circles
:可选输出参数,用于存储检测到的圆形,以numpy.ndarray格式返回。param1
:表示边缘检测的高阈值,用于辅助检测图像中的圆形。通常取值为100。param2
:表示霍夫变换中的累加器阈值,用于确定检测到的圆形是否存在。通常取值为30到50之间。minRadius
和maxRadius
:可选参数,表示需要检测的圆形的半径范围,以像素为单位。
该函数将返回一个包含检测到的圆形的圆心坐标和半径的numpy.ndarray数组。数组中每一行表示检测到的一个圆形,包括三个参数:圆心坐标x、y和半径r。
代码使用与检测直线非常相似,这里就不写示例代码了。
相关文章:

09 OpenCV图形检测
1 轮廓描边 cv2.findContours() 函数是OpenCV中用于寻找轮廓的函数之一。它可以用于在二值图像中查找并检测出所有的物体轮廓,以及计算出这些轮廓的各种属性,例如面积、周长、质心等。 cv2.findContours() 函数的语法如下: contours, hiera…...

解密Teradata与中国市场“分手”背后的原因!国产数据库能填补空白吗?
2月15日,西方的情人节刚刚过去一天,国内IT行业就爆出一个大瓜。 继Adobe、甲骨文、Tableau、Salesforce之后,又一个IT巨头要撤离中国市场。 Teradata天睿公司官宣与中国市场“分手”,结束在中国的直接运营。目前,多家…...

Bernstein-Vazirani算法
B-V算法 (1) 问题描述 给定布尔函数f:{0,1}n→0,1f:{\left\{ {0,1} \right\}^n} \to{0,1}f:{0,1}n→0,1, 函数fff的值是由输入比特串xxx和确定的比特串sss做模2意义下的内积:f(x)x⋅s(mod2),f\left( x \right) x \cdot s\left( {\bmod 2} \right),f(x)x⋅s(mod2),…...
华为OD机试 - 相对开音节 | 备考思路,刷题要点,答疑 【新解法】
最近更新的博客 【新解法】华为OD机试 - 关联子串 | 备考思路,刷题要点,答疑,od Base 提供【新解法】华为OD机试 - 停车场最大距离 | 备考思路,刷题要点,答疑,od Base 提供【新解法】华为OD机试 - 任务调度 | 备考思路,刷题要点,答疑,od Base 提供【新解法】华为OD机试…...

MyBatis
一、MyBatis环境搭建创建工程启动idea开发工具,选择工具栏中的“file”--“new”--“project”选项弹出“new project”对话框,编辑项目名称 选择maven项目,项目路径 单击 create 创建即可。引入相关依赖<dependencies><dependency&…...
良好的作息表
今天给大家带来“传说中”的“世界上最健康的作息时间表”(仅供参考),随时提醒自己吧,毕竟身体可是自己的哦。 7:30 起床:英国威斯敏斯特大学的研究人员发现,那些在早上5:22-7:21分起床的人,其血液中有一种能引起心脏病…...

【郭东白架构课 模块一:生存法则】01|模块导学:是什么在影响架构活动的成败?
你好,我是郭东白。这节课是我们模块一的导入部分,我会先来介绍模块的主要内容,以及为什么我要讲生存法则这个话题。 一名软件架构师要为相对复杂的业务制定,并且引导实施一个结构化的软件方案。这个发现最终方案和推动实施的过程&…...

webshell免杀之函数与变量玩法
webshell免杀之函数与变量玩法 前言 前文列举了一些用符号免杀的例子,此篇文章就以函数和变量来尝试下免杀。 本文以PHP为例,用PHP中函数和变量及语法特性,在不隐藏函数关键字情况下进行免杀。 动态函数 PHP中支持一个功能叫 variable fu…...
【新解法】华为OD机试 - 去重求和 | 备考思路,刷题要点,答疑,od Base 提供
华为 OD 清单查看地址:blog.csdn.net/hihell/category_12199275.html 去重求和 | 备考思路,刷题要点,答疑,od Base 提供 给定一个数组,编写一个函数, 计算他的最大N个数和最小N个数的和, 需要对数组进行去重。 输入 第一行输入M,M表示数组大小 第二行输入M个数,表…...

MySQL 服务正在启动.MySQL 服务无法启动.服务没有报告任何错误。请键入 NET HELPMSG 3534 以获得更多的帮助。总结较全 (已解决)
输入以下命令启动mysql: net start mysql出现以下错误提示: MySQL 服务正在启动 .MySQL 服务无法启动。服务没有报告任何错误。请键入 NET HELPMSG 3534 以获得更多的帮助。 出现这个问题的话,一般有几个情况: 一、MySQL安装文…...

【数据结构与算法】数组2:双指针法 二分法(螺旋矩阵)
文章目录今日任务1.Leetcode977:有序数列的平方(1)题目(2)思路(3)暴力排序(4)双指针法2.Leetcode209:长度最小的子数组(1)题目&#x…...
librtmp优化
librtmp是一个RTMP的开源库,很多地方用它来做推流、拉流。它是RTMPDump开源软件里的一部分,librtmp的下载地址:RTMPDump,目前最新版是V2.3。本文重点介绍librtmp优化。 1、调整网络输出块大小。 RTMP_Connect0函数中LibRTMP是关…...

数据结构与算法(二):线性表
上一篇《数据结构与算法(一):概述》中介绍了数据结构的一些基本概念,并分别举例说明了算法的时间复杂度和空间复杂度的求解方法。这一篇主要介绍线性表。 一、基本概念 线性表是具有零个或多个数据元素的有限序列。线性表中数据…...

IOS安全区域适配
对于 iPhone 8 和以往的 iPhone,由于屏幕规规整整的矩形,安全区就是整块屏幕。但自从苹果手机 iphoneX 发布之后,前端人员在开发移动端Web页面时,得多注意一个对 IOS 所谓安全区域范围的适配。这其实说白了就是 iphoneX 之后的苹果…...

在Java 中 利用Milo通信库,实现OPCUA客户端,并生成证书
程序结构: 配置文件resources: opcua.properties 西门子PLC端口号为4840,kepserver为49320 #opcua服务端配置参数 #opcua.server.endpoint.urlopc.tcp://192.168.2.102:49320 opcua.server.endpoint.urlopc.tcp://192.168.2.11:4840 opcu…...

三分钟学会用Vim
Vim知识点 目录Vim知识点一:什么是vim二:vim常用的三种模式三:vim的基本操作一:什么是vim vim最小集 vim是一款多模式的编辑器—各种模式—每种模式的用法有差别—每种模式之间可以互相切换 但是我们最常用的就是3~5个模式 vi…...

编译链接实战(8)认识elf文件格式
🎀 关于博主👇🏻👇🏻👇🏻 🥇 作者简介: 热衷于知识探索和分享的技术博主。 💂 csdn主页::【奇妙之二进制】 ✍️ 微信公众号:【Linux …...

新手小白如何入门黑客技术?
你是否对黑客技术感兴趣呢?感觉成为黑客是一件很酷的事。那么作为新手小白,我们该如何入门黑客技术,黑客技术又是学什么呢? 其实不管你想在哪个新的领域里有所收获,你需要考虑以下几个问题: 首先ÿ…...

【java】Spring Boot --深入SpringBoot注解原理及使用
步骤一 首先,先看SpringBoot的主配置类: SpringBootApplication public class StartEurekaApplication {public static void main(String[] args){SpringApplication.run(StartEurekaApplication.class, args);} }步骤二 点进SpringBootApplication来…...

一文掌握如何对项目进行诊断?【步骤方法和工具】
作为项目经理和PMO,面对错综复杂的项目,需要对组织的项目运作情况进行精确的分析和诊断,找出组织项目管理中和项目运行中存在的问题和潜在隐患,分析其原因,预防风险,并且形成科学合理的决策建议和解决方案&…...

突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合
强化学习(Reinforcement Learning, RL)是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程,然后使用强化学习的Actor-Critic机制(中文译作“知行互动”机制),逐步迭代求解…...

简易版抽奖活动的设计技术方案
1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...

【Oracle APEX开发小技巧12】
有如下需求: 有一个问题反馈页面,要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据,方便管理员及时处理反馈。 我的方法:直接将逻辑写在SQL中,这样可以直接在页面展示 完整代码: SELECTSF.FE…...

什么是库存周转?如何用进销存系统提高库存周转率?
你可能听说过这样一句话: “利润不是赚出来的,是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业,很多企业看着销售不错,账上却没钱、利润也不见了,一翻库存才发现: 一堆卖不动的旧货…...

【单片机期末】单片机系统设计
主要内容:系统状态机,系统时基,系统需求分析,系统构建,系统状态流图 一、题目要求 二、绘制系统状态流图 题目:根据上述描述绘制系统状态流图,注明状态转移条件及方向。 三、利用定时器产生时…...
C#学习第29天:表达式树(Expression Trees)
目录 什么是表达式树? 核心概念 1.表达式树的构建 2. 表达式树与Lambda表达式 3.解析和访问表达式树 4.动态条件查询 表达式树的优势 1.动态构建查询 2.LINQ 提供程序支持: 3.性能优化 4.元数据处理 5.代码转换和重写 适用场景 代码复杂性…...
为什么要创建 Vue 实例
核心原因:Vue 需要一个「控制中心」来驱动整个应用 你可以把 Vue 实例想象成你应用的**「大脑」或「引擎」。它负责协调模板、数据、逻辑和行为,将它们变成一个活的、可交互的应用**。没有这个实例,你的代码只是一堆静态的 HTML、JavaScript 变量和函数,无法「活」起来。 …...

Python 实现 Web 静态服务器(HTTP 协议)
目录 一、在本地启动 HTTP 服务器1. Windows 下安装 node.js1)下载安装包2)配置环境变量3)安装镜像4)node.js 的常用命令 2. 安装 http-server 服务3. 使用 http-server 开启服务1)使用 http-server2)详解 …...
在树莓派上添加音频输入设备的几种方法
在树莓派上添加音频输入设备可以通过以下步骤完成,具体方法取决于设备类型(如USB麦克风、3.5mm接口麦克风或HDMI音频输入)。以下是详细指南: 1. 连接音频输入设备 USB麦克风/声卡:直接插入树莓派的USB接口。3.5mm麦克…...

算术操作符与类型转换:从基础到精通
目录 前言:从基础到实践——探索运算符与类型转换的奥秘 算术操作符超级详解 算术操作符:、-、*、/、% 赋值操作符:和复合赋值 单⽬操作符:、--、、- 前言:从基础到实践——探索运算符与类型转换的奥秘 在先前的文…...