轮廓查找
简述
轮廓即是以某种方式表示图像中的曲线的点的列表,可以把轮廓理解为一个有序的点集。
OpenCV函数原型
cv2.findContours(img, mode, method)
参数解释
img | 输入的原图片 |
mode | 轮廓检索模式 RETR_EXTERNAL :只检索最外面的轮廓; RETR_LIST:检索所有的轮廓,并将其保存到一条链表当中; RETR_CCOMP:检索所有的轮廓,并将他们组织为两层:顶层是各部分的外部边界,第二层是空洞的边界; RETR_TREE:检索所有的轮廓,并重构嵌套轮廓的整个层次; |
method | 轮廓逼近模式 CHAIN_APPROX_NONE:以Freeman链码的方式输出轮廓,所有其他方法输出多边形(顶点的序列)。 CHAIN_APPROX_SIMPLE:压缩水平的、垂直的和斜的部分,也就是,函数只保留他们的终点部分。 |
轮廓绘制
OpenCV函数原型
cv2.drawContours(image, contours, contourIdx, color, thickness)
参数解释
image | 输入的原图片 |
contours | 已经查找出的多个轮廓 |
contourldx | 需要绘制的轮廓的索引 |
color | 绘制的颜色 |
thickness | 绘制的粗细,如果该参数小于0,则表示填充整个轮廓内的区域 |
注意:该函数会直接在图片上进行绘制,所以一般要将原图复制一份,再进行绘制
轮廓特征
令cnt为图像中的一个轮廓
binary, contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_NONE)
cnt = contours[8]
面积
cv2.contourArea(cnt)
周长
cv2.arcLength(cnt, True)
注意:第二个参数指定图形是否闭环,如果是则为True, 否则只是一条曲线。
轮廓近似
OpenCV函数原型
cv2.approxPolyDP(curve, epsilon, closed)
参数解释
curve | 需要进行近似的轮廓 |
epsilon | 指定近似精度的参数ε,这是原始曲线与其近似值之间的最大距离。参数越小,两直线越接近 |
closed | 若为true,曲线第一个点与最后一个点连接形成闭合曲线,若为false,曲线不闭合。 |
轮廓的外接矩形
OpenCV函数原型
cv2.rectangle(img, (x, y), (x + w, y + h), color, thickness)
参数解释
img | 进行绘制的图片 |
x,y | 轮廓左上角的坐标 |
w,h | 轮廓的宽度和高度 |
color | 轮廓颜色 |
thickness | 轮廓线条的粗细 |
关于x,y,w,h的位置关系
x,y ------
| |
| |
| |
--------x+w,y+h
代码演示
import cv2 as cv
import numpy as np
# 读入图片
src = cv.imread('contours.png')
# 转换成灰度图
gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
# 二值化
ret, thresh = cv.threshold(gray, 129, 255, cv.THRESH_BINARY)
# 查找轮廓
# binary-二值化结果,contours-轮廓信息,hierarchy-层级
binary, contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_NONE)
# 显示轮廓,tmp为黑色的背景图
tmp = np.zeros(src.shape, np.uint8)
res = cv.drawContours(tmp, contours, -1, (250, 255, 255), 1)
cv.imshow('Allcontours', res)
cnt = contours[8]
tmp2 = np.zeros(src.shape, np.uint8)
res2 = cv.drawContours(tmp2, cnt, -1, (250, 255, 255), 2)
cv.imshow('cnt', res2)
# 轮廓特征
# 面积
print(cv.contourArea(cnt))
# 周长,第二个参数指定图形是否闭环,如果是则为True, 否则只是一条曲线.
print(cv.arcLength(cnt, True))
# 轮廓近似,epsilon数值越小,越近似
epsilon = 0.08 * cv.arcLength(cnt, True)
approx = cv.approxPolyDP(cnt, epsilon, True)
tmp2 = np.zeros(src.shape, np.uint8)
# 注意,这里approx要加中括号
res3 = cv.drawContours(tmp2, [approx], -1, (250, 250, 255), 1)
cv.imshow('approx', res3)
# 外接图形
x, y, w, h = cv.boundingRect(cnt)
# 直接在图片上进行绘制,所以一般要将原图复制一份,再进行绘制
tmp3 = src.copy()
res4 = cv.rectangle(tmp3, (x, y), (x + w, y + h), (0, 0, 255), 2)
cv.imshow('rectangle', res4)
cv.waitKey()
cv.destroyAllWindows()
运行结果