OpenCV第九章——图形检测

devtools/2024/9/23 2:08:54/

1.图像的轮廓       

轮廓是指图形或物体的外边缘线条,简单的几何图形是由平滑的线构成的容易识别,但不规则图形的轮廓由许多个点构成,识别起来比较困难。Opencv提供了findContours()方法来判断图像的边缘,之后将边缘的点封装成数组返回,语法结构如下:

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

参数说明:

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

mode:轮廓的检索模式(下表)

method:检测轮廓时使用的方法(下表)

返回值说明:

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

hierarchy:轮廓之间的层次关系

OpenCV还提供了drawContours()方法用来绘制轮廓,语法结构如下 :

参数说明:

  • image:要绘制轮廓的图像。这个图像应该是单通道(灰度图)或三通道(彩色图)的。
  • contours:轮廓点集,通常是由cv2.findContours()方法返回的第二个参数(在某些版本的OpenCV中,返回值可能有所不同,但contours始终是轮廓点集的列表)。
  • contourIdx:指定要绘制的轮廓索引。如果是-1,则绘制所有轮廓。
  • color:轮廓的颜色。对于灰度图,它是一个标量值;对于彩色图,它是一个BGR元组(即颜色顺序是蓝、绿、红)。
  • thickness:轮廓线的粗细。如果为负数(如cv2.FILLED),则轮廓内部将被填充。
  • lineType:线条的类型,例如cv2.LINE_8cv2.LINE_AA等。如果未指定,默认为cv2.LINE_8
  • hierarchy:轮廓的层次结构,由cv2.findContours()返回(在某些版本的OpenCV中可能返回)。如果不需要,可以设置为None
  • maxLevel:绘制轮廓的最大层级数,仅当hierarchy非空时才有效。如果为0,则只绘制指定的轮廓;如果为1,则绘制该轮廓及其直接子轮廓;依此类推。
  • offset:轮廓点集的偏移量。这是一个可选参数,表示在绘制轮廓时,轮廓点集中的所有点都要加上这个偏移量。

1.1绘制几何图像的轮廓

操作用图:

操作代码示例:

import cv2
img = cv2.imread(r"C:\Users\cgs\Desktop\pictures\5(9).jpg")  # 读取原图
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()  

操作效果图像:

1.2绘制不规则的轮廓

操作用图像:

操作代码示例:

import cv2
img = cv2.imread(r"C:\Users\cgs\Desktop\pictures\5(10).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矩形包围框

retval = cv2.boundingRect(array)

参数说明:

array:轮廓数组

返回值说明:

retval: 返回一个包含四个整数的元组 (x, y, w, h),具体含义如下:

x: 矩形的左上角的 x 坐标。

y: 矩形的左上角的 y 坐标。

w: 矩形的宽度。

h: 矩形的高度。

操作用图像:


操作代码示例:

import cv2
img = cv2.imread(r"C:\Users\cgs\Desktop\pictures\6(1).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圆形包围框

center, radius = cv2.minEnclosingCircle(points)

参数说明:

center:元组类型,包含两个浮点值(圆心横坐标和纵坐标)

radius;浮点类型,最小圆形包围框半径

操作代码示例:

import cv2
img = cv2.imread(r"C:\Users\cgs\Desktop\pictures\6(1).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.凸包

在OpenCV中,凸包(Convex Hull)是一个计算几何中的概念,用于描述一个点集的最外层凸多边形。具体来说,凸包是指完全包含原有轮廓,并且仅由轮廓上的点所构成的多边形,其特点是每一处都是凸的,即在凸包内连接任意两点的直线都在凸包的内部,并且任意连续3个点的内角小于180度。

语法结构如下:

hull = cv2.convexHull(points, clockwise=None, returnPoints=True)

 

参数说明

  • points:这是输入的点集,通常是一个NumPy数组,形状为(N, 1, 2)(N, 2),其中N是点的数量,每个点由两个元素(通常是x和y坐标)表示。
  • clockwise(可选):该参数指定凸包的输出方向。如果为True,则凸包的方向是顺时针的;如果为False,则为逆时针。如果未指定(即None),则凸包的方向由凸包算法的内部实现决定。
  • returnPoints(可选):如果为True,则返回凸包上的点。如果为False,则返回凸包索引(即原始点集中的索引)。在大多数情况下,你会希望这个参数为True

返回值

  • hull:如果returnPoints=True,则hull是一个NumPy数组,包含凸包上的点。这些点按凸包轮廓的顺序排列。
  • 如果returnPoints=False,则hull是一个包含索引的数组,这些索引指向原始点集中的点,按凸包轮廓的顺序排列。

操作代码示例:

import cv2img = cv2.imread(r"C:\Users\cgs\Desktop\pictures\6(1).png")  # 读取原始图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 转为灰度图像
ret, binary = cv2.threshold(gray, 127, 225, cv2.THRESH_BINARY)  # 二值化阈值处理
# 检测图像中出现的所有轮廓
contours, hierarchy = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
hull = cv2.convexHull(contours[0])  # 获取轮廓的凸包
cv2.polylines(img, [hull], True, (0, 0, 255), 2)  # 绘制凸包
cv2.imshow("img", img)  # 显示图像
cv2.waitKey()  
cv2.destroyAllWindows()  

操作效果图像:

 

4.Canny边缘检测

Canny边缘检测算法是一种非常流行的边缘检测算法,由John F. Canny在1986年提出。该算法旨在在噪声抑制和边缘检测之间取得最佳平衡,通常通过以下步骤实现:

  1. 噪声去除:首先,使用高斯滤波器平滑图像以去除噪声。这一步很重要,因为边缘检测对噪声很敏感。

  2. 计算梯度强度和方向:然后,计算图像中每个像素点的梯度强度和方向。这通常使用Sobel算子或其他梯度算子来完成。

  3. 非极大值抑制:在得到梯度强度和方向后,算法会对每个像素位置进行非极大值抑制。这一步的目的是保留局部梯度最大的点,作为边缘点。

  4. 双阈值处理和边缘连接:最后,算法使用两个阈值(高阈值和低阈值)来检测和连接边缘。首先,通过高阈值得到一个边缘图像,这个图像可能包含一些不连续的边缘片段。然后,通过检查由低阈值得到的边缘图像中哪些边缘片段可以连接到高阈值边缘图像中的边缘片段,来连接和恢复这些边缘。

Canny()方法语法结构:

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

image:要进行边缘检测的输入图像,应为灰度图。

threshold1:第一个阈值,用于边缘连接时的低阈值。

threshold2:第二个阈值,用于检测边缘时的高阈值。

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

L2gradient:可选参数,计算图像梯度的标识

返回值说明:

edges:输出的边缘图像,与输入图像具有相同的尺寸和类型

操作用图像:

操作代码示例:

import cv2
img = cv2.imread(r"C:\Users\cgs\Desktop\pictures\5(5).jpg")  # 读取原图
r1 = cv2.Canny(img, 10, 50);  # 使用不同的阈值进行边缘检测
r2 = cv2.Canny(img, 100, 200);
r3 = cv2.Canny(img, 400, 600);cv2.imshow("img", img)  # 显示原图
cv2.imshow("r1", r1)  # 显示边缘检测结果
cv2.imshow("r2", r2)
cv2.imshow("r3", r3)
cv2.waitKey()  
cv2.destroyAllWindows()  

操作效果图像:

5.霍夫变换

霍夫变换(Hough Transform)是一种图像处理技术,用于检测图像中的几何形状,尤其是直线和圆等常见形状。它特别适用于处理有噪声的图像数据,因为它能够在特征空间中找到形状,即使在图像中这些形状可能是断裂的或者被遮挡的。

5.1 直线检测

OpenCV中的HoughLinesP()方法

HoughLinesP() 是 OpenCV 中用于直线检测的函数之一,与 HoughLines() 相比,HoughLinesP() 能够直接返回直线的两个端点,这对于后续处理(如绘制直线)更为方便。

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

参数说明:

image: 输入图像,应该是边缘检测后的二值图像(通常是Canny边缘检测的结果)。

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

theta: 以弧度为单位的θ的精度。

threshold: 累加器平面的阈值参数。只有那些获得足够交点的曲线才被返回。

minLineLength: 最小线段长度。比这个长度短的线段将被拒绝。

maxLineGap: 线段上最大间隔,用于将同一行上的点连接成线段。如果间隔大于此值,则视为两条线段。

操作用图像:


操作代码示例:

import cv2
import numpy as npimg = cv2.imread(r"C:\Users\cgs\Desktop\pictures\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()  


操作效果图像: 

5.2圆环检测

OpenCV中的HoughCircles()方法

在OpenCV中,HoughCircles()函数用于实现基于霍夫变换的圆环检测。它返回图像中检测到的圆的参数(圆心和半径)

 cv2.HoughCircles(image, method, dp, minDist, param1=100, param2=100, minRadius=0, maxRadius=0)

参数说明:

image:原始图像

method:检测圆的方法。目前OpenCV中唯一实现的方法是cv2.HOUGH_GRADIENT,它基于边缘的梯度信息。

dp:累加器分辨率与图像分辨率的反比。例如,如果dp=1,则累加器和输入图像具有相同的分辨率。dp=2,累加器分辨率是图像分辨率的一半。

minDist:检测到的圆心之间的最小距离。如果参数设置得太小,则可能会错误地检测到多个相邻的圆。

param1:Canny边缘检测器的高阈值(第一阶段)。记住,低阈值是高阈值的一半。

param2:累加器阈值,即识别为圆所需的投票数。参数值越高,检测到的圆越完美。

minRadius:圆半径的最小值。

maxRadius:圆半径的最大值。

返回值说明:

circles:函数返回一个包含圆参数(x, y, radius)的NumPy数组,每个圆占用数组的一行。如果未找到圆,则返回None。

操作用图像:

操作代码示例:

import cv2
import numpy as npimg = cv2.imread(r"C:\Users\cgs\Desktop\pictures\6(2).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()  

操作效果图像:

 

有关轮廓检测的内容就到这里了,感谢大家的观看!!! 


http://www.ppmy.cn/devtools/115751.html

相关文章

技术选型对SQL与NoSQL以及Mysql,Hbase,Hive使用特性差别

在对关系数据库 MySQL 和非关系型的分布式数据库 HBase、Hive 进行技术选型分析时,可以从以下几个方面考虑: 一、性能方面 查询速度 MySQL:对于结构化数据的复杂查询,尤其是使用索引进行精确查询时,可以有较快的响应速…

Python练习宝典:Day 1 - 选择题 - 基础知识

目录 一、踏上Python之旅二、Python语言基础三、流程控制语句四、序列的应用 一、踏上Python之旅 1.想要输出 I Love Python,应该使用()函数。 A.printf() B.print() C.println() D.Print()2.Python安装成功的标志是在控制台(终端)输入python/python3后,命令提示符变为: A.&…

多个PDF合并为一个PDF

1、安装依赖: 首先,确保在Python环境中安装了 PyPDF2 库,可以通过以下命令安装: pip install pypdf22、合并 PDF 文件的代码: import os from PyPDF2 import PdfMergerdef merge_pdfs(pdf_list, output_path):merge…

Python中的null是什么?

在知乎上遇到一个问题,说:计算机中的「null」怎么读? null正确的发音是/n^l/,有点类似四声‘纳儿’,在计算机中null是一种类型,代表空字符,没有与任何一个值绑定并且存储空间也没有存储值。 Py…

OpenAI GPT o1技术报告阅读(2)- 关于模型安全性的测试案例

✨报告阅读:使用大模型来学习推理(Reason) 首先是原文链接:https://openai.com/index/learning-to-reason-with-llms/ 接下来我们看一个简单的关于模型安全性的测试,当模型被问到一个有风险的话题时,会如何思考并回答用户呢&…

electron-vue安装与打包问题解决

electron-vue安装与打包问题解决 1.项目安装 报错 RequestError: connect ETIMEDOUT 185.199.109.133:443RequestError: socket hang up 问题 npm国内下载时存在网络连接失败以及网络缓慢的情况,需要使用镜像安装设置npm镜像地址,安装vue-electron时…

【项目】基于 Huffman 算法实现文件压缩

摘要:记录通过学习Huffman算法自主实现简单的文件压缩程序的过程。 什么是文件压缩 在古诗词中,这种信息的高度浓缩体现得淋漓尽致。例如王维的《使至塞上》中的名句 “ 大漠孤烟直,长河落日圆 ”。仅仅十个字,却描绘出了一幅极为…

【Linux实践】实验二:LINUX操作基础

【Linux实践】实验二:LINUX操作基础 实验目的实验内容实验步骤及结果1. 打开终端2. 关闭计算机命令3. 查看帮助文档4. 修改计算机主机名5. 显示月历和时间6. 统计行数、字符数、单词数 这章开始要涉及到命令了,其他关于命令的内容可以看我 2021年写的笔记…