您现在的位置是:网站首页> 编程资料编程资料
Python OpenCV实现图形检测示例详解_python_
2023-05-26
422人已围观
简介 Python OpenCV实现图形检测示例详解_python_
图形检测在计算机视觉开发中是一项非常重要的操作,算法通过对图像的检测,分析出图像中可能存在哪些形状。除此之外,除了让计算机识别轮廓之外,轮廓也需要让人看到,这就需要再分别读这些轮廓的形状进行描绘。
1. 轮廓识别与描绘
cv2.findContours() & cv2.drawContours() 方法
在Python中OpenCV提供了findContours() 方法来判断图像的轮廓,drawContours()方法来绘制轮廓。
1.1 cv2.findComtours()方法
cv2.findComtours()方法的语法如下
cv2.contours, hierarchy = findContours(image, mode, method)
其中
- image 即原图像
- mode 轮廓检索模式,具体参数被总结在了下表中
- method 使用的方法,具体参数也被总结在了下表中
contours是一个列表,列表的每一个元素都是由某个轮廓的像素的坐标组成的数组。
hierarchy是轮廓与轮廓之间的层次关系。
mode取值表
| mode值 | 描述 |
|---|---|
| cv2.RETR_EXTERNAL | 只检测外轮廓 |
| cv2.RETR_LIST | 检测所有轮廓,但不建立层次关系 |
| cv2.RETR_CCOMP | 检测所有轮廓,并建立两级层次关系 |
| cv2.RETR_TREE | 建立所有轮廓,并建立树状结构的层次关系 |
method取值表
| cv2.PATH_APPROX_ | 储存轮廓上所有点 |
|---|---|
| cv2.PATH_APPROX_NONE | 只保存水平、垂直或对角线轮廓的端点 |
| cv2.PATH_APPROX_SIMPLE | Ten-Chinl |
| cv2.PATH_APPROX_TC89_L1 | Ten-Chinl近似算法的一种 |
| cv2.PATH_APPROX_TC89_KCOS | Ten-Chinl近似算法的一种 |
1.2 cv2.drawContours() 方法
cv2.drawContours(image, contours, contourIdx, color, thickness=None, lineType=None, hierarchy=None, maxLevel=None, offset=None)
- image 目标图像
- contours findComtours()方法得到的轮廓列表
- contourldx 轮廓中列表中,绘制轮廓的对象的索引,如果为-1则表示绘制所有
- color 绘制线条时的颜色,使用BGR格式描述
- thickness 线条粗细程度,-1表示实心
- lineType 绘制轮廓时线条的类型(可选参数)
- hierarchy findComtours()方法得到的层次关系(可选参数)
- maxLevel 绘制轮廓的层次深度,最深绘制在maxLevel层。(可选参数)
- offset 偏移量 (可选参数)
drawContours() 方法返回的是一个图像(数组)。
1.3 代码示例
以队此小鸟图操作为例(test1.jpg):

import cv2 img = cv2.imread("test1.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() 程序执行结果展示如下,图中所有能够识别出的轮廓被描出:

2. 轮廓拟合
轮廓拟合,即,将凹凸不平的轮廓用平整的几何图形体现出来。这里展示使用矩形和圆形拟合两种方法。
2.1 矩形包围框拟合 - cv2.boundingRect()
在Python中OpenCV提供了cv2.boundingRect()来计算轮廓的最小矩形边界的坐标 ,其语法如下
retval = cv2.boundingRect(array)
其中参数array为轮廓数组。即,cv2.findComtours()方法的执行结果中的contours中的元素。
返回值retval是一个包含着四个整数值的元组,四个值依次是左上角顶点的横坐标,左上角顶点的纵坐标,矩形的宽,矩形的高。
常常也可以写成x,y,w,h = retval = cv2.boundingRect(array)
还以这张小鸟图片(test1.jpg)为例,在上一个部分的示例中,我们找出并绘制出了图中所有的轮廓,经过调试,发现被识别出的轮廓共有94个。
我们要从数组列表中,选择出表示小鸟轮廓的位置的数组。
从上图中可以看出,小鸟的轮廓是所有轮廓中最大的。即该数组的 shape[0] 最大。即我们只用找出 shape[0]最大的即可。
import cv2 img = cv2.imread("test1.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_SIMPLE) # 找出小鸟的轮廓 n1 = 1 n2 = 0 index = 0 for arr in contours: if len(arr) > n1: n1 = len(arr) index = n2 n2 += 1 print(index) x, y, w, h = cv2.boundingRect(contours[index]) # 绘制红色矩形 cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 255), 2) cv2.imshow("img", img) cv2.waitKey() cv2.destroyAllWindows() 绘制出矩形包围框效果如下:

2.2圆形包围框拟合 - cv2.minEnclosingCircle()
在Python中OpenCV提供了cv2.minEnclosingCircle()来计算轮廓的最小圆形边界的圆心和半径 ,其语法如下
center,radius = minEnclosingCircle(points)
其中
- points的轮廓数组
- center最小圆形包围框的圆心的横纵坐标。是元组类型。
- radius是最小圆形包围款更多半径,浮点类型。
同样的算法,只是这次调用cv2.minEnclosingCircle()方法,其他不变:
import cv2 img = cv2.imread("test1.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_SIMPLE) n1 = 1 n2 = 0 index = 0 for arr in contours: if len(arr) > n1: n1 = len(arr) index = n2 n2 += 1 center, radius = cv2.minEnclosingCircle(contours[index]) # 圆心点横坐标转为近似整数 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. 凸包 绘制
使用矩形框和圆形框对图形的贴合程度往往都会较差。为了提高这个贴合程度,我们可以使用“凸包”。
所谓凸包,就是最逼近轮廓的多边形。
在Python中OpenCV提供了 cv2.bonvexHull()方法来计算凸包
cv2.bonvexHull()方法语法如下:
hull = convexHull(points, clockwise=None, returnPoints=None)
其中
- points 是轮廓数组
- clockwise 是布尔类型的参数,默认为True,表示凸包中的点按顺时针排序,为False时则按逆时针 排序。
- returnPoints 是布尔类型的参数,默认为True时返回点坐标。如果为False则返回点索引。
返回值hull是凸包的点阵数组
依然以“test1.jpg为例”,为图中的小鸟绘制凸包:
import cv2 img = cv2.imread("test1.jpg") # 转为灰度图像 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) n1 = 1 n2 = 0 index = 0 for arr in contours: if len(arr) > n1: n1 = len(arr) index = n2 n2 += 1 hull = cv2.convexHull(contours[index]) cv2.polylines(img, [hull], True, (0, 0, 255), 2) cv2.imshow("img", img) cv2.waitKey() cv2.destroyAllWindows() 
4. Canny边缘检测 - cv2.Canny()
4.1 cv2.Canny() 用法简介
Canny边缘检测算法是John F.Canny在1986年开发的一个多级边缘检测算法。
Canny边缘检测算法通过像素的梯度变化寻找图像的边缘,最终可以绘制出十分精细的二值边缘图像
edges = cv2.Canny(image, threshold1, threshold2, apertureSize=None, L2gradient=None)
其中
- image 即原图像
- threshold1 第一个阈值,一般为最小阈值
- threshold2 第二个阈值,一般为最大阈值
- apertureSize Sobel算子的孔径大小
- L2gradient 计算图像梯度的标识。默认为False。为True时采用更精准的算法进行计算。
关于这两个阈值怎么用,这涉及到了算法的底层逻辑,还请自行探索。这里一种可以接受的解释是:低于阈值1的像素点,会被认为不构成边缘,而高于阈值2的像素点,会被认为构成边缘。
最后返回值edges是一个二值的灰度图像。
4.2 代码示例
下边对test1.jpg以三组不同的阈值来做Canny边缘检测,根据处理结果感受算法效果:
- 当阈值为 10-50 时
import cv2 img = cv2.imread("test1.jpg") r1 = cv2.Canny(img, 10, 50) cv2.imshow("r1", r1) cv2.waitKey() cv2.destroyAllWindows() 
- 当阈值为100-200时
import cv2 img = cv2.imread("test1.jpg") r2 = cv2.Canny(img, 100, 200) cv2.imshow("r2", r2) cv2.waitKey() cv2.destroyAllWindows()
- 当阈值为400-600时
import cv2 img = cv2.imread("test1.jpg") r3 = cv2.Canny(img, 400, 600) cv2.imshow("r3", r3) cv2.waitKey() cv2.destroyAllWindows()
5. 霍夫变换
5.1 概述
霍夫变换是一种特征检测,通过霍夫变换可以检测出图像中存在的特殊的形状。比如,直线,圆等。
霍夫变换检测直线时,算法有两个,
一个是cv2.HoughLines() 方法,用于检测无限延长的直线;
另一个是cv2.HoughLinesP() 方法,用于检测线段。
霍夫变换检测圆,使用的是**cv2.HoughCircles()**方法。
使用这三个方法前,都要
相关内容
- Python语法学习之进程的创建与常用方法详解_python_
- 基于PyQt5制作一个群发邮件工具_python_
- Python&Matlab实现樱花的绘制_python_
- Python OpenCV形态学运算示例详解_python_
- 4种方法python批量修改替换列表中元素_python_
- Python+OpenCV实现图片中的圆形检测_python_
- Python中文分词库jieba(结巴分词)详细使用介绍_python_
- 基于Python实现对比Exce的工具_python_
- pytorch分类模型绘制混淆矩阵以及可视化详解_python_
- Python OpenCV之常用滤波器使用详解_python_
