opencv-python 4.9.1. 轮廓:入门

什么是轮廓?

轮廓可以简单地解释为连接所有具有相同的颜色或强度的连续点(沿着边界)的曲线。轮廓是形状分析和物体检测和识别的很有用的工具。

  • 为了更好的准确性,使用二进制图像,因此,在找到轮廓之前,应用阈值或canny边缘检测。
  • 从OpenCV 3.2开始,findContours()不再修改源图像,而是将修改后的图像作为三个返回参数中的第一个返回。
  • 在OpenCV中,找到轮廓就像从黑色背景中找到白色物体。所以请记住,要找到的对象应该是白色,背景应该是黑色。

contours,hierarchy=cv.findContours(image,mode,method)
cv.findContours函数中有三个参数, 第一个是源图像,第二个是轮廓检索模式,第三个是轮廓逼近方法。

  • image:源图像
  • mode:轮廓提取模式
    • cv.RETR_EXTERNAL 只提取外部轮廓
    • cv.RETR_LIST 提取所有轮廓,不包含轮廓间的层次关系
    • cv.RETR_CCOMP 提取所有轮廓,包含2层层次关系,顶层是外围边界,底层是内部hole。如果有多层嵌套,仍然按照2层组织。
    • cv.RETR_TREE 按照完整的层次关系组织
    • cv.RETR_FLOODFILL
  • method:轮廓近似方法
    • cv.CHAIN_APPROX_NONE 存储所有的边间点,不管是垂直方向、水平方向或者对角线方向
    • cv.CHAIN_APPROX_SIMPLE 垂直方向、水平方向或对角线方向只保留终点,比如一个长方形就只包含4个顶点
    • cv.CHAIN_APPROX_TC89_L1 使用teh-Chini近似算法
    • cv.CHAIN_APPROX_TC89_KCOS 使用teh-Chini近似算法

它输出轮廓和层次结构。

  • contours是图像中所有轮廓的Python列表,是由n个轮廓组成的list,每个轮廓是一个numpy数组,它的shape为(m,1,2),m为轮廓构成的像素的个数,每个点有2个数值,分别为x和y坐标。
  • hierarchy的shape为(1,n,4),n对应contours的个数n,所以要访问第i个轮廓的hierarchy时用hierarchy[0][i]表示。每个hierarchy的元素有4个值组成,依次为next,previous,first child和parent,表示下一个节点,上一个节点,第一个子节点,父节点。

如何绘制轮廓?

要绘制轮廓,可以使用cv.drawContours函数。如果图像有边界点,它也可以用于绘制任何形状。
drawContours(image,contours,contourIdx,color[,thickness[,lineType[,hierarchy[,maxLevel[,offset]]]]])->image
参数含义:

  • image:源图像,调用后会修改源图像。
  • contours:轮廓列表,一般传入findContours()找到的边框。
  • contourIdx:contours的索引,也就是要表示的第几个边框,如果要绘制所有的边框,设置为负数即可。
  • color:颜色,bgr三个参数构成的tuple。
  • thickness:边框的宽度。
  • lineType:边界连线类型。
  • hierarchy:依赖maxLevel使用,如果maxLevel设置为1和2时用到该参数,
  • maxLevel:
  • offset:边框偏移位置, offset=(10,10)

1.一次性绘制所有轮廓, 可以将contourIdx设置为-1,

import cv2 as cv

img = cv.imread(r'C:\Users\yuyalong\Pictures\Saved Pictures\rectangle.jpg')

imgray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
ret, thresh = cv.threshold(imgray, 127, 255, 0)

# cv.CHAIN_APPROX_SIMPLE 获取边界的端点
contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
print(99, len(contours))

res1 = cv.drawContours(img, contours, -1, (0, 255, 0), 3)

cv.imshow('res1', res1)
cv.waitKey(0)

image

2.绘制指定区域的边界1

import cv2 as cv

img = cv.imread(r'C:\Users\yuyalong\Pictures\Saved Pictures\rectangle.jpg')

imgray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
ret, thresh = cv.threshold(imgray, 127, 255, 0)

# cv.CHAIN_APPROX_SIMPLE 获取边界的端点
contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
print(99, len(contours))

# 获取最里边区域的边界
cnt = contours[2]

res1 = cv.drawContours(img, cnt, -1, (0, 255, 0), 3)

cv.imshow('res1', res1)
cv.waitKey(0)

image

2.绘制指定区域的边界2

import cv2 as cv

img = cv.imread(r'C:\Users\yuyalong\Pictures\Saved Pictures\rectangle.jpg')

imgray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
ret, thresh = cv.threshold(imgray, 127, 255, 0)

# cv.CHAIN_APPROX_SIMPLE 获取边界的端点
contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
print(99, len(contours))

# 获取中间区域的边界
cnt = contours[1]

res1 = cv.drawContours(img, cnt, -1, (0, 255, 0), 3)

cv.imshow('res1', res1)
cv.waitKey(0)

image

2.绘制指定区域的边界3

import cv2 as cv

img = cv.imread(r'C:\Users\yuyalong\Pictures\Saved Pictures\rectangle.jpg')

imgray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
ret, thresh = cv.threshold(imgray, 127, 255, 0)

# cv.CHAIN_APPROX_SIMPLE 获取边界的端点
contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
print(99, len(contours))

# 获取最外边区域的边界
cnt = contours[0]

res1 = cv.drawContours(img, cnt, -1, (0, 255, 0), 3)

cv.imshow('res1', res1)
cv.waitKey(0)

image

posted @ 2023-03-31 15:06  一枚码农  阅读(181)  评论(0编辑  收藏  举报