OpenCV_08轮廓查找

前言:总纲请看《计算机视觉学习路》

图像轮廓

定义:具有相同颜色强度连续点的曲线

轮廓的作用:

  1. 用于图形分析
  2. 物体识别与检测

为了检测的准确性,需要先对图像进行二值化或Canny操作

画轮廓时会修改输入的图像

查找轮廓:

findContours(img , mode , ApproximationMode...) 

mode : 查找到轮廓后,返回什么样的形式?

        RETR_EXTERNAL = 0 表示只检测外轮廓

        RETR_LIST = 1  检测的轮廓不建立等级关系

        RETR_CCOMP = 2  每层最多两级

        RETR_TREE = 3  按树形存储轮廓,从大到小返回轮廓,常用

ApproximationMode : 近似模式

        CHAIN_APPROX_NONE  保存所有轮廓上的点

        CHAIN_APPROX_SIMPLE  只保存角点

返回值:contours(查找到的轮廓列表)和 hierarchy(轮廓有没有前后关系)

 绘制轮廓:

drawContours(img , contours , contourIdx , color, thickness...)

contourIdx : 想要绘制的轮廓的索引   -1表示所有轮廓

thickness    线宽,-1是全部填充

import cv2
import numpy as np

img = cv2.imread('../img/contours1.jpeg')
# 转变成单通道
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 二值化
ret, bin = cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY)
cv2.imshow('bin',bin)
# 轮廓查找
contours,hierarchy = cv2.findContours(bin,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

print(contours)  # 打印出找到的角点

# 绘制轮廓,可以在bin上绘制,也可以在img绘制,需要注意的是img是三通道。bin是单通道
cv2.drawContours(img,contours,-1,(0,0,255),2)
cv2.imshow('contours',img)

cv2.waitKey(0)

 轮廓的面积和周长

contourArea(contour)

arcLength(curve , closed)  # curve就是contours , closed=true闭合,false不闭合

比如想查看最大的轮廓的周长和面积:

# 计算面积
area = cv2.contourArea(contours[0])
print('area = %d'% area)

# 计算周长
len = cv2.arcLength(contours[0],True)
print('len = %d'%len)

 

多边形逼近与凸包

approxPolyDP(curve , epsilon , closed)

curve:轮廓  epsilon : 精度  closed是否是闭合

convexHull(points , clockwise..)

points轮廓  clockwise = true顺时针, false逆时针

 如下图,红色边界是findConturs绘制的,绿色的线是多边形逼近绘制的,可以用较少的点绘制出大体轮廓,减少计算量,提高精度epsilon的值可以增加点,使边沿拟合更平滑

下面这个绿色的曲线是凸包 

 

总体代码如下:

import cv2
import numpy as np


# 定义一个函数,连接appros里面的点
def drawShape(src, points):
    i = 0
    while i < len(points):
        if i == len(points) - 1:
            x, y = points[i][0]
            x1, y1 = points[0][0]
            cv2.line(src, (x, y), (x1, y1), (0, 255, 0), 2)
        else:
            x, y = points[i][0]
            x1, y1 = points[i + 1][0]
            cv2.line(src, (x, y), (x1, y1), (0, 255, 0), 2)
        i = i + 1


img = cv2.imread('../img/hand.png')
# 转变成单通道
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 二值化
ret, bin = cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY)
cv2.imshow('img', img)
# 轮廓查找
contours, hierarchy = cv2.findContours(bin, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

print(contours)  # 打印出找到的角点

# 绘制轮廓,可以在bin上绘制,也可以在img绘制,需要注意的是img是三通道。bin是单通道
cv2.drawContours(img, contours, -1, (0, 0, 255), 2)

# 多边形逼近
e = 20  # 精度
appros = cv2.approxPolyDP(contours[0], e, True)
drawShape(img, appros)
print('appros=',appros)

# 凸包
hull = cv2.convexHull(contours[0])
drawShape(img,hull)

cv2.imshow('result', img)

cv2.waitKey(0)

外接矩形

最小外接矩形

minAreaRect(points)   # 返回值:RotateRect 带有角度的矩形

最大外接矩形

boundingRect(array)  # 返回Rect

 如下图,红色是最小外接矩形,带有角度,蓝色是最大外接矩形

import cv2
import numpy as np


# 定义一个函数,连接appros里面的点
def drawShape(src, points):
    i = 0
    while i < len(points):
        if i == len(points) - 1:
            x, y = points[i][0]
            x1, y1 = points[0][0]
            cv2.line(src, (x, y), (x1, y1), (0, 255, 0), 2)
        else:
            x, y = points[i][0]
            x1, y1 = points[i + 1][0]
            cv2.line(src, (x, y), (x1, y1), (0, 255, 0), 2)
        i = i + 1


img = cv2.imread('../img/hello.jpeg')
# 转变成单通道
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 二值化
ret, bin = cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY)
cv2.imshow('img', img)
# 轮廓查找
contours, hierarchy = cv2.findContours(bin, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
print('contours = ', contours)

# 绘制最小外接矩阵
r = cv2.minAreaRect(contours[1])
# 取出r中不包含角度的部分并且转换为int
box = cv2.boxPoints(r)
box = np.int0(box)
cv2.drawContours(img, [box], 0, (0, 0, 255, 3))

# 绘制最大矩形
x, y, w, h = cv2.boundingRect(contours[1])
cv2.rectangle(img, (x, y), (x+w, y+h),(255,0,0))

cv2.imshow('result', img)

cv2.waitKey(0)

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Goafan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值