Opencv+Python笔记(八)轮廓检测

一、轮廓的检测和绘制

轮廓检测有什么作用:
使用轮廓检测可以获得物体的边界,方便在图像中对他们进行定位。

什么是轮廓:
当我们把物体边缘所有的点连接在一起可以获得轮廓。对于特定的轮廓是指那些具有相同颜色和亮度的边界点像素。

调用流程:
(1)读入图像
(2)将读入图像转化为灰度图
(3)对(2)得到的灰度图进行二值化或者Candy边缘检测处理,从而把感兴趣的物体加亮凸显出来以便于使用轮廓检测算法
(4)进行轮廓检测(使用 findContours()函数来检测图像中的所有的轮廓)
(5)在原图中显示轮廓(使用 drawContours()函数来在原图上显示轮廓)

1.读入图像

img = cv2.imread('img.jpg')

2.将读入图像转化为灰度图

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

3.对灰度图进行二值化 图像的阈值化处理

ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)

4.进行轮廓检测

Opencv API:

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

参数:
contours:检测到的轮廓,每个轮廓是由一些点构成的向量组成
hierarchy:记录轮廓之间的层级关系,四个维度分别代表:同级后一个轮廓的序号、同级上一个轮廓的序号、第一个孩子序号,父亲序号
mode:检测轮廓的层级关系排列规则:(1)RETR_EXTERNAL:仅仅检测外圈轮廓;(2)RETR_LIST:检测所有轮廓,但是没有层级关系;(3)RETR_CCOMP:仅仅两层包含关系,即只有外层和内层,假设有夹层,那么夹层也算外层,只要某个轮廓还包含有轮廓,都算外部轮廓;(4)RETR_TREE:检测所有的轮廓,并存储非常完整的层级关系,一般都用这个 把所有轮廓都存下来以后用得到哪个就拿哪个
method:轮廓点的存储方式:(1)CHAIN_APPROX_NONE:将要存储的轮廓整个存储下来;(2)HAIN_APPROX_SIMPLE:该算法对水平、垂直以及对角线方向的片段轮廓进行了省略,仅仅保存了他们的端点。这意味着所有直线上的点都会消失,只保存端点信息,比如矩形就只保存四个顶点。这种模式先处理速度要比CHAIN_APPROX_NONE更快,所需要的内存更少,因此执行时间就会被节省。

5.在原图中显示轮廓

Opencv API:

img = cv2.drawContours(img, contours, index, color, thickness, linetype)

参数:
contours:是list类型的数组,里面存储了轮廓数组包含所有存储的轮廓
contourIdx:从上面的轮廓list中取出哪一个画出来,-1代表全部
color:绘制轮廓所用颜色
thickness:线条粗细,-1代表填充式画轮廓,整个轮廓内部被指定颜色填充
lineType:线条类型,虚线、实线之类的,默认实线

注意:
绘制轮廓钱要做一个原图的副本,图片传入绘制轮廓函数后,会在该图片上画出轮廓从而使得该图片无法使用

二、轮廓层级关系

多数情况下,如果一个形状中包含有其它形状,我们一般认为外边形状是出内部形状的父亲。
在这里插入图片描述

其中4a为4的内侧轮廓,5a为5的内侧轮廓
OpenCV 用 [Next, Previous, First_Child, Parent] 表示轮廓层级关系信息。即返回值hierarchy。

next:同层级的下一个轮廓,若不存在则为-1
previous:同层级的上一个轮廓,若不存在则为-1
first_child:该轮廓的第一个孩子结点,不存在则为-1
parent:该轮廓的父亲结点,不存在则为-1

然后来解释一下mode的四个轮廓获取方法

1.RET_LIST

该轮廓获取方法不创建任何父子关系,直接存储,如图:
在这里插入图片描述

2.RETR_EXTERNAL

该轮廓检测方法仅仅存储父亲轮廓,子孙轮廓被忽略,如图:
在这里插入图片描述

3. RETR_CCOMP

该轮廓检测算法将轮廓赋值为 2 个级别。所有的外部轮廓都是层级1,所有的内部轮廓都是层级2; 如果内部还有其他内部层级,循环使用级别1 和 2。

如图:
在这里插入图片描述

4.RETR_TREE

RETR_TREE获得所有的轮廓并检索所有轮廓并创建一个家族,告诉谁是儿子,谁是孙子,谁是父亲,谁是祖父,如图:
在这里插入图片描述


代码:

ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)  #检测轮廓
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

draw_img = img.copy()
res = cv2.drawContours(draw_img, contours, -1, (255, 0, 0), 2)  #绘制轮廓

titles = ['origin', 'contours']
imgs = [img, res]
plt_show(2, 1, 2, titles, imgs)

在这里插入图片描述

三、轮廓特征

1.轮廓周长

Opencv API:

leng = cv2.arcLength(cnt, isClosed)  

参数:
cnt:所要检测周长的轮廓
isClosed:标志位,若为True表示轮廓闭合,若为False表示轮廓不闭合

2.轮廓面积

Opencv API:

area = cv2.contourArea(cnt)

3.轮廓近似

Opencv API:

cv2.approxPolyDP(curve, epsion, isClosed)

参数
curve 轮廓
epsion 原始轮廓和近似多边形之间的最大误差δ值 精度越高越逼近原始轮廓
isClosed 布尔标志,如果是True,表示多边形是闭合的

代码:

cnt = contours[2]
epsilon = 0.1 * cv2.arcLength(cnt, True)
approx = cv2.approxPolyDP(cnt, epsilon, True)

draw_img = img.copy()
res = cv2.drawContours(draw_img, [approx], -1, (255, 0, 0), 2)
cv_show('res', res)

在这里插入图片描述

  • 3
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
你可以使用OpenCV和Turtle库来画图片的轮廓。首先,你需要使用OpenCV加载图像并进行边缘检测,然后使用Turtle库来绘制检测到的边缘。 下面是一个示例代码,展示了如何使用OpenCV和Turtle来画图片的轮廓: ```python import cv2 import turtle # 加载图像并进行边缘检测 image = cv2.imread('image.jpg') gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) edges = cv2.Canny(gray, 50, 150) # 创建Turtle画布 screen = turtle.Screen() screen.setup(image.shape[1], image.shape[0]) screen.setworldcoordinates(0, 0, image.shape[1], image.shape[0]) # 创建Turtle画笔 pen = turtle.Turtle() pen.speed(0) pen.hideturtle() # 绘制边缘 for y in range(edges.shape[0]): for x in range(edges.shape[1]): if edges[y, x] > 0: pen.penup() pen.goto(x, edges.shape[0] - y) pen.pendown() pen.forward(1) # 关闭窗口 turtle.done() cv2.destroyAllWindows() ``` 在上述代码中,你需要将'image.jpg'替换为你想要处理的图像文件路径。该代码会加载图像,将其转化为灰度图像,然后使用Canny边缘检测算法检测边缘。接下来,我们创建一个Turtle画布,并设置其大小与图像一致。然后,我们创建一个Turtle画笔,设置绘制速度并隐藏画笔。最后,我们遍历边缘图像的每个像素,如果像素值大于0,则将画笔移动到该位置并绘制1个像素的线段。最后,我们关闭Turtle窗口并销毁OpenCV的窗口。 希望这个示例能帮到你!如有任何问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值